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>
This commit is contained in:
@@ -23,7 +23,7 @@ eingebunden.
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
### Implementierte Tools (v0.4.15)
|
||||
### Implementierte Tools (v0.4.16)
|
||||
|
||||
| Kategorie | Tools |
|
||||
|---|---|
|
||||
@@ -31,7 +31,7 @@ eingebunden.
|
||||
| Listen | `get_lists` |
|
||||
| Tasks (Lesen) | `get_tasks` (inkl. `category_id`, `due_date`, `assignee_ids`), `get_categories` (inkl. `custom`-Flag) |
|
||||
| Wall | `get_activities`, `like_post` |
|
||||
| Tasks (Schreiben) | `create_task` (inkl. `category_id`, `due_date`, `assignee_ids`), `update_task` (inkl. `category_id`, `due_date`, `assignee_ids`, `list_id`), `toggle_task`, `delete_task` |
|
||||
| Tasks (Schreiben) | `create_task` (inkl. `category_id`, `due_date`, `assignee_ids`), `update_task` (inkl. `category_id`, `due_date`, `clear_due_date`, `assignee_ids`, `list_id`), `toggle_task`, `delete_task` |
|
||||
| Kategorien (Schreiben) | `create_category` (inkl. `icon`), `delete_category` (System-Kategorien geschützt) |
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, and tasks directly from Claude.
|
||||
|
||||
## Features (v0.4.15)
|
||||
## Features (v0.4.16)
|
||||
|
||||
### Read
|
||||
|
||||
@@ -16,7 +16,7 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your
|
||||
### Write (with confirmation prompt)
|
||||
|
||||
- `create_task` -- create a new task in a list (supports `category_id`, `due_date`, `assignee_ids`)
|
||||
- `update_task` -- update text, description, category, due date, assignees, or move to a different list (note: clearing a due date is not supported by the Family Wall API)
|
||||
- `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
|
||||
- `create_category` -- create a custom category for a shopping list (with optional icon)
|
||||
|
||||
@@ -315,28 +315,33 @@ Hinweis: `taskListId` ist optional – ohne diesen Parameter bleibt der Task in
|
||||
|
||||
**Response-Struktur:** kein spezifischer Rückgabewert – Erfolg = kein `ex`/`un`-Key auf Top-Level.
|
||||
|
||||
**dueDate Clearing – nicht implementierbar (Stand: April 2026):**
|
||||
**dueDate Clearing – `"$empty"` Sentinel (verifiziert April 2026, v0.4.16):**
|
||||
|
||||
Ausgiebig getestete Werte für `dueDate`, die alle fehlschlugen:
|
||||
Der FiZ-Framework verwendet den Sentinel-Wert `"$empty"` um optionale Felder zu leeren.
|
||||
|
||||
```
|
||||
POST taskupdate2
|
||||
metaId=task/23431854_726333919&dueDate=$empty
|
||||
→ dueDate wird auf null gesetzt ✓
|
||||
```
|
||||
|
||||
`update_task(clear_due_date=True)` sendet intern `dueDate=$empty`.
|
||||
|
||||
**Getestete Werte die fehlschlugen (vor der Lösung):**
|
||||
|
||||
| Wert | API-Response |
|
||||
|---|---|
|
||||
| `""` (leerer String) | `a00.un.un: " is not a valid Date"` |
|
||||
| `"null"` | `a00.un.un: "Cannot parse date val=null"` |
|
||||
| `"0"` | API-Fehler (ungültiges Datum) |
|
||||
| `"-1"` | `a00.un.un: "-1 is not a valid Date"` |
|
||||
| `"remove"` / `"clear"` | `a00.un.un: "Cannot parse date val=..."` |
|
||||
| `"0000-00-00T00:00:00"` | API-Fehler |
|
||||
| `"1970-01-01T00:00:00"` | **Erfolgreich** – setzt dueDate auf Unix-Epoch (kein echtes Clearing!) |
|
||||
| Separate Parameter (`removeDueDate`, `clearDueDate`, `clearFields`) | werden ignoriert, dueDate bleibt unverändert |
|
||||
| Feld weglassen (kein `dueDate` in Request) | dueDate bleibt unverändert |
|
||||
| `""` (leerer String) | `a00.un: " is not a valid Date"` |
|
||||
| `"null"` | `a00.un: "Cannot parse date val=null"` |
|
||||
| `"undefined"` | `a00.un: "Cannot parse date val=undefined"` |
|
||||
| `"0"`, `"-1"` | `a00.un: "... is not a valid Date"` |
|
||||
| `"remove"` / `"clear"` | `a00.un: "Cannot parse date val=..."` |
|
||||
| `"1970-01-01T00:00:00"` | Erfolgreich – setzt dueDate auf Unix-Epoch (kein Clearing!) |
|
||||
| Feld weglassen | dueDate bleibt unverändert |
|
||||
| `removeDueDate=1`, `clearDueDate=1` | werden ignoriert |
|
||||
|
||||
**Wichtig:** Die Fehler werden als `a00.un.un` zurückgegeben (nicht Top-Level `un`).
|
||||
Der `fw_client` prüfte ursprünglich nur Top-Level `un` → silent fail (ab v0.4.15 behoben:
|
||||
`a00.un` wird ebenfalls erkannt und als `FamilyWallError` geworfen).
|
||||
|
||||
Das `dueDate`-Feld kann einmal gesetzt nicht mehr entfernt werden.
|
||||
`update_task(clear_due_date=True)` gibt eine klare Fehlermeldung zurück.
|
||||
**Wichtig:** Die Fehler werden als `a00.un` zurückgegeben (nicht Top-Level `un`).
|
||||
Ab v0.4.15 erkennt `fw_client` diese und wirft `FamilyWallError`.
|
||||
|
||||
### `taskmark` – Task als erledigt/offen markieren
|
||||
POST https://api.familywall.com/api/taskmark
|
||||
@@ -543,4 +548,4 @@ AND `moodStarShortcut: false` AND `moodMap: {}`.
|
||||
- ~~`taskcreate2` / `taskupdate2`: Zuweisung-Parameter~~ → **`assignee`** (Member-ID String; mehrere Werte = mehrfach senden); gespeichert als `assigneeIds[]` (verifiziert)
|
||||
- ~~`taskupdate2`: Task verschieben~~ → **`taskListId`** als optionaler Parameter setzt neue Liste (verifiziert)
|
||||
- `taskupdate2`: Alle Zuweisungen entfernen (leere `assignee`-Liste) → noch nicht verifiziert
|
||||
- ~~`taskupdate2`: `dueDate` entfernen (Clearing)~~ → **nicht möglich** (verifiziert, April 2026) — alle getesteten Werte werden als ungültiges Datum abgelehnt (siehe unten)
|
||||
- ~~`taskupdate2`: `dueDate` entfernen (Clearing)~~ → **`dueDate=$empty`** (FiZ-Sentinel, verifiziert April 2026, v0.4.16)
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "mcp-familywall"
|
||||
version = "0.4.15"
|
||||
version = "0.4.16"
|
||||
description = "MCP server for Family Wall — read your family's lists and tasks via Claude"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.4.15"
|
||||
__version__ = "0.4.16"
|
||||
|
||||
@@ -758,10 +758,8 @@ def update_task(
|
||||
shopping lists; ignored for TODO lists.
|
||||
due_date: New due date in ISO 8601 format (e.g. ``"2026-04-30T18:00:00"``).
|
||||
Omit to leave unchanged. Cannot be used together with *clear_due_date*.
|
||||
clear_due_date: Set to ``True`` to request removal of the due date.
|
||||
**Note:** The Family Wall API does not support clearing a due date once
|
||||
set — this will return an informational error. This parameter exists to
|
||||
surface the limitation explicitly rather than silently doing nothing.
|
||||
clear_due_date: Set to ``True`` to remove the due date from the task.
|
||||
Cannot be used together with *due_date*.
|
||||
assignee_ids: New list of member IDs from get_members (e.g. ``["23431898"]``).
|
||||
Pass an empty list to remove all assignees. Omit to leave unchanged.
|
||||
list_id: Move the task to a different list by providing the target list ID
|
||||
@@ -771,23 +769,19 @@ def update_task(
|
||||
Returns:
|
||||
JSON success indicator or an error message.
|
||||
"""
|
||||
if clear_due_date:
|
||||
return (
|
||||
"Error: Removing a due date is not supported by the Family Wall API. "
|
||||
"The 'dueDate' field cannot be cleared once set — this is a known "
|
||||
"limitation of the API (all tested values are rejected as invalid dates). "
|
||||
"You can set a different future date instead."
|
||||
)
|
||||
if clear_due_date and due_date is not None:
|
||||
return "Error: 'clear_due_date' and 'due_date' cannot be used together."
|
||||
|
||||
if (
|
||||
text is None
|
||||
and description is None
|
||||
and category_id is None
|
||||
and due_date is None
|
||||
and not clear_due_date
|
||||
and assignee_ids is None
|
||||
and list_id is None
|
||||
):
|
||||
return "Error: At least one of 'text', 'description', 'category_id', 'due_date', 'assignee_ids', or 'list_id' must be provided."
|
||||
return "Error: At least one of 'text', 'description', 'category_id', 'due_date', 'clear_due_date', 'assignee_ids', or 'list_id' must be provided."
|
||||
|
||||
params: dict[str, Any] = {"metaId": task_id}
|
||||
if text is not None:
|
||||
@@ -796,7 +790,10 @@ def update_task(
|
||||
params["description"] = description
|
||||
if category_id is not None:
|
||||
params["taskCategoryId"] = category_id
|
||||
if due_date is not None:
|
||||
if clear_due_date:
|
||||
# The FiZ framework uses "$empty" as a sentinel to clear optional date fields.
|
||||
params["dueDate"] = "$empty"
|
||||
elif due_date is not None:
|
||||
params["dueDate"] = due_date
|
||||
if assignee_ids is not None:
|
||||
params["assignee"] = assignee_ids if assignee_ids else ""
|
||||
|
||||
Reference in New Issue
Block a user