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>
This commit is contained in:
@@ -23,15 +23,15 @@ eingebunden.
|
|||||||
|
|
||||||
## Aktueller Stand
|
## Aktueller Stand
|
||||||
|
|
||||||
### Implementierte Tools (v0.4.11)
|
### Implementierte Tools (v0.4.14)
|
||||||
|
|
||||||
| Kategorie | Tools |
|
| Kategorie | Tools |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Kreise | `get_circles`, `get_members` |
|
| Kreise | `get_circles`, `get_members` |
|
||||||
| Listen | `get_lists` |
|
| Listen | `get_lists` |
|
||||||
| Tasks (Lesen) | `get_tasks` (inkl. `category_id`), `get_categories` (inkl. `custom`-Flag) |
|
| Tasks (Lesen) | `get_tasks` (inkl. `category_id`, `due_date`, `assignee_ids`), `get_categories` (inkl. `custom`-Flag) |
|
||||||
| Wall | `get_activities`, `like_post` |
|
| Wall | `get_activities`, `like_post` |
|
||||||
| Tasks (Schreiben) | `create_task` (inkl. `category_id`), `update_task` (inkl. `category_id`), `toggle_task`, `delete_task` |
|
| 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` |
|
||||||
| Kategorien (Schreiben) | `create_category` (inkl. `icon`), `delete_category` (System-Kategorien geschützt) |
|
| Kategorien (Schreiben) | `create_category` (inkl. `icon`), `delete_category` (System-Kategorien geschützt) |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,21 @@
|
|||||||
|
|
||||||
MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, and tasks directly from Claude.
|
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.13)
|
## Features (v0.4.14)
|
||||||
|
|
||||||
### 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 (optionally filtered by circle)
|
- `get_lists` -- list all task lists (optionally filtered by circle)
|
||||||
- `get_tasks` -- list tasks in a specific list (includes `category_id` field)
|
- `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)
|
||||||
|
|
||||||
### Write (with confirmation prompt)
|
### Write (with confirmation prompt)
|
||||||
|
|
||||||
- `create_task` -- create a new task in a list (supports `category_id` for shopping lists)
|
- `create_task` -- create a new task in a list (supports `category_id`, `due_date`, `assignee_ids`)
|
||||||
- `update_task` -- update text, description, and/or category of an existing task
|
- `update_task` -- update text, description, category, due date, assignees, or move to a different list
|
||||||
- `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_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)
|
||||||
|
|||||||
@@ -168,8 +168,10 @@ a02.r.r.updatedCreated[] → tasksync (Tasks)
|
|||||||
.name → Listen-Systemkategorien (z.B. "SYS-CAT-SHOPPINGLIST", "SYS-CAT-TODOS")
|
.name → Listen-Systemkategorien (z.B. "SYS-CAT-SHOPPINGLIST", "SYS-CAT-TODOS")
|
||||||
.taskCategoryId → spezifische Task-Kategorie (verifiziert): metaId-Format
|
.taskCategoryId → spezifische Task-Kategorie (verifiziert): metaId-Format
|
||||||
(z.B. "taskCategory/23431854_200"), null wenn nicht gesetzt
|
(z.B. "taskCategory/23431854_200"), null wenn nicht gesetzt
|
||||||
.assignee / .assigneeIds → zugewiesene Mitglieder
|
.assignee[] → zugewiesene Mitglieder: [{accountId: "..."}]
|
||||||
.reminder → Erinnerungsdatum (ISO 8601, optional)
|
.assigneeIds[] → zugewiesene Member-IDs als String-Array (z.B. ["23431898"])
|
||||||
|
.dueDate → Fälligkeitsdatum (ISO 8601, z.B. "2026-04-30T18:00:00.000Z"; null wenn nicht gesetzt)
|
||||||
|
.reminder → Erinnerungsregel (Objekt mit reminderUnit, reminderType, reminderValue — nicht das Fälligkeitsdatum!)
|
||||||
.recurrency → Wiederholungsregel (optional)
|
.recurrency → Wiederholungsregel (optional)
|
||||||
.sortingIndex → Anzeigereihenfolge
|
.sortingIndex → Anzeigereihenfolge
|
||||||
```
|
```
|
||||||
@@ -263,6 +265,8 @@ Content-Type: application/x-www-form-urlencoded
|
|||||||
| `text` | ja | Aufgabentitel |
|
| `text` | ja | Aufgabentitel |
|
||||||
| `description` | nein | Optionale Beschreibung |
|
| `description` | nein | Optionale Beschreibung |
|
||||||
| `taskCategoryId` | nein | Kategorie-MetaId aus `get_categories` (z.B. `taskCategory/23431854_200`) |
|
| `taskCategoryId` | nein | Kategorie-MetaId aus `get_categories` (z.B. `taskCategory/23431854_200`) |
|
||||||
|
| `dueDate` | nein | Fälligkeitsdatum ISO 8601 (z.B. `"2026-04-30T18:00:00"`); gespeichert als `dueDate` im Task-Objekt |
|
||||||
|
| `assignee` | nein | Member-ID aus `get_members` (z.B. `"23431898"`); für mehrere Zuweisungen: mehrfach senden (`assignee=id1&assignee=id2`); gespeichert als `assigneeIds[]` im Task-Objekt |
|
||||||
|
|
||||||
**Response-Struktur (verifiziert):**
|
**Response-Struktur (verifiziert):**
|
||||||
```
|
```
|
||||||
@@ -285,8 +289,11 @@ Content-Type: application/x-www-form-urlencoded
|
|||||||
| `text` | nein | Neuer Titel (mindestens eines der optionalen Felder erforderlich) |
|
| `text` | nein | Neuer Titel (mindestens eines der optionalen Felder erforderlich) |
|
||||||
| `description` | nein | Neue Beschreibung |
|
| `description` | nein | Neue Beschreibung |
|
||||||
| `taskCategoryId` | nein | Kategorie-MetaId aus `get_categories` (z.B. `taskCategory/23431854_200`) |
|
| `taskCategoryId` | nein | Kategorie-MetaId aus `get_categories` (z.B. `taskCategory/23431854_200`) |
|
||||||
|
| `dueDate` | nein | Fälligkeitsdatum ISO 8601 (z.B. `"2026-04-30T18:00:00"`); gespeichert als `dueDate` im Task-Objekt |
|
||||||
|
| `assignee` | nein | Member-ID aus `get_members` (z.B. `"23431898"`); für mehrere Zuweisungen: mehrfach senden (`assignee=id1&assignee=id2`); leerer String (`""`) entfernt alle Zuweisungen (nicht verifiziert); gespeichert als `assigneeIds[]` im Task-Objekt |
|
||||||
|
| `taskListId` | nein | Ziel-Listen-ID zum Verschieben des Tasks (verifiziert – ändert `taskListId` im Task-Objekt) |
|
||||||
|
|
||||||
Hinweis: `taskListId` ist **nicht** erforderlich (verifiziert – Update ohne `taskListId` funktioniert).
|
Hinweis: `taskListId` ist optional – ohne diesen Parameter bleibt der Task in seiner aktuellen Liste.
|
||||||
|
|
||||||
**Response-Struktur:** kein spezifischer Rückgabewert – Erfolg = kein `ex`/`un`-Key auf Top-Level.
|
**Response-Struktur:** kein spezifischer Rückgabewert – Erfolg = kein `ex`/`un`-Key auf Top-Level.
|
||||||
|
|
||||||
@@ -491,3 +498,7 @@ AND `moodStarShortcut: false` AND `moodMap: {}`.
|
|||||||
- ~~`taskcreate2` / `taskupdate2`: Kategorie-Paramter-Name~~ → **`taskCategoryId`**, Wert = vollständige metaId (verifiziert)
|
- ~~`taskcreate2` / `taskupdate2`: Kategorie-Paramter-Name~~ → **`taskCategoryId`**, Wert = vollständige metaId (verifiziert)
|
||||||
- ~~`taskcategoryput`: Body-Parameter, Response-Struktur~~ → `name` (Pflicht), `emoji` (optional), Response = neues Kategorie-Objekt (verifiziert)
|
- ~~`taskcategoryput`: Body-Parameter, Response-Struktur~~ → `name` (Pflicht), `emoji` (optional), Response = neues Kategorie-Objekt (verifiziert)
|
||||||
- ~~`taskcategorydelete`: Body-Parameter~~ → **`id`** (nicht `metaId`!), Response = `"true"` (verifiziert)
|
- ~~`taskcategorydelete`: Body-Parameter~~ → **`id`** (nicht `metaId`!), Response = `"true"` (verifiziert)
|
||||||
|
- ~~`taskcreate2` / `taskupdate2`: Fälligkeitsdatum-Parameter~~ → **`dueDate`**, ISO 8601 String, gespeichert als `dueDate` im Task-Objekt (verifiziert)
|
||||||
|
- ~~`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
|
||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mcp-familywall"
|
name = "mcp-familywall"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
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 @@
|
|||||||
__version__ = "0.4.13"
|
__version__ = "0.4.14"
|
||||||
|
|||||||
@@ -326,6 +326,8 @@ def get_tasks(list_id: str, only_open: bool = True):
|
|||||||
"description": task.get("description"),
|
"description": task.get("description"),
|
||||||
"completed": completed,
|
"completed": completed,
|
||||||
"category_id": task.get("taskCategoryId"),
|
"category_id": task.get("taskCategoryId"),
|
||||||
|
"due_date": task.get("dueDate"),
|
||||||
|
"assignee_ids": task.get("assigneeIds") or [],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -676,6 +678,8 @@ def create_task(
|
|||||||
text: str,
|
text: str,
|
||||||
description: str | None = None,
|
description: str | None = None,
|
||||||
category_id: str | None = None,
|
category_id: str | None = None,
|
||||||
|
due_date: str | None = None,
|
||||||
|
assignee_ids: list[str] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Create a new task in the given list.
|
"""Create a new task in the given list.
|
||||||
|
|
||||||
@@ -688,6 +692,9 @@ def create_task(
|
|||||||
category_id: Optional category metaId from get_categories
|
category_id: Optional category metaId from get_categories
|
||||||
(e.g. ``taskCategory/23431854_200``). Only meaningful for
|
(e.g. ``taskCategory/23431854_200``). Only meaningful for
|
||||||
shopping lists; ignored for TODO lists.
|
shopping lists; ignored for TODO lists.
|
||||||
|
due_date: Optional due date in ISO 8601 format (e.g. ``"2026-04-30T18:00:00"``).
|
||||||
|
assignee_ids: Optional list of member IDs from get_members to assign the task
|
||||||
|
(e.g. ``["23431898"]``). Empty list assigns to nobody.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON with the new task's metaId on success, or an error message.
|
JSON with the new task's metaId on success, or an error message.
|
||||||
@@ -697,6 +704,10 @@ def create_task(
|
|||||||
params["description"] = description
|
params["description"] = description
|
||||||
if category_id:
|
if category_id:
|
||||||
params["taskCategoryId"] = category_id
|
params["taskCategoryId"] = category_id
|
||||||
|
if due_date is not None:
|
||||||
|
params["dueDate"] = due_date
|
||||||
|
if assignee_ids is not None:
|
||||||
|
params["assignee"] = assignee_ids if assignee_ids else ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = _authenticated_call("taskcreate2", params)
|
data = _authenticated_call("taskcreate2", params)
|
||||||
@@ -728,11 +739,14 @@ def update_task(
|
|||||||
text: str | None = None,
|
text: str | None = None,
|
||||||
description: str | None = None,
|
description: str | None = None,
|
||||||
category_id: str | None = None,
|
category_id: str | None = None,
|
||||||
|
due_date: str | None = None,
|
||||||
|
assignee_ids: list[str] | None = None,
|
||||||
|
list_id: str | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Update the text, description, and/or category of an existing task.
|
"""Update an existing task's fields.
|
||||||
|
|
||||||
IMPORTANT: Ask the user for confirmation before calling this tool.
|
IMPORTANT: Ask the user for confirmation before calling this tool.
|
||||||
At least one of *text*, *description*, or *category_id* must be provided.
|
At least one parameter besides *task_id* must be provided.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
task_id: Task metaId from get_tasks.
|
task_id: Task metaId from get_tasks.
|
||||||
@@ -741,12 +755,26 @@ def update_task(
|
|||||||
category_id: New category metaId from get_categories
|
category_id: New category metaId from get_categories
|
||||||
(e.g. ``taskCategory/23431854_200``). Only meaningful for
|
(e.g. ``taskCategory/23431854_200``). Only meaningful for
|
||||||
shopping lists; ignored for TODO lists.
|
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.
|
||||||
|
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
|
||||||
|
from get_lists (e.g. ``"taskList/23431854_29740942"``). Omit to keep in
|
||||||
|
current list.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON success indicator or an error message.
|
JSON success indicator or an error message.
|
||||||
"""
|
"""
|
||||||
if text is None and description is None and category_id is None:
|
if (
|
||||||
return "Error: At least one of 'text', 'description', or 'category_id' must be provided."
|
text is None
|
||||||
|
and description is None
|
||||||
|
and category_id is None
|
||||||
|
and due_date is None
|
||||||
|
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."
|
||||||
|
|
||||||
params: dict[str, Any] = {"metaId": task_id}
|
params: dict[str, Any] = {"metaId": task_id}
|
||||||
if text is not None:
|
if text is not None:
|
||||||
@@ -755,6 +783,12 @@ def update_task(
|
|||||||
params["description"] = description
|
params["description"] = description
|
||||||
if category_id is not None:
|
if category_id is not None:
|
||||||
params["taskCategoryId"] = category_id
|
params["taskCategoryId"] = category_id
|
||||||
|
if due_date is not None:
|
||||||
|
params["dueDate"] = due_date
|
||||||
|
if assignee_ids is not None:
|
||||||
|
params["assignee"] = assignee_ids if assignee_ids else ""
|
||||||
|
if list_id is not None:
|
||||||
|
params["taskListId"] = list_id
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_authenticated_call("taskupdate2", params)
|
_authenticated_call("taskupdate2", params)
|
||||||
|
|||||||
Reference in New Issue
Block a user