From 8276647fcfb748d9cb14861043bd50c0b80e8c61 Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Wed, 15 Apr 2026 14:15:20 +0200 Subject: [PATCH] feat: add get_activities tool via wallget endpoint (v0.3.0) --- SPEC.md | 32 ++++++++++++++++ pyproject.toml | 2 +- src/mcp_familywall/__init__.py | 2 +- src/mcp_familywall/server.py | 70 ++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 2 deletions(-) diff --git a/SPEC.md b/SPEC.md index 7bcff1b..ca3b81e 100644 --- a/SPEC.md +++ b/SPEC.md @@ -135,6 +135,38 @@ Bekannte Systembezeichnungen werden deutsch übersetzt: Unbekannte Bezeichnungen werden unverändert zurückgegeben. Mapping-Tabelle bei Bedarf erweitern. +### `wallget` – Aktivitäten (Wall) abrufen +POST https://api.familywall.com/api/wallget +Content-Type: application/x-www-form-urlencoded + +**Body-Parameter:** + +| Parameter | Wert | +|---|---| +| `nb` | Anzahl Einträge (z.B. `"20"`) | +| `date` | optional, für Paginierung (Datum des letzten Eintrags) | +| `accountId` | optional | +| `type` | optional | +| `nested` | optional | +| `masterNested` | optional | +| `sortBy` | optional | + +**Response-Struktur:** zu verifizieren beim ersten echten Call + +### `wallactivityget` – Einzelne Aktivität abrufen +POST https://api.familywall.com/api/wallactivityget +Content-Type: application/x-www-form-urlencoded + +**Body-Parameter:** + +| Parameter | Wert | +|---|---| +| `accountId` | optional | +| `masterNested` | optional | + +**Response-Struktur:** zu verifizieren beim ersten echten Call +(Endpoint noch nicht implementiert — für spätere Versionen) + ## Debug-Logging Wenn die Umgebungsvariable `FW_DEBUG=1` gesetzt ist, loggt `fw_client.py` diff --git a/pyproject.toml b/pyproject.toml index 2604b77..81f3cb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mcp-familywall" -version = "0.2.5" +version = "0.3.0" description = "MCP server for Family Wall — read your family's lists and tasks via Claude" readme = "README.md" requires-python = ">=3.12" diff --git a/src/mcp_familywall/__init__.py b/src/mcp_familywall/__init__.py index fe404ae..493f741 100644 --- a/src/mcp_familywall/__init__.py +++ b/src/mcp_familywall/__init__.py @@ -1 +1 @@ -__version__ = "0.2.5" +__version__ = "0.3.0" diff --git a/src/mcp_familywall/server.py b/src/mcp_familywall/server.py index d60316f..ac6524f 100644 --- a/src/mcp_familywall/server.py +++ b/src/mcp_familywall/server.py @@ -269,6 +269,76 @@ def get_tasks(list_id: str, only_open: bool = True) -> str: return json.dumps(result, ensure_ascii=False, indent=2) +# --------------------------------------------------------------------------- +# Tool: get_activities +# --------------------------------------------------------------------------- + + +@mcp.tool() +def get_activities(limit: int = 20) -> str: + """Return recent Family Wall wall activities (posts, comments, photos, …). + + Uses the wallget endpoint. Response structure is not yet verified against + a live API call — the raw response is returned when no known pattern is + matched, so the structure can be inspected on the first real call. + + Args: + limit: Maximum number of activities to return (default 20). + + Returns: + JSON string — list of objects with keys: + id, type, text, date, author. + Falls back to raw API response when the structure is unrecognised. + """ + try: + email, password = get_credentials() + except RuntimeError as exc: + return f"Error: {exc}" + + try: + with FamilyWallClient() as client: + client.login(email, password) + data = client.call("wallget", {"nb": str(limit)}) + client.logout() + except FamilyWallError as exc: + return f"Error: {exc}" + except Exception as exc: + return f"Connection error: {exc}" + + # Try known response patterns; fall back to raw JSON for verification. + raw_activities: list[dict[str, Any]] | None = None + try: + candidate = data["a00"]["r"]["r"] + if isinstance(candidate, list): + raw_activities = candidate + elif isinstance(candidate, dict) and isinstance(candidate.get("updatedCreated"), list): + raw_activities = candidate["updatedCreated"] + except (KeyError, TypeError): + pass + + if raw_activities is None: + # Response structure not yet verified — return raw JSON for inspection. + return json.dumps( + {"warning": "Unexpected wallget response structure", "raw": data}, + ensure_ascii=False, + indent=2, + ) + + result = [] + for item in raw_activities: + result.append( + { + "id": item.get("metaId"), + "type": item.get("type"), + "text": item.get("text") or item.get("comment"), + "date": item.get("date") or item.get("createdDate"), + "author": item.get("authorName") or item.get("author"), + } + ) + + return json.dumps(result, ensure_ascii=False, indent=2) + + # --------------------------------------------------------------------------- # Factory # ---------------------------------------------------------------------------