From c412c24c867e4e81636e2981fcef7eb940e75c19 Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Wed, 15 Apr 2026 15:32:12 +0200 Subject: [PATCH] feat: add like_post tool via wallmood endpoint (v0.4.2) Co-Authored-By: Claude Sonnet 4.6 --- README.md | 3 ++- SPEC.md | 21 ++++++++++++++- pyproject.toml | 2 +- src/mcp_familywall/server.py | 50 ++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9604bb4..be2c483 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, and tasks directly from Claude. -## Features (v0.4.0) +## Features (v0.4.2) ### Read @@ -17,6 +17,7 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your - `update_task` -- update the text/description of an existing task - `toggle_task` -- mark a task complete or reopen it - `delete_task` -- permanently delete a task +- `like_post` -- like or unlike a wall post/activity ## Requirements diff --git a/SPEC.md b/SPEC.md index 19adeef..a30faaf 100644 --- a/SPEC.md +++ b/SPEC.md @@ -266,6 +266,24 @@ mit `{"a00": {"un": {"un": {"message": "missing value in: id"}}}}` auf Top-Level → wird vom fw_client fälschlich als Erfolg interpretiert. Daher ist der korrekte Parameter-Name kritisch. +### `wallmood` – Wall-Post liken / unliken +POST https://api.familywall.com/api/wallmood +Content-Type: application/x-www-form-urlencoded + +**Body-Parameter (zu verifizieren):** + +| Parameter | Pflicht | Wert | +|---|---|---| +| `wallId` | ja | Post-ID aus `get_activities` (Format `wall/23431854_31119189`) | +| `moodType` | vermutlich ja | `"LIKE"` zum Liken, `"NONE"` zum Unliken (zu verifizieren) | + +**Verhalten:** Gleicher Endpoint für Like und Unlike. Mechanismus (Toggle vs. explizit) +und genaue Parameter-Namen sind noch zu verifizieren via `FW_DEBUG=1`. + +Ein Like erzeugt serverseitig einen neuen Wall-Eintrag (Nebeneffekt). + +**Response-Struktur:** zu verifizieren beim ersten echten Call + ## Noch zu verifizieren - ~~Exakter Wert für `type`-Parameter beim Login~~ → nicht senden (verifiziert per JS-Analyse) @@ -279,4 +297,5 @@ kritisch. - ~~`taskcreate2`: Response-Struktur~~ → `a00.r.r` = vollständiges Task-Objekt (verifiziert) - ~~`taskupdate2`: ob `taskListId` Pflichtfeld ist~~ → **nein**, nicht erforderlich (verifiziert) - ~~`taskmark`: korrekter Parameter-Name~~ → **`taskId`** (nicht `metaId`!) (verifiziert) -- ~~`metadelete`: korrekter Parameter-Name + Response-Struktur~~ → **`id`**, Response `"true"` (verifiziert) \ No newline at end of file +- ~~`metadelete`: korrekter Parameter-Name + Response-Struktur~~ → **`id`**, Response `"true"` (verifiziert) +- `wallmood`: Parameter-Namen (`wallId`?, `moodType`?), Toggle vs. explizit, Response-Struktur \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 45bc8dc..de5e79d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mcp-familywall" -version = "0.3.2" +version = "0.4.2" 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/server.py b/src/mcp_familywall/server.py index 0531834..f0203a9 100644 --- a/src/mcp_familywall/server.py +++ b/src/mcp_familywall/server.py @@ -471,6 +471,56 @@ def delete_task(task_id: str) -> str: return json.dumps({"deleted": True, "id": task_id}, ensure_ascii=False, indent=2) +# --------------------------------------------------------------------------- +# Tool: like_post +# --------------------------------------------------------------------------- + + +@mcp.tool() +def like_post(post_id: str, like: bool = True) -> str: + """Like or unlike a wall post/activity. + + Args: + post_id: Wall post ID from get_activities (e.g. ``wall/23431854_31119189``). + like: ``True`` to like the post, ``False`` to unlike. + + Returns: + JSON success indicator or an error message. + """ + # wallmood is a toggle endpoint — same endpoint for like and unlike. + # The 'like' parameter controls the intended state; since the endpoint + # toggles server-side state, it is sent as 'moodType' to allow the server + # to differentiate. Exact parameter names to be verified via FW_DEBUG=1. + params: dict[str, Any] = { + "wallId": post_id, + "moodType": "LIKE" if like else "NONE", + } + + try: + data = _authenticated_call("wallmood", params) + except RuntimeError as exc: + return f"Error: {exc}" + + # The response structure is not yet fully verified — return raw JSON + # if the expected shape is absent so the caller can inspect it. + try: + result_data = data["a00"]["r"]["r"] + if result_data is None: + raise KeyError("empty result") + except (KeyError, TypeError): + return json.dumps( + {"warning": "Unexpected wallmood response structure", "raw": data}, + ensure_ascii=False, + indent=2, + ) + + return json.dumps( + {"liked": like, "id": post_id}, + ensure_ascii=False, + indent=2, + ) + + # --------------------------------------------------------------------------- # Factory # ---------------------------------------------------------------------------