Add explicit guidance to resolve raw API IDs to human-readable names before
user display. Affected tools: get_tasks, get_lists, get_activities,
get_wall_posts, get_members, get_circles, get_categories, get_meal_plan.
Add general usability rule to CLAUDE.md implementation section: never present
raw numeric/metaIDs to the user. No breaking changes; docstring improvements only.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add 38 unit tests covering fw_client, recipes, lists, and server modules
- Test error handling: top-level ex/un, nested a00.un.un/a00.ex.ex, successful responses
- Test ingredients_parsed parser: newlines, empty lines, commas, headings
- Test list name translation: SYS-CAT-SHOPPINGLIST, SYS-CAT-TODOS, unknown names
- Test date validation: ISO YYYY-MM-DD format enforcement
- Test error response helper: JSON format, Unicode, special characters
- All tests use unittest.mock (stdlib), no external mocking libraries
- No API calls — all HTTP interactions mocked
- Framework: pytest with asyncio support
- Run: uv run pytest tests/test_unit.py -v
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add get_wall_posts: read recent wall posts with like/comment counts
- Add create_wall_post: publish new status posts to the wall
- Add add_comment: add comments to wall posts and activities
- like_post already supports both wall posts and activities (v1.2.0)
- Update README.md with new Wall & Activities section
- Update CLAUDE.md with v1.3.0 and tool reorganization
- Update CHANGELOG.md with v1.3.0 release notes
- Add wallpublish and walladdComment documentation to SPEC.md
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Exhaustive FW_DEBUG investigation on both Free and Premium accounts
confirmed that taskupdate2 silently ignores all reminder fields regardless
of encoding (flat, JSON-string, PHP-bracket, all variants). Alternative
endpoints (tasksetalert etc.) are unregistered. Root cause: mobile app
Service Worker transforms reminder requests in ways not reproducible via
direct API calls. Reminders remain read-only. Recurrency write confirmed
working (flat encoding). Docs updated with full investigation findings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
FiZ Ai() encoder does not support nested objects — recurrencyDescriptor
and reminder fields must be top-level params (recurrency=WEEKLY, not
recurrencyDescriptor={recurrency:WEEKLY}). Same fix for reminder fields.
SPEC.md and CLAUDE.md updated to document the flat encoding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**Critical:**
- Add IMPORTANT confirmation lines to toggle_task and like_post docstrings
- Add [project.urls] section with Gitea repository link to pyproject.toml
**Medium:**
- Fix .gitignore: test_*.py recursive pattern (remove leading slash)
- Add exception logging to clear_list() for failed deletions
- Update get_categories() docstring: clarify custom vs system category locale behavior
- Add Versioning Policy section to CHANGELOG.md
**Minor:**
- Fix CLI help text (remove "(read-only)" qualifier)
- Add language note to CLAUDE.md (German file, English code)
- Create tests/README.md with integration test documentation
- Update version to 1.0.1 in pyproject.toml
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Move integration tests to tests/; fix .gitignore to scope root-only
- Remove tracked debug artefacts (probe2_stderr/stdout.txt)
- __init__.py: version via importlib.metadata; export create_server in __all__
- server.py: unified JSON error format {"error":"..."} for all tools
- server.py: date validation (YYYY-MM-DD) for all meal-plan tools
- server.py: clear_list reports partial failures (failed_count, failed_ids)
- server.py: -> str annotations on get_circles, get_tasks, get_activities
- server.py: document TODO:94 as known limitation (no name in sortingIndexByTaskList)
- server.py: date validation also added to get_meal_plan
- Add LICENSE (MIT, Marcus van Elst)
- Add CHANGELOG.md (Keep a Changelog, v0.1.0–v1.0.0)
- README.md: restructured by use case; 🔒 marks write tools
- CLAUDE.md: update to v1.0.0 state; condense roadmap history
- SPEC.md: add version stamp
- pyproject.toml: version 1.0.0 (single source of truth)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documentation-only release explaining the isRecipe flag:
- isRecipe='true': Real recipes in the recipe box
- isRecipe='false': Free-text stubs from meal planner OR old imported recipes
never properly tagged (e.g. recipe/16282169_7055369 'Elsässer Flammkuchen')
get_recipe_box filters strictly on isRecipe='true' — consistent with Family Wall app.
Updated SPEC.md, README.md, CLAUDE.md with v0.11.8.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Removed reference/mcp-synology from git index (was accidentally committed as embedded repo).
Added reference/ to .gitignore to prevent future issues.
This fixes the 'git submodule update' error when installing via uv tool.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- New tool get_recipe_box: filtered version of get_recipes returning only real recipes (isRecipe=true), excluding stubs created for free-text meal entries
- Parser fix: ingredients_parsed now generated from free-text ingredients field instead of API's ingredientsList which has parser bug on comma+space (e.g. '1, 5g' breaks)
- Updated SPEC.md with parser bug documentation
- Updated version to 0.11.7 in __init__.py and pyproject.toml
- Updated .gitignore to exclude debug/test scripts
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Deletes all tasks in a list within a single authenticated session,
avoiding N×(login+logout) overhead — Login once, N×delete, logout once.
Supports only_open=True to keep completed tasks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New write tool using mpmealput endpoint to create meal/ note entries
with optional free-text and serving count. Response structure verified
from JS-bundle (Sg class); a00.r.r is a plain object (unlike mpcreate).
Structured output matches get_meal_plan meal entry format.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reuses the existing metadelete endpoint (already used for tasks and
recipes). Validates that entry_id starts with 'dish/' or 'meal/' before
calling the API. SPEC.md updated to reflect metadelete's broader scope.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Map verified mpcreate response to same field layout as get_meal_plan.
Key difference: a00.r.r is an array (take [0]) unlike mpcreateByRecipeId
which returns a plain object. is_from_recipe_box is always false.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New write tool using mpcreate endpoint for free-text meal entries
(no recipe link). Parameters verified from JS-bundle. Returns raw
response pending production verification; structured output → v0.11.3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Map verified mpcreateByRecipeId response (a00.r.r dish object) to the
same field layout as get_meal_plan entries. is_from_recipe_box is always
true since this tool only creates recipe-box entries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New write tool using mpcreateByRecipeId endpoint (parameters verified
from JS-bundle). Returns raw response pending production verification;
structured output planned for v0.11.1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Join recipeList[] from API response as a lookup table: isRecipe="true"
means a real recipe from the recipe box, "false" is a free-text stub.
Dish entries get is_from_recipe_box=true/false; meal entries get null.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- dish entries (list[]) and meal entries (mealList[]) are now merged and
returned together, sorted by date then type (BREAKFAST→LUNCH→SNACK→DINNER)
- New output fields: note (free-text, meal entries only) and serves (int)
- SPEC.md: document verified mealList[] response structure
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Implement get_meal_plan() tool for accessing Family Wall meal planner
- Parameters: date_from, date_to (ISO 8601 format)
- Returns raw JSON for initial verification via FW_DEBUG=1
- Response structure to be verified in first deployment
- Add Meal Planner API section to SPEC.md documenting mplistinterval and other endpoints
- Update version to 0.10.0 in __init__.py and pyproject.toml
- Update README.md and CLAUDE.md with tool info and roadmap
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
API uses reminderUnit/reminderValue keys, not unit/value.
value=0 with a present unit is a valid reminder (at event time) and must not be nulled out.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- create_list now accepts list_type="OTHER" (previously rejected)
- get_tasks logs unknown task fields to stderr when FW_DEBUG=1 (preparation for repeating-task field discovery)
- README, CLAUDE.md, version bumped to 0.8.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Investigated toggle_recipe_favorite (v0.8.3 goal):
- mpstar: not registered server-side (Service Worker intercepts it)
- metamood: registered, accepts recipe IDs, but self-reaction restriction
prevents state changes on own recipes (same as wallmood for own posts)
- isFavorite cannot be set via any discovered endpoint
Added to SPEC.md:
- metamood endpoint spec with known limitations (FiZClassId 8004, self-reaction)
- mpstar investigation summary with unblock requirements
- mpstar / isFavorite added to Offene Punkte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement v0.8.2: When get_lists() is called without a scope parameter,
it now fetches lists from ALL circles instead of only the primary circle.
Implementation:
- Login once, call famlistfamily to get all circle IDs
- For each circle, call taskgettasklists(scope=<circle_id>)
- Merge results and return all lists with circle_id field
All tests passed: test_multi circle creation, list creation in secondary
circle, get_lists() without scope returns lists from both circles.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Bug 1: update_recipe(category_ids=[]) didn't remove categories
- Fixed: send empty string "" to API to remove all categories
- Non-empty lists continue to work as expected
- Verified via FW_DEBUG=1 testing
Bug 2: get_recipe_categories() only showed used categories
- Fixed: always return 5 free-tier standard categories
- Added _get_family_id() helper to extract family ID
- Now returns all available category IDs even on new accounts
- Standard categories: category/<familyId>_2 through _6
Version: 0.8.0 → 0.8.1
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- New tool: get_recipe_categories() lists available recipe category IDs
- Enhanced create_recipe and update_recipe with optional category_ids parameter
- Extended get_recipe and get_recipes to include category_ids in response
- Updated parse_recipe_full() to extract recipeCategoryIdList from API response
- Extended build_create_params() and build_update_params() to handle category_ids
Recipe categories are managed via recipe.recipeCategoryIdList in mprecipeput API.
Categories are represented as a list of category IDs (e.g. ["category/23431854_2"]).
No direct API endpoint exists for listing all categories; they are discovered from
existing recipes or must be known in advance.
Version: 0.7.5 → 0.8.0
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Adds isFirstFamily check to update_circle — mirrors the same guard
already present in delete_circle. Attempting to rename the primary
circle now returns a clear error instead of silently renaming it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements accupdatefamily endpoint (verified via FW_DEBUG=1):
- Parameter 'scope' targets any circle (primary or secondary)
- Without scope: renames the primary circle (API default)
- Server always capitalises the first letter of the new name
- Verifies circle existence via famlistfamily in same session
- Response a00.r.r = full circle object with updated name
Also corrects SPEC.md: accupdatefamily with scope= works for any
circle, not just the primary (previous note was incomplete).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements taskupdatelist endpoint (verified via FW_DEBUG=1):
- Parameter 'metaId' (not 'id') identifies the list
- Partial update: only provided fields (name/color/emoji) are changed
- Reads rights.canUpdate before calling the endpoint (single session)
- System lists (canUpdate != 'true') are rejected with a clear error
- Scope derived from list metaId for secondary-circle support
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements `delete_circle(circle_id)` using the verified `adminwipefamily`
endpoint. Protects the primary circle via `isFirstFamily` check. Probe
circles family/23447370 and family/23447378 cleaned up during testing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_lists(scope): API scope parameter now used server-side; accepts circle
metaId ("family/XXXX") or circle name; returns circle_id field per list
- create_list(circle_id): new optional param; passes as API scope param
- delete_list: derives circle from list metaId and passes scope for
secondary-circle lists
- Added _circle_id_from_list_id() helper (taskList/FAMNUM_LISTNUM -> family/FAMNUM)
- SPEC.md: documented scope param for taskgettasklists, taskcreatelist, taskdeletelist
- Verified: familyId/circleId/id params ignored by API, only scope works
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- acccreatefamily endpoint creates a new circle (returns numeric ID)
- accinvite endpoint invites new users by email (familyId, identifier, role, firstname)
- fw_client now detects a00.ex errors (was only checking a00.un before)
- New modules/circles.py with FamilyRoleTypeEnum constants
- SPEC.md updated with acccreatefamily, accinvite, accupdatefamily docs
- Note: circle deletion not supported by FW API (metadelete → "delete not supported")
- Note: accinvite only works for new (non-existing) FW accounts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends the category_id parameter docstring with an explicit instruction
to always call get_categories first and assign the most fitting category
to every shopping list item, plus a concrete German-category mapping.
Uncategorized items are harder to find in the store.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug fix: literal backslash-n sequences in ingredients/instructions are now
converted to real newline characters before sending to the API, so the server
correctly splits ingredient lines into ingredientsList[].
New tool: update_recipe — partial update via mprecipeput with recipe.metaId;
fetches current recipe in the same session to verify can_update and supply
name fallback. Verified: recipe.metaId triggers update (not create).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 4 new MCP tools for the Family Wall recipe box:
- get_recipes: list all family recipes via metasync id='recipe'
- get_recipe: fetch full recipe detail by id (filters from metasync response)
- create_recipe: create a new recipe via mprecipeput (params use 'recipe.' prefix)
- delete_recipe: delete a recipe via metadelete (same endpoint as tasks)
Verified endpoints and parameter names via FW_DEBUG=1 probe scripts.
All 4 tools pass the create → read → get_single → delete integration test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents the preferred format for quantities in shopping list tasks:
item name first, quantity in parentheses at the end.
Examples: "Äpfel (5x)", "Hackfleisch (500g)", "Joghurt (Erdbeere, 2x)".
No functional code changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_lists now includes emoji and color fields per list entry.
create_list response also returns emoji and color from the API.
Field name verification (FW_DEBUG=1, 2026-04-16):
- emoji: API returns "" when unset -> normalised to null
- color: API omits key when unset -> normalised to null
- Both fields present in taskgettasklists and taskcreatelist responses
SPEC.md: taskgettasklists documented with full response structure
and emoji/color normalisation notes.
taskcreatelist response updated with emoji + color fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two new MCP tools:
- create_list(name, list_type, shared_to_all, color, emoji)
POST taskcreatelist; returns full list object incl. metaId
- delete_list(list_id) – with canDelete safety guard
POST taskdeletelist; param 'id' (same pattern as metadelete)
Both endpoints verified via FW_DEBUG=1 on 2026-04-16.
SPEC.md and CLAUDE.md updated with verified parameter names
and response structures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Family Wall API (FiZ framework) uses the special string "\$empty"
to clear optional date fields. Sending dueDate=\$empty to taskupdate2
reliably removes the due date (verified via direct API probing).
- update_task(clear_due_date=True) now sends dueDate=\$empty instead
of returning an error
- Remove the "not supported" limitation message from the docstring
- Update SPEC.md, README.md, CLAUDE.md to document the discovery
- Bump version to 0.4.16
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fw_client: detect nested a00.un errors (previously silent-failed as success)
- update_task: add clear_due_date=True parameter that returns a clear error
explaining the Family Wall API cannot clear dueDate once set
- SPEC.md: document all tested clearing candidates and their API responses,
add Fehlerstruktur-Varianten section
- Verified: dueDate cannot be removed via any form-encoded value; all invalid
date strings are rejected via a00.un.un (silently swallowed before this fix)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>