Adds 4 new MCP tools for the Family Wall recipe box: - get_recipes: list all family recipes via metasync id='recipe' - get_recipe: fetch full recipe detail by id (filters from metasync response) - create_recipe: create a new recipe via mprecipeput (params use 'recipe.' prefix) - delete_recipe: delete a recipe via metadelete (same endpoint as tasks) Verified endpoints and parameter names via FW_DEBUG=1 probe scripts. All 4 tools pass the create → read → get_single → delete integration test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
15 KiB
Family Wall API – Spezifikation
Erarbeitet durch Browser-Traffic-Analyse und React-Fiber-Analyse (April 2026). Es gibt keine offizielle API-Dokumentation.
Base URL
https://api.familywall.com/api
Authentifizierung
Login
POST https://api.familywall.com/api/log2in Content-Type: application/x-www-form-urlencoded
Request-Parameter:
| Parameter | Wert |
|---|---|
identifier |
E-Mail-Adresse |
password |
Passwort |
type |
"email" (verifiziert) |
Response (Erfolg):
{ "r": { "r": <SessionObject> } }
Response (Fehler):
{ "ex": { "ex": <ErrorObject> } }
{ "un": { "un": <ErrorObject> } }
Der Server setzt nach erfolgreichem Login ein Session-Cookie:
Set-Cookie: JSESSIONID=<session-id>
Folgecalls (nach Login)
| Cookie | JSESSIONID=<session-id> |
| Header | Tokencsrf: <session-id> (identisch zur JSESSIONID) |
| Content-Type | application/x-www-form-urlencoded |
Logout
POST https://api.familywall.com/api/log2out
Keine Parameter. Session wird serverseitig invalidiert.
Session-Strategie
Kein Session-Caching. Jeder MCP-Tool-Call führt folgende Sequenz aus:
POST /api/log2in → Session-ID
POST /api/<endpoint> → Nutzdaten (ggf. mehrere Calls in einer Session)
POST /api/log2out → Session invalidieren
Credentials (E-Mail + Passwort) werden einmalig via mcp-familywall setup
im OS Keyring gespeichert (Keys: email, password).
Fehlerbehandlung
Silent-Fail Warnung
Die API gibt Fehler manchmal NICHT auf Top-Level zurück, sondern eingebettet:
{"a00": {"un": {"un": {"message": "missing value in: taskId"}}}}
fw_client.py prüft beide Ebenen (a00.un.un und Top-Level ex/un)
und wirft FamilyWallError. Nie eine Response als Erfolg werten ohne
beide Fehlerebenen zu prüfen.
Sentinel-Wert $empty
Das FiZ-Server-Framework nutzt $empty als Sentinel-String um optionale
Felder zu löschen. Alle anderen Werte ("", null, "null", "0",
"-1", "remove", "clear", Epoch-Timestamps) werden vom Server mit
"is not a valid Date" abgelehnt.
Aktuell genutzt für:
dueDate=$empty→ löscht Fälligkeitsdatum intaskupdate2
Gefunden durch: React-Fiber-Analyse des nativen datetime-local-Inputs –
nach Klick auf "Löschen" im Custom-Datepicker wird der Input-Wert auf
"$empty" gesetzt, was beim Speichern an die API gesendet wird.
Bekannte Endpoints
famlistfamily – Kreise + Mitglieder abrufen
POST https://api.familywall.com/api/famlistfamily
Body-Parameter: keine
Response-Struktur:
a00.r.r[] → Kreise
.metaId → Kreis-ID (z.B. "family/23431854")
.name → Kreis-Name
.members[] → Mitglieder des Kreises
.accountId → numerische User-ID
.firstName → Anzeigename (bevorzugen)
.name → E-Mail als Fallback
.role → Familienrolle (Parent/Child/Unknown)
.right → Berechtigung (SuperAdmin etc.)
.color → Profilfarbe (#RRGGBB)
.medias[0].pictureUrl → Avatar-URL
.identifiers[type=Email].value → E-Mail-Adresse
accgetallfamily – Listen, Tasks, Kategorien abrufen
POST https://api.familywall.com/api/accgetallfamily
Body-Parameter:
| Parameter | Wert |
|---|---|
a01call |
"taskcategorysync" |
a02call |
"tasksync" |
Response-Struktur:
a00.r.r[] → Kategorien (taskcategorysync)
.metaId → Kategorie-ID
.name → Kategoriename (Systembezeichnung)
.taskListType → SHOPPING_LIST oder TODOS
.sortingIndexByTaskList → Sortierreihenfolge pro Liste
.rights.canDelete → "true" = custom, null = System
.locale → Sprachcode (de/en/fr/...), fehlt bei custom
a02.r.r.updatedCreated[] → Tasks (tasksync)
.metaId → Task-ID
.text → Aufgabentext
.description → optionale Beschreibung
.taskListId → Listen-ID
.complete → "true" / "false" (String!)
.taskCategoryId → Kategorie-ID (optional)
.dueDate → Fälligkeitsdatum (ISO 8601, optional)
.assignee[] → Liste von Member-IDs (optional)
.assigneeIds[] → alternativ zu assignee[]
wallget – Wall-Aktivitäten abrufen
POST https://api.familywall.com/api/wallget
Response-Struktur:
a00.r.r[]
.metaId → Post-ID (z.B. "wall/23431854_31119189")
.type → STATUS, FAMILY_CREATED, etc.
.text → Post-Text
.modifDate → Timestamp (ISO 8601)
.creator.accountId → Author-ID
.moodMap → {"<accountId>": ["STAR"]} für Likes
.moodStarShortcut → true wenn geliked
.comments[] → Kommentare
taskcreate2 – Task erstellen
POST https://api.familywall.com/api/taskcreate2
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
taskListId |
ja | Listen-metaId |
text |
ja | Aufgabentext |
description |
nein | Beschreibung |
taskCategoryId |
nein | Kategorie-metaId (vollständig, z.B. taskCategory/23431854_200) |
dueDate |
nein | ISO 8601 (z.B. 2026-04-30T18:00:00) |
assignee |
nein | Member-accountId, mehrfach sendbar für mehrere Zuweisungen |
Response:
a00.r.r → vollständiges Task-Objekt
.metaId → neue Task-ID
taskupdate2 – Task aktualisieren
POST https://api.familywall.com/api/taskupdate2
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
metaId |
ja | Task-metaId |
text |
nein | neuer Titel |
description |
nein | neue Beschreibung |
taskCategoryId |
nein | neue Kategorie-metaId |
dueDate |
nein | ISO 8601 oder $empty zum Löschen |
assignee |
nein | Member-accountId (mehrfach sendbar), "" zum Entfernen aller |
taskListId |
nein | neue Listen-metaId (verschiebt Task) |
Hinweis: taskListId ist NICHT Pflicht beim Update.
Response:
a00.r.r → vollständiges Task-Objekt
taskmark – Task abhaken/wiedereröffnen
POST https://api.familywall.com/api/taskmark
Body-Parameter:
| Parameter | Wert |
|---|---|
taskId |
Task-metaId ⚠️ nicht metaId! |
complete |
"true" oder "false" (String!) |
Response:
a00.r.r → Task-Objekt mit lastAction: "MARK_COMPLETED"
metadelete – Task löschen
POST https://api.familywall.com/api/metadelete
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Task-metaId ⚠️ nicht metaId! |
Response:
a00.r.r → "true" (String)
wallmood – Post liken
POST https://api.familywall.com/api/wallmood
Body-Parameter:
| Parameter | Wert |
|---|---|
wall_message_id |
Post-metaId ⚠️ nicht wallId oder id! |
moodType |
"STAR" für Like |
Bekannte Einschränkungen:
- Unlike: Endpoint/Parameter unbekannt (Service Worker verschlüsselt Request-Body)
- Self-Like: API antwortet 200, macht aber serverseitig nichts
moodType="NONE"und andere Werte haben keine Wirkung
Response:
a00.r.r → Wall-Objekt mit moodMap, refAction: "MOOD_STAR"
taskcategoryput – Kategorie erstellen/aktualisieren
POST https://api.familywall.com/api/taskcategoryput
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
name |
ja | Kategoriename |
emoji |
nein | Unicode-Emoji oder beliebiger String |
Hinweis: Kategorien sind family-wide – listId hat keine Wirkung.
Response:
a00.r.r → Kategorie-Objekt mit metaId
taskcategorydelete – Kategorie löschen
POST https://api.familywall.com/api/taskcategorydelete
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Kategorie-metaId ⚠️ nicht metaId! |
Hinweis: System-Kategorien (rights.canDelete=null) können technisch
gelöscht werden, sind dann aber dauerhaft weg und nicht wiederherstellbar.
MCP-Server schützt dagegen durch Check auf rights.canDelete.
taskcreatelist – Liste erstellen
POST https://api.familywall.com/api/taskcreatelist
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
name |
ja | Listen-Name (max 200 Zeichen) |
taskListType |
ja | "SHOPPING_LIST" oder "TODOS" |
sharedToAll |
nein | "true" / "false" (default: "true") |
color |
nein | Hex-Farbwert z.B. "#4784EC" |
emoji |
nein | Unicode-Emoji z.B. "🛒" |
Response:
a00.r.r → vollständiges Listen-Objekt
.metaId → neue Listen-ID (z.B. "taskList/23431854_29759623")
.name → Listen-Name
.taskListType → SHOPPING_LIST oder TODOS
.sharedToAll → "true" / "false"
.emoji → Unicode-Emoji (fehlt wenn nicht gesetzt)
.color → Hex-Farbwert z.B. "#E53935" (fehlt wenn nicht gesetzt)
.rights.canDelete → "true" (user-created lists)
Verifiziert am: 2026-04-16 via FW_DEBUG=1
taskdeletelist – Liste löschen
POST https://api.familywall.com/api/taskdeletelist
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Listen-metaId ⚠️ nicht listId oder taskListId! |
Response:
a00.r.r → "true" (String)
Hinweis: Löscht die Liste und alle enthaltenen Tasks unwiderruflich.
System-Listen (rights.canDelete fehlt oder null) sind nicht löschbar.
MCP-Server prüft dies vor dem Löschen via taskgettasklists.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
taskgettasklists – Listen abrufen
POST https://api.familywall.com/api/taskgettasklists
Body-Parameter: keine
Response-Struktur:
a00.r.r[] → Liste aller Task-Listen
.metaId → Listen-ID (z.B. "taskList/23431854_29740942")
.name → Systembezeichnung oder Benutzer-Name
.taskListType → SHOPPING_LIST oder TODOS
.emoji → Unicode-Emoji oder "" (leerer String = kein Emoji)
.color → Hex-Farbwert z.B. "#E53935" (fehlt wenn nicht gesetzt)
.remainingTaskNumber → offene Tasks (String)
.totalTaskNumber → Gesamt-Tasks (String)
.sharedToAll → "true" / "false"
.sharedMemberIds[] → Member-accountIds
.rights.canDelete → "true" = löschbar, fehlt/leer = Systemliste
.systemId → vorhanden nur bei Systemlisten (z.B. "-10", "-11")
Hinweis emoji/color:
emoji: Systemlisten liefern"", user-created Listen liefern den Emoji-String oder""wenn kein Emoji gesetzt. Normalisierung:""→nullim MCP-Server.color: Fehlt komplett wenn nicht gesetzt (nichtnulloder""). Normalisierung: fehlendes Feld →nullim MCP-Server.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
Systembezeichnungen für Listen-Namen
| Systembezeichnung | Deutsch |
|---|---|
SYS-CAT-SHOPPINGLIST |
Einkaufsliste |
SYS-CAT-TODOLIST |
Aufgaben |
Debug-Logging
Wenn die Umgebungsvariable FW_DEBUG=1 gesetzt ist, loggt fw_client.py
vollständige Request-Bodies und Responses nach stderr.
Wichtig: Keine Secrets in Debug-Ausgaben (Passwort maskieren).
Wann FW_DEBUG=1 nutzen:
- Neue Endpoints verifizieren
- Parameter-Namen unbekannt
- Silent-Fail debuggen
- Service Worker blockiert Browser-DevTools
Service Worker
Die Family Wall Web-App registriert einen Service Worker der bestimmte HTTP-Requests abfängt und modifiziert bevor sie das Netzwerk erreichen. Betroffen sind u.a. Unlike-Calls und möglicherweise andere schreibende Operationen.
Folge: Browser-DevTools Network-Tab und JS-Interceptoren (XHR/Fetch)
zeigen nicht den echten Request-Body für diese Calls.
Lösung: FW_DEBUG=1 auf MCP-Server-Seite zeigt was tatsächlich gesendet wird.
mprecipeput – Rezept erstellen
POST https://api.familywall.com/api/mprecipeput
Wichtig: Alle Parameter haben das Präfix recipe. (verifiziert via FW_DEBUG=1).
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
recipe.name |
ja | Rezeptname |
recipe.isRecipe |
ja | immer "true" |
recipe.description |
nein | Kurzbeschreibung |
recipe.ingredients |
nein | Zutaten als Freitext (Zeilen mit \n trennen) |
recipe.instructions |
nein | Anleitung als Freitext (Zeilen mit \n trennen) |
recipe.prepTime |
nein | Zubereitungszeit in Minuten (String, z.B. "30") |
recipe.cookTime |
nein | Kochzeit in Minuten (String, z.B. "60") |
recipe.serves |
nein | Portionen (String, z.B. "4") |
recipe.url |
nein | externe URL |
Response:
a00.r.r → vollständiges Rezept-Objekt
.metaId → neue Rezept-ID (z.B. "recipe/23431854_10968866")
.name → Rezeptname
.description → Beschreibung
.ingredients → Zutaten Freitext (API liefert \r\n als Zeilenumbrüche)
.ingredientsList[] → auto-geparste Zutaten (read-only, vom Server generiert)
.metaId → "recipeIngredient/<id>"
.name → Zutatname
.instructions → Anleitung Freitext
.prepTime → Zubereitungszeit als String ("30")
.cookTime → Kochzeit als String ("60")
.serves → Portionen als String ("4")
.url → externe URL (fehlt wenn leer)
.isRecipe → "true"
.isFavorite → "false"
.recipeCategories[] → []
.recipeCategoryIdList[] → []
.rights.canDelete → "true" für eigene Rezepte
.rights.canUpdate → "true" für eigene Rezepte
.familyId, .accountId, .creationDate, .moodMap, .moodStarShortcut
Verifiziert am: 2026-04-16 via FW_DEBUG=1
metasync (id='recipe') – Alle Rezepte abrufen
POST https://api.familywall.com/api/metasync
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
"recipe" (lowercase, enum-Wert) |
Response-Struktur:
a00.r.r.updatedCreated[] → Liste aller Rezepte der Familie
→ Felder identisch mit mprecipeput-Response (siehe oben)
Hinweis: Der Parameter id nimmt einen MetaIdTypeEnum-Wert, kein tatsächliches Objekt.
Nur "recipe" (lowercase) funktioniert – "RECIPE", "Recipe" und andere Schreibweisen
liefern MetaIdTypeEnum-Fehler.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
metadelete – Rezept löschen
POST https://api.familywall.com/api/metadelete
Identisch mit dem Task-Löschen-Endpoint. Funktioniert auch für Rezepte.
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Rezept-metaId (z.B. "recipe/23431854_10968866") |
Response:
a00.r.r → "true" (String)
Verifiziert am: 2026-04-16 via FW_DEBUG=1
Offene Punkte
- Unlike-Endpoint (Service Worker blockiert Analyse)
- Erinnerungen (reminder) – nur Premium-Account
- Wiederholungen (repeat) – nur Premium-Account
- Sortierung von Kategorien via API
- update_recipe (Rezept aktualisieren) – Endpoint: mprecipeput mit metaId
- mpadditemtolist (Zutaten aus Rezept → Einkaufsliste)