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>
This commit is contained in:
@@ -10,6 +10,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
This project follows Semantic Versioning (SemVer).
|
This project follows Semantic Versioning (SemVer).
|
||||||
Breaking changes (removed tools, changed parameters) increment the major version.
|
Breaking changes (removed tools, changed parameters) increment the major version.
|
||||||
|
|
||||||
|
## [1.1.0] – 2026-04-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `update_task`: recurrency parameters (`recurrency`, `recurrency_interval`, `rrule`,
|
||||||
|
`clear_recurrency`) — set or remove task recurrence rules via `recurrencyDescriptor`
|
||||||
|
- `update_task`: reminder parameters (`reminder_unit`, `reminder_value`, `clear_reminder`)
|
||||||
|
— set or remove task reminders via `reminder`
|
||||||
|
- SPEC.md: documented `recurrencyDescriptor` and `reminder` fields for `taskupdate2`
|
||||||
|
(verified via JS-Bundle xb-Encoder / fc-Encoder)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [1.0.1] – 2026-04-17
|
## [1.0.1] – 2026-04-17
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ und wird in Claude Desktop eingebunden.
|
|||||||
|
|
||||||
## Aktueller Stand
|
## Aktueller Stand
|
||||||
|
|
||||||
### Version: **v1.0.0** ← aktuell
|
### Version: **v1.1.0** ← aktuell
|
||||||
|
|
||||||
### Implementierte Tools
|
### Implementierte Tools
|
||||||
|
|
||||||
@@ -130,8 +130,10 @@ Fehler bei falschen Parametern kommen nicht immer auf Top-Level:
|
|||||||
| Endpoint | Parameter | Wert/Format |
|
| Endpoint | Parameter | Wert/Format |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `taskcreate2` | `taskListId`, `text`, `description`, `taskCategoryId`, `dueDate`, `assignee` | – |
|
| `taskcreate2` | `taskListId`, `text`, `description`, `taskCategoryId`, `dueDate`, `assignee` | – |
|
||||||
| `taskupdate2` | `metaId`, `text`, `description`, `taskCategoryId`, `dueDate`, `assignee`, `taskListId` | – |
|
| `taskupdate2` | `metaId`, `text`, `description`, `taskCategoryId`, `dueDate`, `assignee`, `taskListId`, `recurrencyDescriptor`, `reminder` | – |
|
||||||
| `taskupdate2` | `dueDate` löschen | `$empty` |
|
| `taskupdate2` | `dueDate` löschen | `$empty` |
|
||||||
|
| `taskupdate2` | `recurrencyDescriptor` | `{recurrency, recurrencyInterval, rrule, byDay, byMonthDay, recurrencyEndDate, endOccurence}`; löschen: `{recurrency: "NONE"}` |
|
||||||
|
| `taskupdate2` | `reminder` | `{reminderUnit: "MINUTE"\|"HOUR"\|"DAY", reminderValue: int, reminderType: "SNOOZE", localId: 0}`; löschen: `{reminderUnit: "", reminderValue: 0, ...}` |
|
||||||
| `taskmark` | `taskId`, `complete` | `"true"`/`"false"` |
|
| `taskmark` | `taskId`, `complete` | `"true"`/`"false"` |
|
||||||
| `metadelete` | `id` | metaId des Tasks / Rezepts |
|
| `metadelete` | `id` | metaId des Tasks / Rezepts |
|
||||||
| `wallmood` | `wall_message_id`, `moodType` | `"STAR"` für Like |
|
| `wallmood` | `wall_message_id`, `moodType` | `"STAR"` für Like |
|
||||||
|
|||||||
@@ -201,9 +201,36 @@ POST https://api.familywall.com/api/taskupdate2
|
|||||||
| `dueDate` | nein | ISO 8601 oder `$empty` zum Löschen |
|
| `dueDate` | nein | ISO 8601 oder `$empty` zum Löschen |
|
||||||
| `assignee` | nein | Member-accountId (mehrfach sendbar), `""` zum Entfernen aller |
|
| `assignee` | nein | Member-accountId (mehrfach sendbar), `""` zum Entfernen aller |
|
||||||
| `taskListId` | nein | neue Listen-metaId (verschiebt Task) |
|
| `taskListId` | nein | neue Listen-metaId (verschiebt Task) |
|
||||||
|
| `recurrencyDescriptor` | nein | Objekt mit Wiederholungs-Feldern (siehe unten) |
|
||||||
|
| `reminder` | nein | Objekt mit Erinnerungs-Feldern (siehe unten) |
|
||||||
|
|
||||||
**Hinweis:** `taskListId` ist NICHT Pflicht beim Update.
|
**Hinweis:** `taskListId` ist NICHT Pflicht beim Update.
|
||||||
|
|
||||||
|
**`recurrencyDescriptor`-Felder** (verifiziert via JS-Bundle xb-Encoder):
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|---|---|
|
||||||
|
| `recurrency` | `"DAILY"` \| `"WEEKLY"` \| `"MONTHLY"` \| `"YEARLY"` \| `"NONE"` |
|
||||||
|
| `recurrencyInterval` | int (z.B. `2` für "alle 2 Wochen") |
|
||||||
|
| `rrule` | vollständige iCal-RRULE (z.B. `"FREQ=WEEKLY;INTERVAL=2;BYDAY=FR"`) |
|
||||||
|
| `byDay` | z.B. `"FR"`, `"1SA"`, `"MO,TU,WE,TH,FR"` |
|
||||||
|
| `byMonthDay` | int (z.B. `7` für "am 7. des Monats") |
|
||||||
|
| `recurrencyEndDate` | ISO-Datum (z.B. `"2026-12-31"`) |
|
||||||
|
| `endOccurence` | int (nach N Wiederholungen aufhören) |
|
||||||
|
|
||||||
|
Wiederholung entfernen: `recurrencyDescriptor = {"recurrency": "NONE"}`
|
||||||
|
|
||||||
|
**`reminder`-Felder** (verifiziert via JS-Bundle fc-Encoder):
|
||||||
|
|
||||||
|
| Feld | Wert |
|
||||||
|
|---|---|
|
||||||
|
| `reminderUnit` | `"MINUTE"` \| `"HOUR"` \| `"DAY"` |
|
||||||
|
| `reminderValue` | int (`0` = zum Zeitpunkt, `15` = 15 min vorher, `1` = 1 Einheit vorher) |
|
||||||
|
| `reminderType` | immer `"SNOOZE"` |
|
||||||
|
| `localId` | immer `0` |
|
||||||
|
|
||||||
|
Erinnerung entfernen: `reminder = {"reminderUnit": "", "reminderValue": 0, "reminderType": "SNOOZE", "localId": 0}`
|
||||||
|
|
||||||
**Response:**
|
**Response:**
|
||||||
```
|
```
|
||||||
a00.r.r → vollständiges Task-Objekt
|
a00.r.r → vollständiges Task-Objekt
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mcp-familywall"
|
name = "mcp-familywall"
|
||||||
version = "1.0.1"
|
version = "1.1.0"
|
||||||
description = "MCP server for Family Wall — manage your family's circles, lists, tasks, recipes, and meal plan via Claude"
|
description = "MCP server for Family Wall — manage your family's circles, lists, tasks, recipes, and meal plan via Claude"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
@@ -926,6 +926,13 @@ def update_task(
|
|||||||
clear_due_date: bool = False,
|
clear_due_date: bool = False,
|
||||||
assignee_ids: list[str] | None = None,
|
assignee_ids: list[str] | None = None,
|
||||||
list_id: str | None = None,
|
list_id: str | None = None,
|
||||||
|
recurrency: str | None = None,
|
||||||
|
recurrency_interval: int | None = None,
|
||||||
|
rrule: str | None = None,
|
||||||
|
clear_recurrency: bool = False,
|
||||||
|
reminder_unit: str | None = None,
|
||||||
|
reminder_value: int | None = None,
|
||||||
|
clear_reminder: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Update an existing task's fields.
|
"""Update an existing task's fields.
|
||||||
|
|
||||||
@@ -948,12 +955,40 @@ def update_task(
|
|||||||
list_id: Move the task to a different list by providing the target list ID
|
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
|
from get_lists (e.g. ``"taskList/23431854_29740942"``). Omit to keep in
|
||||||
current list.
|
current list.
|
||||||
|
recurrency: Recurrence frequency — ``"DAILY"``, ``"WEEKLY"``, ``"MONTHLY"``,
|
||||||
|
``"YEARLY"``, or ``"NONE"``. Examples: daily → ``recurrency="DAILY",
|
||||||
|
recurrency_interval=1``; every 2 weeks on Friday →
|
||||||
|
``recurrency="WEEKLY", recurrency_interval=2,
|
||||||
|
rrule="FREQ=WEEKLY;INTERVAL=2;BYDAY=FR"``.
|
||||||
|
Cannot be used together with *clear_recurrency*.
|
||||||
|
recurrency_interval: Repeat every N units (e.g. ``2`` for "every 2 weeks").
|
||||||
|
Only meaningful when *recurrency* is set.
|
||||||
|
rrule: Full iCalendar RRULE string (e.g. ``"FREQ=WEEKLY;INTERVAL=2;BYDAY=FR"``).
|
||||||
|
Overrides simple recurrency fields when set.
|
||||||
|
clear_recurrency: Set to ``True`` to remove the recurrence rule from the task.
|
||||||
|
Cannot be used together with *recurrency*.
|
||||||
|
reminder_unit: Unit for the reminder offset — ``"MINUTE"``, ``"HOUR"``, or
|
||||||
|
``"DAY"``. Must be provided together with *reminder_value*. Requires a
|
||||||
|
*due_date* to be set on the task.
|
||||||
|
reminder_value: Offset before the due date/time (e.g. ``0`` = at the time,
|
||||||
|
``15`` = 15 min before, ``1`` with unit ``"DAY"`` = 1 day before).
|
||||||
|
Must be provided together with *reminder_unit*.
|
||||||
|
clear_reminder: Set to ``True`` to remove the reminder from the task.
|
||||||
|
Cannot be used together with *reminder_unit*/*reminder_value*.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON success indicator or an error message.
|
JSON success indicator or an error message.
|
||||||
"""
|
"""
|
||||||
if clear_due_date and due_date is not None:
|
if clear_due_date and due_date is not None:
|
||||||
return _err("'clear_due_date' and 'due_date' cannot be used together.")
|
return _err("'clear_due_date' and 'due_date' cannot be used together.")
|
||||||
|
if clear_recurrency and recurrency is not None:
|
||||||
|
return _err("'clear_recurrency' and 'recurrency' cannot be used together.")
|
||||||
|
if clear_reminder and (reminder_unit is not None or reminder_value is not None):
|
||||||
|
return _err(
|
||||||
|
"'clear_reminder' cannot be used together with 'reminder_unit'/'reminder_value'."
|
||||||
|
)
|
||||||
|
if (reminder_unit is None) != (reminder_value is None):
|
||||||
|
return _err("'reminder_unit' and 'reminder_value' must be provided together.")
|
||||||
|
|
||||||
if (
|
if (
|
||||||
text is None
|
text is None
|
||||||
@@ -963,10 +998,16 @@ def update_task(
|
|||||||
and not clear_due_date
|
and not clear_due_date
|
||||||
and assignee_ids is None
|
and assignee_ids is None
|
||||||
and list_id is None
|
and list_id is None
|
||||||
|
and recurrency is None
|
||||||
|
and not clear_recurrency
|
||||||
|
and reminder_unit is None
|
||||||
|
and not clear_reminder
|
||||||
):
|
):
|
||||||
return _err(
|
return _err(
|
||||||
"At least one of 'text', 'description', 'category_id', 'due_date',"
|
"At least one of 'text', 'description', 'category_id', 'due_date',"
|
||||||
" 'clear_due_date', 'assignee_ids', or 'list_id' must be provided."
|
" 'clear_due_date', 'assignee_ids', 'list_id', 'recurrency',"
|
||||||
|
" 'clear_recurrency', 'reminder_unit'/'reminder_value', or"
|
||||||
|
" 'clear_reminder' must be provided."
|
||||||
)
|
)
|
||||||
|
|
||||||
params: dict[str, Any] = {"metaId": task_id}
|
params: dict[str, Any] = {"metaId": task_id}
|
||||||
@@ -986,6 +1027,33 @@ def update_task(
|
|||||||
if list_id is not None:
|
if list_id is not None:
|
||||||
params["taskListId"] = list_id
|
params["taskListId"] = list_id
|
||||||
|
|
||||||
|
recurrency_descriptor: dict[str, Any] = {}
|
||||||
|
if clear_recurrency:
|
||||||
|
recurrency_descriptor["recurrency"] = "NONE"
|
||||||
|
elif recurrency is not None:
|
||||||
|
recurrency_descriptor["recurrency"] = recurrency
|
||||||
|
if recurrency_interval is not None:
|
||||||
|
recurrency_descriptor["recurrencyInterval"] = recurrency_interval
|
||||||
|
if rrule is not None:
|
||||||
|
recurrency_descriptor["rrule"] = rrule
|
||||||
|
if recurrency_descriptor:
|
||||||
|
params["recurrencyDescriptor"] = recurrency_descriptor
|
||||||
|
|
||||||
|
if clear_reminder:
|
||||||
|
params["reminder"] = {
|
||||||
|
"reminderUnit": "",
|
||||||
|
"reminderValue": 0,
|
||||||
|
"reminderType": "SNOOZE",
|
||||||
|
"localId": 0,
|
||||||
|
}
|
||||||
|
elif reminder_unit is not None and reminder_value is not None:
|
||||||
|
params["reminder"] = {
|
||||||
|
"reminderUnit": reminder_unit,
|
||||||
|
"reminderValue": reminder_value,
|
||||||
|
"reminderType": "SNOOZE",
|
||||||
|
"localId": 0,
|
||||||
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_authenticated_call("taskupdate2", params)
|
_authenticated_call("taskupdate2", params)
|
||||||
except RuntimeError as exc:
|
except RuntimeError as exc:
|
||||||
|
|||||||
Reference in New Issue
Block a user