fix: unlike not supported — wallmood is idempotent SET, not toggle (v0.4.5)
Extensive FW_DEBUG=1 testing revealed: - wallmood with moodType=STAR is an idempotent SET operation, not a toggle - Tested: all moodType variations, moodStarShortcut param, 9 alternative endpoints — none could remove a like - Service Worker in the web app prevents intercepting the real unlike payload - like=False now returns a clear error; like=True continues to work correctly - SPEC.md updated with full investigation notes and ruled-out approaches Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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.4)
|
||||
## Features (v0.4.5)
|
||||
|
||||
### Read
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ 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
|
||||
### `wallmood` – Wall-Post liken
|
||||
POST https://api.familywall.com/api/wallmood
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
@@ -278,9 +278,26 @@ Content-Type: application/x-www-form-urlencoded
|
||||
| `moodType` | ja | `"STAR"` (einziger bekannter Wert — entspricht dem Like-Button in der App) |
|
||||
|
||||
**Verhalten (verifiziert):**
|
||||
- Toggle-Mechanismus: gleicher Call zum Liken und Unliken
|
||||
- Erster Aufruf → Like setzen, zweiter Aufruf → Like entfernen
|
||||
- `moodType: "LIKE"` wurde als `"STAR"` serverseitig gespeichert → korrekter Wert ist `"STAR"`
|
||||
- `wallmood` mit `moodType: "STAR"` ist eine **idempotente SET-Operation** — kein Toggle!
|
||||
- Mehrfaches Aufrufen mit denselben Parametern hinterlässt denselben Zustand
|
||||
- `moodType: "LIKE"` wurde serverseitig als `"STAR"` gespeichert → korrekter Wert ist `"STAR"`
|
||||
- Nur für Post-Typ `STATUS` wirksam; `FAMILY_CREATED` und vermutlich System-Posts ignorieren den Call
|
||||
|
||||
**Unlike – nicht implementierbar (Stand: April 2026):**
|
||||
|
||||
Ausgiebig getestete Ansätze, die alle fehlschlugen:
|
||||
|
||||
| Ansatz | Ergebnis |
|
||||
|---|---|
|
||||
| `moodType: "NONE"` / `"REMOVE"` / `"DELETE"` / `""` | moodMap unverändert |
|
||||
| `moodType` ganz weglassen | moodMap unverändert |
|
||||
| `moodStarShortcut: "false"` als Parameter | moodMap unverändert |
|
||||
| Alternative Endpoints: `wallmooddelete`, `wallmoodremove`, `wallmoodelete`, `wallunmood`, `wallcommentdelete`, `wallmoodstar`, `wallstar`, `wallreact`, `wallreactdelete` | alle: `"The call X is not registered"` (502) |
|
||||
| `metadelete` auf Mood-Comment-ID | löscht den Comment, aber `moodStarShortcut` bleibt gesetzt |
|
||||
|
||||
Die Web-App nutzt einen Service Worker, der Requests abfängt — der echte Unlike-Payload
|
||||
ist dadurch nicht per Browser-DevTools inspizierbar. Unlike bleibt bis zur weiteren
|
||||
Analyse nicht unterstützt.
|
||||
|
||||
**Response-Struktur (verifiziert):**
|
||||
```
|
||||
@@ -325,4 +342,5 @@ jeweilige Account geliked hat. Leere Map oder fehlender Key = kein Like.
|
||||
- ~~`taskmark`: korrekter Parameter-Name~~ → **`taskId`** (nicht `metaId`!) (verifiziert)
|
||||
- ~~`metadelete`: korrekter Parameter-Name + Response-Struktur~~ → **`id`**, Response `"true"` (verifiziert)
|
||||
- ~~`wallmood`: Parameter-Name `wallId`~~ → **`wall_message_id`** (verifiziert via API-Fehlermeldung)
|
||||
- ~~`wallmood`: `moodType`-Werte, Toggle vs. explizit, Response-Struktur~~ → vollständig verifiziert via FW_DEBUG=1 (siehe oben)
|
||||
- ~~`wallmood`: `moodType`-Werte, Toggle vs. explizit, Response-Struktur~~ → verifiziert: idempotentes SET mit `"STAR"`, kein Toggle (siehe oben)
|
||||
- `wallmood` Unlike: Mechanismus unbekannt — Service Worker verhindert Browser-Inspektion; alle getesteten Ansätze fehlgeschlagen (siehe oben)
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "mcp-familywall"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
description = "MCP server for Family Wall — read your family's lists and tasks via Claude"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
@@ -478,22 +478,36 @@ def delete_task(task_id: str) -> str:
|
||||
|
||||
@mcp.tool()
|
||||
def like_post(post_id: str, like: bool = True) -> str:
|
||||
"""Like or unlike a wall post/activity.
|
||||
"""Like a wall post/activity with a STAR mood.
|
||||
|
||||
Note: Unlike (like=False) is not yet supported. The Family Wall API offers
|
||||
no discoverable endpoint or parameter to remove a like. Passing like=False
|
||||
returns an error without making any API call.
|
||||
|
||||
Args:
|
||||
post_id: Wall post ID from get_activities (e.g. ``wall/23431854_31119189``).
|
||||
like: ``True`` to like the post, ``False`` to unlike.
|
||||
like: Must be ``True``. ``False`` is reserved for future unlike support.
|
||||
|
||||
Returns:
|
||||
JSON success indicator or an error message.
|
||||
"""
|
||||
# wallmood toggles the STAR mood on a wall post (same endpoint for like/unlike).
|
||||
# Unlike is not yet supported: extensive FW_DEBUG=1 testing showed that
|
||||
# wallmood with moodType="STAR" is an idempotent SET operation (not a toggle).
|
||||
# Tested and ruled out: moodType variations ("NONE", "REMOVE", "DELETE", ""),
|
||||
# moodStarShortcut parameter, and alternative endpoints (all return 502).
|
||||
# See SPEC.md for full investigation notes.
|
||||
if not like:
|
||||
return json.dumps(
|
||||
{"error": "Unlike is not yet supported. The unlike mechanism is unknown."},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
|
||||
# Verified via FW_DEBUG=1:
|
||||
# - Parameter 'wall_message_id': post ID as returned by get_activities
|
||||
# - Parameter 'moodType': "STAR" (Family Wall's internal like type)
|
||||
# - Response a00.r.r: full wall message object with moodMap showing current state
|
||||
# The endpoint is a toggle — calling it again removes the mood.
|
||||
# 'like=False' relies on this toggle behaviour (call again to undo).
|
||||
# - Parameter 'moodType': "STAR" (Family Wall's internal like type; "LIKE" is silently
|
||||
# mapped to "STAR" server-side — use "STAR" directly)
|
||||
# - Response a00.r.r: full wall message object with moodMap showing resulting state
|
||||
params: dict[str, Any] = {
|
||||
"wall_message_id": post_id,
|
||||
"moodType": "STAR",
|
||||
@@ -504,7 +518,7 @@ def like_post(post_id: str, like: bool = True) -> str:
|
||||
except RuntimeError as exc:
|
||||
return f"Error: {exc}"
|
||||
|
||||
# Extract moodMap from response to determine actual resulting state.
|
||||
# Extract moodMap from the response to confirm the like was recorded.
|
||||
try:
|
||||
wall_obj = data["a00"]["r"]["r"]
|
||||
if not isinstance(wall_obj, dict):
|
||||
@@ -518,8 +532,7 @@ def like_post(post_id: str, like: bool = True) -> str:
|
||||
indent=2,
|
||||
)
|
||||
|
||||
# Determine whether the post is now liked by checking if any entry in
|
||||
# moodMap contains "STAR" (the server-side representation of a like).
|
||||
# Confirm the STAR is present in moodMap (server-side representation of a like).
|
||||
now_liked = any("STAR" in moods for moods in mood_map.values())
|
||||
|
||||
return json.dumps(
|
||||
|
||||
Reference in New Issue
Block a user