feat: Gruppe 1 – Projektgerüst, Auth, CLI (v0.1.0)

- pyproject.toml: hatchling build, mcp-familywall entry-point, deps
- src/mcp_familywall/__init__.py: version 0.1.0
- src/mcp_familywall/config.py: YAML config loader (schema_version: 1)
- src/mcp_familywall/auth.py: keyring credential resolution (FW_EMAIL/FW_PASSWORD → keyring)
- src/mcp_familywall/fw_client.py: httpx client, login/logout/call, FW_DEBUG logging
- src/mcp_familywall/cli.py: click CLI with setup / check / serve commands
- .gitignore, README.md, CLAUDE.md, SPEC.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-15 12:18:37 +02:00
parent a58c776298
commit 38da31b0cb
10 changed files with 948 additions and 0 deletions
+137
View File
@@ -0,0 +1,137 @@
# 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` | zu verifizieren beim ersten echten Login-Call (vermutlich `"email"`) |
| `clientId` | weglassen |
| `clientSecret` | weglassen |
| `generateAutologinToken` | weglassen |
| `countryCode` | weglassen |
**Response (Erfolg):**
```json
{ "r": { "r": <SessionObject> } }
```
**Response (Fehler):**
```json
{ "ex": { "ex": <ErrorObject> } }
{ "un": { "un": <ErrorObject> } }
```
Der Server setzt nach erfolgreichem Login ein Session-Cookie:
Set-Cookie: JSESSIONID=<session-id>
### 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 (zu verifizieren beim ersten echten Call)
**Response-Struktur:** zu verifizieren beim ersten echten Call
### `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: `partnerScope`, `a03call`, `a03id`, `withStateBean` werden
weggelassen. Falls der Server sie erfordert, beim ersten echten Call
nachbessern.
**Response-Struktur (relevant für v1.0):**
a00.r.r[] → Listen (taskcategorysync)
.metaId → eindeutige Listen-ID
.name → Name (ggf. Systembezeichnung, s.u.)
.taskListType → Typ der Liste
.remainingTaskNumber → offene Einträge (String)
.totalTaskNumber → Gesamteinträge (String)
.<Kreis-Feld> → zu verifizieren beim ersten echten Call
a02.r.r.updatedCreated[] → Tasks (tasksync)
.metaId → eindeutige Task-ID
.text → Aufgabentext
.description → optionale Beschreibung
.taskListId → Zugehörigkeit zur Liste (= metaId der Liste)
.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
- Response-Struktur von `famlistfamily` (Kreise)
- Kreis-Zuordnung in `accgetallfamily`-Response
- Ob `partnerScope` / `withStateBean` benötigt werden
- Session-Lebensdauer (irrelevant da kein Caching)