a76dc0fd51
Verified via FW_DEBUG=1 + systematic param-name probing that the correct parameter is `taskCategoryId` with value = full metaId from get_categories (e.g. taskCategory/23431854_200). Numeric systemCategoryId alone causes API error; full metaId is accepted and stored. Changes: - create_task: add optional category_id parameter → sent as taskCategoryId - update_task: add optional category_id parameter → sent as taskCategoryId; guard now accepts category_id-only updates - get_tasks: expose category_id field in returned task objects - get_categories: update docstring (param name now known) - SPEC.md: document verified taskCategoryId param + clarify categories[] vs taskCategoryId field distinction - scripts/find_category_param.py: discovery script used to find param name Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
150 lines
5.1 KiB
Markdown
150 lines
5.1 KiB
Markdown
# mcp-familywall
|
||
|
||
## Kontext
|
||
|
||
Dieses Projekt entwickelt `mcp-familywall` – einen MCP-Server für den Lesezugriff
|
||
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)
|
||
|
||
## Aktueller Stand
|
||
|
||
### Implementierte Tools (v0.4.10)
|
||
|
||
| Kategorie | Tools |
|
||
|---|---|
|
||
| Kreise | `get_circles`, `get_members` |
|
||
| Listen | `get_lists` |
|
||
| Tasks (Lesen) | `get_tasks` (inkl. `category_id`), `get_categories` |
|
||
| Wall | `get_activities`, `like_post` |
|
||
| Tasks (Schreiben) | `create_task` (inkl. `category_id`), `update_task` (inkl. `category_id`), `toggle_task`, `delete_task` |
|
||
|
||
|
||
## Roadmap
|
||
|
||
- v0.x: Erweiterter Lese- + Schreibzugriff ← aktuell
|
||
- Offen: Unlike (`like_post(like=False)`)
|
||
|
||
|
||
## Referenzprojekt
|
||
|
||
Im Ordner `reference/` liegen Dateien aus einem anderen MCP-Server-Projekt
|
||
als Orientierung für Struktur und Patterns:
|
||
|
||
| Datei | Zweck |
|
||
|---|---|
|
||
| `reference/pyproject.toml` | Projektstruktur, Dependencies, Entry-Points, Build-System |
|
||
| `reference/config.py` | Config-Pattern: YAML laden, validieren, speichern |
|
||
| `reference/auth.py` | Keyring-Integration, Credential-Resolution-Reihenfolge |
|
||
| `reference/cli.py` | Setup-Wizard, check, serve – CLI-Struktur |
|
||
|
||
**Wichtig:** Diese Dateien sind Referenz, kein Copy-Paste. Alle
|
||
Synology/DSM-spezifischen Teile werden nicht übernommen.
|
||
Family Wall nutzt ein anderes Auth-Schema – siehe SPEC.md.
|
||
|
||
## Architektur-Entscheidungen
|
||
|
||
### Session-Strategie
|
||
Kein Session-Caching. Jeder Tool-Call führt Login → API-Call → Logout durch.
|
||
Credentials liegen im OS Keyring (nur `email` + `password`), kein `session_id`.
|
||
|
||
### Kreise (Scopes)
|
||
Family Wall kennt mehrere Kreise (z.B. Familie, erweiterter Familienkreis).
|
||
`get_lists` unterstützt optionalen `scope`-Parameter zur Filterung.
|
||
Ohne `scope` werden alle Kreise zurückgegeben.
|
||
|
||
### Listen-Namen
|
||
Systembezeichnungen (z.B. `SYS-CAT-SHOPPINGLIST`) werden in deutsche
|
||
Klarnamen übersetzt. Mapping-Tabelle in `modules/lists.py`.
|
||
|
||
|
||
## Claude Code – Implementierungsregeln
|
||
|
||
- Keine destruktiven Operationen in v1.0 → kein Confirmation-Pattern erforderlich
|
||
- 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
|
||
- 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 im Projekt-Root pflegen und bei jedem Aufruf aktualisieren
|
||
|
||
|
||
## Implementierungsreihenfolge
|
||
|
||
### Gruppe 1 – Projektgerüst + Auth + CLI ✦ Prio: hoch
|
||
|
||
- `pyproject.toml`: Package `mcp-familywall`, Entry-Point `mcp-familywall`
|
||
- `src/mcp_familywall/config.py`: `~/.config/mcp-familywall/config.yaml`,
|
||
schema_version 1
|
||
- `src/mcp_familywall/auth.py`: Keyring-Service `mcp-familywall`,
|
||
Keys: `email`, `password`. Credential-Resolution:
|
||
1. Umgebungsvariablen `FW_EMAIL`, `FW_PASSWORD`
|
||
2. OS Keyring
|
||
- `src/mcp_familywall/fw_client.py`: HTTP-Client mit `httpx`.
|
||
Methoden: `login()`, `logout()`, `call(endpoint, params)`.
|
||
Debug-Logging wenn `FW_DEBUG=1` (Passwort maskieren).
|
||
- `src/mcp_familywall/cli.py`:
|
||
- `setup`: fragt E-Mail + Passwort, führt Login/Logout durch,
|
||
speichert Credentials im Keyring, gibt Claude-Desktop-Snippet aus
|
||
- `check`: testet Auth und API-Erreichbarkeit
|
||
- `serve`: startet MCP-Server
|
||
|
||
Config-Datei enthält nur:
|
||
```yaml
|
||
schema_version: 1
|
||
```
|
||
|
||
### Gruppe 2 – MCP Tools ✦ Prio: hoch
|
||
|
||
`src/mcp_familywall/server.py` + `src/mcp_familywall/modules/lists.py`
|
||
|
||
**`get_circles`**
|
||
- Ruft `famlistfamily` auf
|
||
- Gibt alle Kreise zurück: `id`, `name`
|
||
- Confirmation: nein
|
||
|
||
**`get_lists`**
|
||
- Signatur: `get_lists(scope: str = None) -> str`
|
||
- Ruft `accgetallfamily` auf (Parameter: `a01call=taskcategorysync`, `a02call=tasksync`)
|
||
- Gibt zurück: `id` (metaId), `name` (übersetzt), `type`, offene Einträge,
|
||
Gesamteinträge, Kreis-Name
|
||
- Ohne `scope`: alle Kreise; mit `scope`: nur dieser Kreis
|
||
- Confirmation: nein
|
||
|
||
**`get_tasks`**
|
||
- Signatur: `get_tasks(list_id: str, only_open: bool = True) -> str`
|
||
- `list_id`: metaId aus `get_lists`
|
||
- Gibt zurück: `id`, `text`, `description`, `completed`
|
||
- Confirmation: nein
|
||
|
||
|
||
## Test-Credentials (nur für Entwicklung)
|
||
|
||
| | |
|
||
|---|---|
|
||
| E-Mail | `marcus@gecheckt.de` |
|
||
| Passwort | `Lasdas1234` |
|
||
|
||
|
||
## 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. 🌱 |