48 Commits

Author SHA1 Message Date
marcus 5671d70000 docs(usability): enforce ID→name resolution in all tool docstrings (v1.4.3)
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>
2026-04-18 00:10:26 +02:00
marcus 0e7c4da362 feat(wall-posts): add wall post reading/writing with comments (v1.3.0)
- 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>
2026-04-17 23:19:37 +02:00
marcus 70c2f61f05 feat(like_post): add unlike support via remove.0 array dot-notation (v1.2.0)
Unlike is now implemented: add=\$empty, remove.0=STAR (verified via Network Interceptor).
Adds optional mood parameter (default STAR). Removes the early-return error path for like=False.
SPEC.md, CLAUDE.md, CHANGELOG.md updated; Unlike offene Punkte entry removed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 22:57:47 +02:00
marcus 4c1e4e2c23 feat(tasks): support reminder write via dot-notation (v1.2.0)
- Add reminder_unit, reminder_value to create_task
- Add reminder_unit, reminder_value, clear_reminder to update_task
- Wire format verified: reminder.reminderUnit / .reminderValue /
  .reminderType (SNOOZE=active, NONE=clear) / .localId (optional)
- Valid units: MINUTE, HOUR, DAY (WEEK rejected by enum decoder)
- Clear requires full inactive block; partial updates reject with
  "task reminder invalid"
- Flat top-level keys, JSON string and bracket notation are silently
  ignored by the server — confirmed via isolated fuzz per variant
- Update SPEC.md, CLAUDE.md, README.md, CHANGELOG.md
- Remove outdated "not supported" warning in update_task docstring
2026-04-17 22:41:16 +02:00
marcus d6d8d40305 fix(tasks): remove non-functional reminder write params (v1.1.2)
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>
2026-04-17 21:35:23 +02:00
marcus 08ee5fb84a fix(tasks): send recurrency/reminder as flat top-level params (v1.1.1)
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>
2026-04-17 21:18:58 +02:00
marcus f5eb0a46c8 feat(tasks): add recurrency and reminder write support to update_task (v1.1.0)
Verified parameters from JS-Bundle xb-Encoder/fc-Encoder now wired up:
recurrencyDescriptor (recurrency, recurrencyInterval, rrule) and reminder
(reminderUnit, reminderValue). Adds clear_recurrency and clear_reminder flags.
SPEC.md, CHANGELOG.md, CLAUDE.md updated accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 21:15:05 +02:00
marcus 3e021bf01a chore(v1.0.1): opus review findings — docstring confirmation patterns, pyproject.urls, gitignore fix, logging
**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>
2026-04-17 17:28:22 +02:00
marcus bdf9e3c59e chore: finalize v1.0.0 — cleanup, unified errors, date validation
- 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>
2026-04-17 15:30:26 +02:00
marcus 0b56ea92bc docs(recipes): document isRecipe-flag behavior in get_recipe_box (v0.11.8)
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>
2026-04-17 14:09:28 +02:00
marcus 5e3b7e08a3 feat(recipes): add get_recipe_box + parser-fix ingredients_parsed (v0.11.7)
- 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>
2026-04-17 13:55:05 +02:00
marcus 343e8eeb58 feat(tasks): add clear_list tool (v0.11.6)
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>
2026-04-17 13:35:25 +02:00
marcus 3f20b6eda3 feat(meal-planner): add add_meal_note tool (v0.11.5)
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>
2026-04-17 12:33:31 +02:00
marcus e0054116cb feat(meal-planner): add delete_meal_plan_entry tool (v0.11.4)
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>
2026-04-17 12:28:41 +02:00
marcus a26a637c83 feat(meal-planner): structured output for add_meal_to_meal_plan (v0.11.3)
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>
2026-04-17 12:24:48 +02:00
marcus 0ed9d62e4a feat(meal-planner): add add_meal_to_meal_plan tool (v0.11.2)
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>
2026-04-17 12:10:20 +02:00
marcus d344251796 feat(meal-planner): structured output for add_recipe_to_meal_plan (v0.11.1)
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>
2026-04-17 11:52:16 +02:00
marcus e7e242151f feat(meal-planner): add add_recipe_to_meal_plan tool (v0.11.0)
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>
2026-04-17 11:45:28 +02:00
marcus bf086a4f84 feat(meal-planner): add is_from_recipe_box field to get_meal_plan (v0.10.3)
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>
2026-04-17 11:31:51 +02:00
marcus 7d912beb5f feat(meal-planner): merge mealList[] into get_meal_plan output (v0.10.2)
- 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>
2026-04-17 11:26:21 +02:00
marcus a7b21c1ede feat(meal-planner): structured output for get_meal_plan (v0.10.1)
- Map mplistinterval response to clean JSON list (id, date, type, name,
  recipe_id, can_update, can_delete) — no more raw dump
