From 343e8eeb587308b0e985d249978a8383837b5ae6 Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Fri, 17 Apr 2026 13:35:25 +0200 Subject: [PATCH] feat(tasks): add clear_list tool (v0.11.6) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- CLAUDE.md | 7 ++-- README.md | 3 +- SPEC.md | 6 ++++ pyproject.toml | 2 +- src/mcp_familywall/__init__.py | 2 +- src/mcp_familywall/server.py | 65 ++++++++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d86c242..f75eaee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -24,12 +24,12 @@ und wird in Claude Desktop eingebunden. ## Aktueller Stand -### Implementierte Tools (v0.11.5) +### Implementierte Tools (v0.11.6) | Kategorie | Tools | |---|---| | Lesen | `get_circles`, `get_members`, `get_lists`, `get_tasks`, `get_categories`, `get_activities`, `get_meal_plan` | -| Tasks | `create_task`, `update_task`, `toggle_task`, `delete_task` | +| Tasks | `create_task`, `update_task`, `toggle_task`, `delete_task`, `clear_list` | | Listen | `create_list`, `update_list`, `delete_list` | | Kategorien | `create_category`, `delete_category` | | Aktivitäten | `like_post` | @@ -68,7 +68,8 @@ und wird in Claude Desktop eingebunden. - v0.11.2: add_meal_to_meal_plan (mpcreate; Freitext; raw response bis Struktur verifiziert) ✓ - v0.11.3: add_meal_to_meal_plan strukturierter Output (a00.r.r ist Array, nicht Objekt) ✓ - v0.11.4: delete_meal_plan_entry (metadelete für dish/ und meal/-Objekte) ✓ -- v0.11.5: add_meal_note (mpmealput; Notiz + Portionen; strukturierter Output) ✓ ← aktuell +- v0.11.5: add_meal_note (mpmealput; Notiz + Portionen; strukturierter Output) ✓ +- v0.11.6: clear_list (alle Tasks einer Liste in einer Session löschen; bulk delete) ✓ ← aktuell - v2.0: Schreibzugriff auf Wall-Posts (Erstellen, Kommentieren) diff --git a/README.md b/README.md index 66c5dd2..101b152 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, tasks, and recipes directly from Claude. -## Features (v0.11.5) +## Features (v0.11.6) ### Read @@ -23,6 +23,7 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your - `update_task` -- update text, description, category, due date, assignees, or move to a different list; supports `clear_due_date=True` to remove a due date - `toggle_task` -- mark a task complete or reopen it - `delete_task` -- permanently delete a task +- `clear_list` -- delete all tasks in a list in a single session (bulk delete; optional `only_open=True` to keep completed tasks) - `create_list` -- create a new task list (`SHOPPING_LIST`, `TODOS`, or `OTHER`; optional `emoji`, `color`, and `circle_id` to target a specific circle) - `update_list` -- rename a list or change its emoji/color (partial update — omitted fields unchanged; system lists are protected) - `delete_list` -- permanently delete a list and all its tasks (system lists are protected) diff --git a/SPEC.md b/SPEC.md index cc8b536..4e68efd 100644 --- a/SPEC.md +++ b/SPEC.md @@ -62,6 +62,12 @@ POST /api/log2out → Session invalidieren Credentials (E-Mail + Passwort) werden einmalig via `mcp-familywall setup` im OS Keyring gespeichert (Keys: `email`, `password`). +### Performance-Hinweis: Bulk-Operationen + +Bulk-Operationen (z.B. alle Tasks einer Liste löschen) bündeln mehrere Calls +in einer einzigen Session: Login → Call1 → Call2 → ... → CallN → Logout. +Das spart N−1 Login/Logout-Roundtrips gegenüber N separaten Tool-Aufrufen. + ## Fehlerbehandlung ### Silent-Fail Warnung diff --git a/pyproject.toml b/pyproject.toml index f175a5a..7a157af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mcp-familywall" -version = "0.11.5" +version = "0.11.6" description = "MCP server for Family Wall — read your family's lists and tasks via Claude" readme = "README.md" requires-python = ">=3.12" diff --git a/src/mcp_familywall/__init__.py b/src/mcp_familywall/__init__.py index 91df974..be37974 100644 --- a/src/mcp_familywall/__init__.py +++ b/src/mcp_familywall/__init__.py @@ -1 +1 @@ -__version__ = "0.11.5" +__version__ = "0.11.6" diff --git a/src/mcp_familywall/server.py b/src/mcp_familywall/server.py index 032cbd6..a6551f8 100644 --- a/src/mcp_familywall/server.py +++ b/src/mcp_familywall/server.py @@ -1041,6 +1041,71 @@ def delete_task(task_id: str) -> str: return json.dumps({"deleted": True, "id": task_id}, ensure_ascii=False, indent=2) +# --------------------------------------------------------------------------- +# Tool: clear_list +# --------------------------------------------------------------------------- + + +@mcp.tool() +def clear_list(list_id: str, only_open: bool = False) -> str: + """Delete all tasks in a list within a single authenticated session. + + IMPORTANT: Ask the user for confirmation before calling this tool. + + Significantly faster than deleting tasks one by one because all + delete calls share a single login/logout session. + + Args: + list_id: List metaId from get_lists + (e.g. ``"taskList/16282169_29775360"``). + only_open: When ``True`` only incomplete tasks are deleted; + completed tasks are kept. Default ``False`` deletes all. + + Returns: + JSON with ``deleted_count`` and ``list_id`` on success, + or an error message. + """ + if not list_id.startswith("taskList/"): + return "Error: list_id must start with 'taskList/'" + + try: + email, password = get_credentials() + except RuntimeError as exc: + return f"Error: {exc}" + + try: + with FamilyWallClient() as client: + client.login(email, password) + + data = client.call( + "accgetallfamily", + {"a01call": "taskcategorysync", "a02call": "tasksync"}, + ) + raw_tasks = _extract_tasks(data) + + tasks_to_delete = [ + t + for t in raw_tasks + if t.get("taskListId") == list_id + and (not only_open or str(t.get("complete", "false")).lower() != "true") + ] + + for task in tasks_to_delete: + client.call("metadelete", {"id": task["metaId"]}) + + client.logout() + except FamilyWallError as exc: + return f"Error: Family Wall API error: {exc}" + except Exception as exc: + return f"Error: Connection error: {exc}" + + return json.dumps( + {"deleted_count": len(tasks_to_delete), "list_id": list_id}, + ensure_ascii=False, + indent=2, + ) + + # --------------------------------------------------------------------------- # Tool: create_list # ---------------------------------------------------------------------------