Files
mcp-familywall/SPEC.md
T

147 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Family Wall API Spezifikation
Erarbeitet durch Browser-Traffic-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` | nicht senden — wird als `undefined` ignoriert (verifiziert per JS-Analyse) |
| `clientId` | weglassen |
| `clientSecret` | weglassen |
| `generateAutologinToken` | weglassen |
| `countryCode` | weglassen |
**Response (Erfolg):**
```json
{ "a00": { "r": { "r": <SessionObject> }, "cn": "log2in" } }
```
`SessionObject` enthält u.a. `tokenCsrf` und `webApiUrl`.
`tokenCsrf` ist die Session-ID identisch zur `JSESSIONID` im Cookie.
**Response (Fehler):**
```json
{ "ex": { "ex": <ErrorObject> } }
{ "un": { "un": <ErrorObject> } }
```
Der Server setzt nach erfolgreichem Login ein Session-Cookie:
Set-Cookie: JSESSIONID=<session-id> (= tokenCsrf)
### Folgecalls (nach Login)
Alle API-Calls nach dem Login benötigen:
| | |
|---|---|
| **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
Content-Type: application/x-www-form-urlencoded
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
POST /api/log2out → Session invalidieren
Credentials (E-Mail + Passwort) werden einmalig via `mcp-familywall setup`
im OS Keyring gespeichert (Keys: `email`, `password`). Kein Keyring-Eintrag
für `session_id`.
## Bekannte Endpoints
### `famlistfamily` Kreise abrufen
POST https://api.familywall.com/api/famlistfamily
Content-Type: application/x-www-form-urlencoded
**Body-Parameter:** keine (verifiziert)
**Response-Struktur (verifiziert):**
```
a00.r.r[] → Kreise
.metaId → eindeutige Kreis-ID
.name → Kreisname
```
### `accgetallfamily` Listen + Tasks abrufen
POST https://api.familywall.com/api/accgetallfamily
Content-Type: application/x-www-form-urlencoded
**Body-Parameter:**
| Parameter | Wert |
|---|---|
| `a01call` | `"taskcategorysync"` |
| `a02call` | `"tasksync"` |
Hinweis: `a03call=tasklistsync` ist **kein gültiger Endpoint** — API antwortet mit
"The call tasklistsync is not registered". Nicht verwenden.
`partnerScope`, `a03id`, `withStateBean` werden weggelassen.
**Response-Struktur (verifiziert):**
```
a00 → famlistfamily-Daten (Kreise) Nebeneffekt, nicht verwendet
a01.r.r.updatedCreated[] → taskcategorysync (Einkaufskategorien/Abteilungen)
.sortingIndexByTaskList → dict, Keys = Listen-IDs (z.B. "taskList/23431854_29740942")
→ Quelle der Listen-IDs (Namen/Zähler noch unbekannt)
a02.r.r.updatedCreated[] → tasksync (Tasks)
.metaId → eindeutige Task-ID
.text → Aufgabentext
.description → optionale Beschreibung
.taskListId → Zugehörigkeit zur Liste (= Listen-ID aus sortingIndexByTaskList)
.complete → "true" / "false" (String, nicht Boolean!)
```
## Systembezeichnungen für Listen-Namen
Bekannte Systembezeichnungen werden deutsch übersetzt:
| Systembezeichnung | Deutsch |
|---|---|
| `SYS-CAT-SHOPPINGLIST` | `Einkaufsliste` |
Unbekannte Bezeichnungen werden unverändert zurückgegeben.
Mapping-Tabelle bei Bedarf erweitern.
## Debug-Logging
Wenn die Umgebungsvariable `FW_DEBUG=1` gesetzt ist, loggt `fw_client.py`
vollständige Request-Bodies und Responses nach stderr. Dient zur Verifikation
offener Punkte (z.B. `type`-Parameter beim Login, Kreis-Felder in Response).
**Wichtig:** Keine Secrets in Debug-Ausgaben (Passwort maskieren).
## Noch zu verifizieren
- ~~Exakter Wert für `type`-Parameter beim Login~~ → nicht senden (verifiziert per JS-Analyse)
- ~~Response-Struktur von `famlistfamily` (Kreise)~~ → a00.r.r[], metaId + name (verifiziert)
- ~~Ob `a03call=tasklistsync` benötigt wird~~ → **nein**, kein gültiger Endpoint (verifiziert)
- Listen-IDs aus `a01.r.r.updatedCreated[].sortingIndexByTaskList`-Keys (verifiziert)
- Listen-Namen und Zähler (remainingTaskNumber, totalTaskNumber) → noch unbekannt
- Kreis-Zuordnung in `accgetallfamily`-Response → noch offen
- ~~Ob `partnerScope` / `withStateBean` benötigt werden~~ → nein (verifiziert)
- Session-Lebensdauer (irrelevant da kein Caching)