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>
This commit is contained in:
2026-04-17 08:06:10 +02:00
parent 36448e68e0
commit af2cfc8728
5 changed files with 39 additions and 12 deletions
+4 -3
View File
@@ -24,7 +24,7 @@ und wird in Claude Desktop eingebunden.
## Aktueller Stand ## Aktueller Stand
### Implementierte Tools (v0.8.2) ### Implementierte Tools (v0.8.3)
| Kategorie | Tools | | Kategorie | Tools |
|---|---| |---|---|
@@ -53,7 +53,8 @@ und wird in Claude Desktop eingebunden.
- v0.7.5: Primärkreis-Schutz in update_circle (isFirstFamily-Check) ✓ - v0.7.5: Primärkreis-Schutz in update_circle (isFirstFamily-Check) ✓
- v0.8.0: Rezept-Kategorien (get_recipe_categories, create_recipe + category_ids, update_recipe + category_ids) ✓ - v0.8.0: Rezept-Kategorien (get_recipe_categories, create_recipe + category_ids, update_recipe + category_ids) ✓
- v0.8.1: Bugfixes (recipe categories) ✓ - v0.8.1: Bugfixes (recipe categories) ✓
- v0.8.2: get_lists() ohne scope → alle Kreise ✓ ← aktuell - v0.8.2: get_lists() ohne scope → alle Kreise ✓
- v0.8.3: OTHER-Listentyp dokumentiert + create_list unterstützt ihn; FW_DEBUG=1 loggt unbekannte Task-Felder (Vorbereitung Wiederholungen) ✓ ← aktuell
- v0.8.x: mpadditemtolist (gestrichen Family Wall kann das nativ) - v0.8.x: mpadditemtolist (gestrichen Family Wall kann das nativ)
- v0.9.x: Erinnerungen + Wiederholungen (Premium-Account erforderlich) - v0.9.x: Erinnerungen + Wiederholungen (Premium-Account erforderlich)
- v2.0: Schreibzugriff auf Wall-Posts (Erstellen, Kommentieren) - v2.0: Schreibzugriff auf Wall-Posts (Erstellen, Kommentieren)
@@ -144,7 +145,7 @@ Fehler bei falschen Parametern kommen nicht immer auf Top-Level:
| `wallmood` | `wall_message_id`, `moodType` | `"STAR"` für Like | | `wallmood` | `wall_message_id`, `moodType` | `"STAR"` für Like |
| `taskcategoryput` | `name`, `emoji` | | | `taskcategoryput` | `name`, `emoji` | |
| `taskcategorydelete` | `id` | metaId der Kategorie | | `taskcategorydelete` | `id` | metaId der Kategorie |
| `taskcreatelist` | `name`, `taskListType`, `sharedToAll`, `color`, `emoji`, `scope` | `scope`: Kreis-metaId für nicht-primäre Kreise | | `taskcreatelist` | `name`, `taskListType`, `sharedToAll`, `color`, `emoji`, `scope` | `taskListType`: `SHOPPING_LIST`, `TODOS`, `OTHER`; `scope`: Kreis-metaId für nicht-primäre Kreise |
| `taskgettasklists` | `scope` | Kreis-metaId; ohne scope → primärer Kreis | | `taskgettasklists` | `scope` | Kreis-metaId; ohne scope → primärer Kreis |
| `taskupdatelist` | `metaId`, `name`, `color`, `emoji`, `scope` | `metaId` ⚠️ nicht `id`!; `scope`: Kreis-metaId für sekundäre Kreise; Partial Update | | `taskupdatelist` | `metaId`, `name`, `color`, `emoji`, `scope` | `metaId` ⚠️ nicht `id`!; `scope`: Kreis-metaId für sekundäre Kreise; Partial Update |
| `taskdeletelist` | `id`, `scope` | `scope`: Kreis-metaId für sekundäre Kreise | | `taskdeletelist` | `id`, `scope` | `scope`: Kreis-metaId für sekundäre Kreise |
+3 -3
View File
@@ -2,13 +2,13 @@
MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, tasks, and recipes directly from Claude. 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.8.2) ## Features (v0.8.3)
### Read ### Read
- `get_circles` -- list all family circles - `get_circles` -- list all family circles
- `get_members` -- list members of a circle (or all circles) - `get_members` -- list members of a circle (or all circles)
- `get_lists` -- list all task lists (includes `emoji`, `color`, `circle_id`; `null` when unset); without scope parameter returns lists from **all circles**; optional `scope` parameter filters by circle metaId or circle name - `get_lists` -- list all task lists (includes `emoji`, `color`, `circle_id`; `null` when unset; list types: `SHOPPING_LIST`, `TODOS`, `OTHER`); without scope parameter returns lists from **all circles**; optional `scope` parameter filters by circle metaId or circle name
- `get_tasks` -- list tasks in a specific list (includes `category_id`, `due_date`, `assignee_ids`) - `get_tasks` -- list tasks in a specific list (includes `category_id`, `due_date`, `assignee_ids`)
- `get_categories` -- list categories for a list (locale-filtered; custom categories always included; `custom` flag marks user-created ones) - `get_categories` -- list categories for a list (locale-filtered; custom categories always included; `custom` flag marks user-created ones)
- `get_activities` -- list recent wall activities (author resolved to display name) - `get_activities` -- list recent wall activities (author resolved to display name)
@@ -22,7 +22,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 - `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 - `toggle_task` -- mark a task complete or reopen it
- `delete_task` -- permanently delete a task - `delete_task` -- permanently delete a task
- `create_list` -- create a new task list (SHOPPING_LIST or TODOS; optional `emoji`, `color`, and `circle_id` to target a specific circle) - `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) - `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) - `delete_list` -- permanently delete a list and all its tasks (system lists are protected)
- `create_category` -- create a custom category for a shopping list (with optional icon) - `create_category` -- create a custom category for a shopping list (with optional icon)
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "mcp-familywall" name = "mcp-familywall"
version = "0.8.2" version = "0.8.3"
description = "MCP server for Family Wall — read your family's lists and tasks via Claude" description = "MCP server for Family Wall — read your family's lists and tasks via Claude"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.8.2" __version__ = "0.8.3"
+30 -4
View File
@@ -4,6 +4,8 @@ from __future__ import annotations
import json import json
import logging import logging
import os
import sys
from typing import Any from typing import Any
from mcp.server.fastmcp import FastMCP from mcp.server.fastmcp import FastMCP
@@ -342,7 +344,9 @@ def get_lists(scope: str | None = None) -> str:
candidate = data["a00"]["r"]["r"] candidate = data["a00"]["r"]["r"]
if isinstance(candidate, list): if isinstance(candidate, list):
raw_lists = candidate raw_lists = candidate
elif isinstance(candidate, dict) and isinstance(candidate.get("updatedCreated"), list): elif isinstance(candidate, dict) and isinstance(
candidate.get("updatedCreated"), list
):
raw_lists = candidate["updatedCreated"] raw_lists = candidate["updatedCreated"]
except (KeyError, TypeError): except (KeyError, TypeError):
pass pass
@@ -392,6 +396,18 @@ def get_tasks(list_id: str, only_open: bool = True):
raw_tasks = _extract_tasks(data) raw_tasks = _extract_tasks(data)
_fw_debug = os.environ.get("FW_DEBUG") == "1"
_known_fields = {
"metaId",
"text",
"description",
"complete",
"taskCategoryId",
"dueDate",
"assigneeIds",
"taskListId",
}
result = [] result = []
for task in raw_tasks: for task in raw_tasks:
if task.get("taskListId") != list_id: if task.get("taskListId") != list_id:
@@ -399,6 +415,16 @@ def get_tasks(list_id: str, only_open: bool = True):
completed = str(task.get("complete", "false")).lower() == "true" completed = str(task.get("complete", "false")).lower() == "true"
if only_open and completed: if only_open and completed:
continue continue
if _fw_debug:
unknown = {k: v for k, v in task.items() if k not in _known_fields}
if unknown:
print(
f"[FW_DEBUG] task {task.get('metaId')} unknown fields: "
+ json.dumps(unknown, ensure_ascii=False),
file=sys.stderr,
)
result.append( result.append(
{ {
"id": task.get("metaId"), "id": task.get("metaId"),
@@ -988,7 +1014,7 @@ def create_list(
Args: Args:
name: Display name for the new list (max 200 characters). name: Display name for the new list (max 200 characters).
list_type: List type — either ``"SHOPPING_LIST"`` or ``"TODOS"``. list_type: List type — ``"SHOPPING_LIST"``, ``"TODOS"``, or ``"OTHER"``.
shared_to_all: When ``True`` (default) the list is shared with all shared_to_all: When ``True`` (default) the list is shared with all
circle members. When ``False`` it is private to the creator. circle members. When ``False`` it is private to the creator.
color: Optional background colour as a hex string (e.g. ``"#4784EC"``). color: Optional background colour as a hex string (e.g. ``"#4784EC"``).
@@ -1003,8 +1029,8 @@ def create_list(
Includes ``circle_id`` field showing which circle the list was Includes ``circle_id`` field showing which circle the list was
created in. created in.
""" """
if list_type not in ("SHOPPING_LIST", "TODOS"): if list_type not in ("SHOPPING_LIST", "TODOS", "OTHER"):
return "Error: list_type must be 'SHOPPING_LIST' or 'TODOS'." return "Error: list_type must be 'SHOPPING_LIST', 'TODOS', or 'OTHER'."
if len(name) > 200: if len(name) > 200:
return "Error: name must not exceed 200 characters." return "Error: name must not exceed 200 characters."