Files
mcp-familywall/CLAUDE.md
T
marcus 0e7c4da362 feat(wall-posts): add wall post reading/writing with comments (v1.3.0)
- Add get_wall_posts: read recent wall posts with like/comment counts
- Add create_wall_post: publish new status posts to the wall
- Add add_comment: add comments to wall posts and activities
- like_post already supports both wall posts and activities (v1.2.0)
- Update README.md with new Wall & Activities section
- Update CLAUDE.md with v1.3.0 and tool reorganization
- Update CHANGELOG.md with v1.3.0 release notes
- Add wallpublish and walladdComment documentation to SPEC.md

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-17 23:19:37 +02:00

9.7 KiB
Raw Blame History

mcp-familywall

Note: This file is intentionally written in German (developer preference). Code, docstrings, and commit messages are in English.

Kontext

Dieses Projekt entwickelt mcp-familywall einen MCP-Server für den Zugriff auf Family Wall (familywall.com). Der MCP-Server läuft lokal und wird in Claude Desktop eingebunden.

Infrastruktur

Family Wall API https://api.familywall.com/api
Gitea https://gitea.gecheckt.de/marcus/mcp-familywall
Lokaler Code D:\Dev\Projects\mcp-familywall
Sprache Python 3.12+, uv, MCP SDK, httpx, keyring, click, rich

Deploy-Workflow (nach jeder Code-Änderung)

  1. Claude Code committet und pusht (bei Berechtigungsfehler: bis zu 2 Retries, je 1s warten)
  2. Marcus installiert lokal und startet Claude Desktop neu

Aktueller Stand

Version: v1.3.0 ← aktuell

Implementierte Tools

Kategorie Tools
Wall & Aktivitäten get_wall_posts, create_wall_post, add_comment, like_post
Kreise & Mitglieder get_circles, get_members, create_circle, update_circle, delete_circle, add_member_to_circle
Listen & Tasks get_lists, get_tasks, get_categories, get_activities, create_list, update_list, delete_list, create_category, delete_category, create_task, update_task, toggle_task, delete_task, clear_list
Rezeptbox get_recipe_categories, get_recipe_box, get_recipes, get_recipe, create_recipe, update_recipe, delete_recipe
Essensplaner get_meal_plan, add_recipe_to_meal_plan, add_meal_to_meal_plan, add_meal_note, delete_meal_plan_entry

Roadmap (Nächstes)

  • v2.0: Weitere Wall-Post Features (Edits, Deletes, Emoji-Reactions beyond STAR)

Historische Meilensteine (kompakt)

  • v0.1v0.4: Lesen (Kreise, Listen, Tasks, Kategorien), Schreiben (Tasks, Kategorien)
  • v0.5: Listen-Management (create/delete), emoji + color
  • v0.6v0.8: Rezeptbox vollständig, Kreismanagement, Rezeptkategorien
  • v0.9: Task-Wiederholungen + Erinnerungen (read-only)
  • v0.10v0.11: Essensplaner (read + write)
  • v1.0: Cleanup, Unified errors, Datumsvalidierung, Partial-Failure-Reporting (Details: CHANGELOG.md)
  • v1.1: Task-Recurrency-Write (flat top-level params)
  • v1.2: Task-Reminder-Write via Dot-Notation (reminder.*) — verifiziert 2026-04-17

Architektur-Entscheidungen

Session-Strategie

Kein Session-Caching. Jeder Tool-Call führt Login → API-Call → Logout durch. Optimierung: Mehrere API-Calls in einer Session bündeln (login → call1 → call2 → logout) um unnötige HTTP-Roundtrips zu vermeiden. Credentials liegen im OS Keyring (nur email + password), kein session_id.

Kreise (Scopes)

Family Wall kennt mehrere Kreise (z.B. Familie, erweiterter Familienkreis). Der API-Parameter scope=family/XXXX schaltet den Server-Kontext um.

  • taskgettasklists ohne scope → primärer Kreis; mit scope → angegebener Kreis
  • taskcreatelist mit scope → neue Liste im angegebenen Kreis
  • taskdeletelist mit scope → löscht Liste aus angegebenem Kreis
  • get_lists(scope="family/XXXX") oder get_lists(scope="Kreis-Name") zur Filterung
  • Die Listen-metaId kodiert den Kreis: taskList/<FAMNUM>_<LISTNUM>family/<FAMNUM>

Listen-Namen

Systembezeichnungen (z.B. SYS-CAT-SHOPPINGLIST) werden in deutsche Klarnamen übersetzt. Mapping-Tabelle in modules/lists.py.

Kategorien

  • Kategorien sind family-wide, nicht list-spezifisch (taskcategoryput gilt für alle Listen)
  • System-Kategorien: rights.canDelete=null → nicht löschbar
  • Custom-Kategorien: rights.canDelete="true" → löschbar
  • Locale-Filter: default "de" Custom-Kategorien haben kein locale-Feld und werden immer angezeigt unabhängig vom Locale-Parameter

Fehlerbehandlung

Die API gibt Fehler manchmal als a00.un.un zurück (nicht Top-Level). fw_client.py prüft beides und wirft FamilyWallError. Nie silent-fail als Erfolg werten immer a00.un und Top-Level ex/un prüfen.

Service Worker

Die Family Wall Web-App nutzt einen Service Worker der bestimmte HTTP-Requests abfängt und modifiziert. Browser-DevTools und JS-Interceptoren können den echten Request-Body in diesen Fällen nicht sehen. → Immer FW_DEBUG=1 für Traffic-Analyse nutzen, nicht Browser-DevTools.