- SPEC.md: document verified mplistinterval response structure
- Fix two pre-existing ruff SIM warnings (SIM102, SIM105)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 11:13:22 +02:00
marcus 500ad278a4 feat(meal-planner): add get_meal_plan read-only tool (v0.10.0)
- 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>
2026-04-17 11:03:48 +02:00
marcus 935a159331 fix(tasks): correct reminder field mapping in get_tasks (v0.9.1)
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>
2026-04-17 09:09:00 +02:00
marcus 6d9f358e76 feat(tasks): add recurrency, rrule, reminder fields to get_tasks (v0.9.0)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 09:02:44 +02:00
marcus af2cfc8728 feat: add OTHER list type + FW_DEBUG task-field logging (v0.8.3)
- 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>
2026-04-17 08:06:10 +02:00
marcus 36448e68e0 docs: clean up documentation (v0.8.2)
- Roadmap: v0.8.x mpadditemtolist marked as 'cancelled – Family Wall native'
- CLAUDE.md: add recipe.recipeCategoryIdList and scope params to tables; add mpstar/isFavorite limitation section
- README.md: v0.8.0 → v0.8.2; get_lists clarification (returns all circles without scope); get_recipe_categories standard categories list
- SPEC.md: update recipe categories explanation, taskupdatelist scope param, offene punkte clarification
2026-04-17 07:38:38 +02:00
marcus b15af18606 feat(lists): get_lists() without scope returns all circles (v0.8.2)
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>
2026-04-17 06:40:09 +02:00
marcus 4c60b5b5fa feat(recipes): add recipe categories support (v0.8.0)
- 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>
2026-04-17 06:24:48 +02:00
marcus eb022e2376 fix(circles): protect primary circle from rename in update_circle (v0.7.5)
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>
2026-04-16 21:39:57 +02:00
marcus 02f9d62720 feat(circles): add update_circle tool (v0.7.4)
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>
2026-04-16 21:33:07 +02:00
marcus d144a77662 feat(lists): add update_list tool (v0.7.3)
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>
2026-04-16 20:12:28 +02:00
marcus dc21416a61 feat: add delete_circle tool (v0.7.2)
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>
2026-04-16 18:28:22 +02:00
marcus abb557e96b fix(lists): circle scope support for get_lists, create_list, delete_list (v0.7.1)
- 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>
2026-04-16 18:10:05 +02:00
marcus 2bc03e2165 feat(circles): create_circle + add_member_to_circle (v0.7.0)
- 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>
2026-04-16 17:59:20 +02:00
marcus 498d5781c5 docs(create_task): add category auto-assign guidance for shopping lists
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>
2026-04-16 16:53:54 +02:00
marcus bc28b09d49 fix(recipes): normalize newlines + add update_recipe (v0.6.1)
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>
2026-04-16 15:01:40 +02:00
marcus ebbbf38ab9 feat(recipes): implement get_recipes, get_recipe, create_recipe, delete_recipe (v0.6.0)
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>
2026-04-16 14:51:53 +02:00
marcus 7abe58dee2 docs(create_task): add quantity convention to text parameter (v0.5.2)
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>
2026-04-16 14:12:02 +02:00
marcus 4a3fe6be87 feat(lists): expose emoji + color in get_lists + create_list (v0.5.1)
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>
2026-04-16 13:50:36 +02:00
marcus 311f37d72b feat(lists): implement create_list + delete_list (v0.5.0)
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>
2026-04-16 12:26:16 +02:00
marcus e76d80ece3 Dokumente aktualisiert 2026-04-16 11:11:48 +02:00
marcus 0517241ee5 feat(tasks): implement clear_due_date via FiZ \$empty sentinel (v0.4.16)
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>
2026-04-16 10:57:21 +02:00
marcus 6c955d67c8 fix: surface a00.un API errors + document dueDate-clearing limitation (v0.4.15)
- 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>
2026-04-16 09:47:51 +02:00
marcus 4411e6d93e feat: due_date, assignee_ids, list_id for create_task/update_task (v0.4.14)
- create_task: new optional params due_date (ISO 8601) and assignee_ids (list[str])
- update_task: new optional params due_date, assignee_ids, and list_id (move task)
- get_tasks: returns due_date and assignee_ids fields per task
- API params verified via FW_DEBUG=1: dueDate, assignee, taskListId
- SPEC.md, README, CLAUDE.md updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 09:01:04 +02:00
marcus 5698196c43 feat: create_category + delete_category tools (v0.4.11)
Verified via systematic FW_DEBUG=1 probing:
- taskcategoryput: requires 'name'; optional 'emoji' (Unicode or string code)
  accepted as-is. 'listId' param has no per-list effect — categories are
  family-wide.