Claude Code Implementierungsregeln

  • Feature complete before next feature jedes Feature vollständig implementieren, testen und verifizieren bevor das nächste beginnt
  • Kein destruktives Probing keine Probe-Calls auf System-Kategorien, echte Listen oder echte Tasks; immer Test-Objekte anlegen und danach sofort löschen
  • Fehlerbehandlung: API-Fehler als verständliche Meldung zurückgeben, keine Stacktraces
  • Keine Secrets in stderr-Ausgaben (Passwort bei Debug-Logging maskieren)
  • Type Hints und Docstrings konsequent verwenden (Englisch)
  • Formatter: ruff format, Linter: ruff check, Tests: pytest
  • Alle Texte (Docstrings, Kommentare, README): Englisch
  • Debug-Logging via FW_DEBUG=1 Umgebungsvariable
  • Nach jeder Aufgabe: git commit + push. Bei Berechtigungsfehler: 1s warten, bis zu 2 Retries
  • .gitignore eigenständig pflegen (Credentials, pycache, .venv, .env, *.pyc etc.)
  • README.md + CLAUDE.md im Projekt-Root bei jedem Aufruf aktualisieren
  • Confirmation-Pattern in Docstrings: IMPORTANT: Ask the user for confirmation before calling this tool. für destruktive oder schreibende Operationen

Bekannte API-Eigenheiten und Fallstricke

Sentinel-Wert $empty

Das FiZ-Framework nutzt $empty als Sentinel um optionale Felder zu löschen. Normale Werte wie "", null, "null", "0" werden vom Server abgelehnt. Aktuell genutzt für: dueDate=$empty (Fälligkeitsdatum entfernen)

Silent-Fail via a00.un.un

Fehler bei falschen Parametern kommen nicht immer auf Top-Level:

{"a00": {"un": {"un": {"message": "missing value in: taskId"}}}}

fw_client muss beide Ebenen prüfen

Bekannte Parameter-Namen (verifiziert)

Endpoint Parameter Wert/Format
taskcreate2 taskListId, text, description, taskCategoryId, dueDate, assignee
taskupdate2 metaId, text, description, taskCategoryId, dueDate, assignee, taskListId
taskupdate2 dueDate löschen $empty
taskupdate2 recurrencyDescriptor (flach!) recurrency, recurrencyInterval, rrule, byDay, byMonthDay, recurrencyEndDate, endOccurence als Top-Level-Parameter; löschen: recurrency="NONE"
taskupdate2 Reminder (Dot-Notation!) reminder.reminderUnit (MINUTE/HOUR/DAY), reminder.reminderValue (String-Integer), reminder.reminderType (SNOOZE=aktiv, NONE=entfernen), reminder.localId optional. Entfernen: vollständigen Block mit reminderType=NONE, reminderValue="0", reminderUnit=MINUTE senden. Partielle Updates → task reminder invalid.
taskupdate2 ⚠️ Encoding Recurrency flach top-level. Reminder nur Dot-Notation reminder.* — flache Keys, JSON-String, Brackets werden silent-ignored.
taskmark taskId, complete "true"/"false"
metadelete id metaId des Tasks / Rezepts
wallmood wall_message_id, add, remove/remove.0 Like: add="STAR", remove="$empty"; Unlike: add="$empty", remove.0="STAR" (Array-Dot-Notation)
taskcategoryput name, emoji
taskcategorydelete id metaId der Kategorie
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
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
mprecipeput recipe.name, recipe.isRecipe="true", recipe.description, recipe.ingredients, recipe.instructions, recipe.prepTime, recipe.cookTime, recipe.serves, recipe.url Alle mit recipe.-Prefix!
mprecipeput (Update) zusätzlich recipe.metaId Vorhandene ID → Update statt Create
mprecipeput (Kategorien) recipe.recipeCategoryIdList Mehrfach sendbar; leerer String "" entfernt alle Kategorien
metasync (Rezepte lesen) id="recipe" liefert a00.r.r.updatedCreated[]
acccreatefamily name liefert numerische Kreis-ID als String in a00.r.r
accinvite familyId, identifier, role="Unknown", firstname nur für neue FW-Accounts
accupdatefamily name, scope scope: Kreis-metaId; ohne scope → PRIMARY Kreis; erster Buchstabe wird kapitalisiert
adminwipefamily scope Kreis-metaId; löscht Kreis + alle Inhalte; a00.r.r="true" bei Erfolg

Self-Like-Restriction

Eigene Posts können nicht geliked werden. API antwortet 200, macht aber nichts.

Unlike

Unlike via remove.0=STAR (Array-Dot-Notation). Verifiziert 2026-04-17 via Network-Interceptor.

mpstar / Rezept-Favorit

Service Worker fängt mpstar ab. metamood funktioniert nur auf fremde Inhalte (Self-Reaction-Restriction). Eigene Rezepte können nicht als Favorit markiert werden. Siehe SPEC.md § Offene Punkte.

Test-Credentials (nur für Entwicklung)

E-Mail marcus@gecheckt.de
Passwort Lasdas1234

Hinweis: Das ist ein kostenloser Test-Account ohne Premium-Features. Der echte Account (Premium) hat andere Credentials die im Keyring gespeichert sind.

Hintergrund

Marcus ist Senior Software Engineer (Java, Jakarta EE). Präferenz: State-of-the-Art, Best Practices, saubere Architektur. Automatisierung spart Zeit für die Familie. 🌱