- taskcategorydelete: uses 'id' param (not 'metaId'), returns r='true'.

Changes:
- create_category(list_id, name, icon=None): creates custom category via
  taskcategoryput; icon maps to 'emoji' API param
- delete_category(category_id): safety check via accgetallfamily looks up
  rights.canDelete='true'; system categories (rights.canDelete=null) are
  refused with a clear error
- get_categories: now exposes 'custom' bool field (rights.canDelete='true')
  so callers can identify deletable categories
- SPEC.md: document taskcategoryput + taskcategorydelete params, responses,
  error formats, and system-category protection behaviour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 07:43:54 +02:00
marcus a76dc0fd51 feat: category assignment in create_task / update_task (v0.4.10)
Verified via FW_DEBUG=1 + systematic param-name probing that the
correct parameter is `taskCategoryId` with value = full metaId from
get_categories (e.g. taskCategory/23431854_200).  Numeric systemCategoryId
alone causes API error; full metaId is accepted and stored.

Changes:
- create_task: add optional category_id parameter → sent as taskCategoryId
- update_task: add optional category_id parameter → sent as taskCategoryId;
  guard now accepts category_id-only updates
- get_tasks: expose category_id field in returned task objects
- get_categories: update docstring (param name now known)
- SPEC.md: document verified taskCategoryId param + clarify categories[]
  vs taskCategoryId field distinction
- scripts/find_category_param.py: discovery script used to find param name

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 06:54:10 +02:00
marcus ffb8b062c8 feat: get_categories tool, author resolution in get_activities, update CLAUDE.md (v0.4.8)
- get_categories(list_id): new tool filtering taskcategorysync by
  sortingIndexByTaskList, returns {id, name, emoji} ordered by sort index
- get_activities: author IDs now resolved to display names (firstName) via
  famlistfamily members; raw author_id preserved as separate field; member
  lookup is non-fatal (falls back to raw ID on error)
- CLAUDE.md: tools table updated to reflect all implemented tools (v0.4.8)
- SPEC.md: full accgetallfamily response structure documented including
  categories[] on tasks and category parameter investigation findings
- Category assignment in create/update task: all tested parameter names
  ignored by API; still to verify (Service Worker blocks web inspection)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 17:04:35 +02:00
marcus 38da31b0cb feat: Gruppe 1 – Projektgerüst, Auth, CLI (v0.1.0)
- pyproject.toml: hatchling build, mcp-familywall entry-point, deps
- src/mcp_familywall/__init__.py: version 0.1.0
- src/mcp_familywall/config.py: YAML config loader (schema_version: 1)
- src/mcp_familywall/auth.py: keyring credential resolution (FW_EMAIL/FW_PASSWORD → keyring)
- src/mcp_familywall/fw_client.py: httpx client, login/logout/call, FW_DEBUG logging
- src/mcp_familywall/cli.py: click CLI with setup / check / serve commands
- .gitignore, README.md, CLAUDE.md, SPEC.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 12:18:37 +02:00