fix: use moodType=STAR for wallmood, parse moodMap from response (v0.4.4)
FW_DEBUG=1 verification revealed: - moodType "LIKE" was silently mapped to "STAR" server-side; use "STAR" directly - Response a00.r.r contains full wall object with moodMap showing actual like state - liked status now derived from moodMap rather than echoing the input bool - SPEC.md updated with fully verified wallmood endpoint details 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.
|
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.3)
|
## Features (v0.4.4)
|
||||||
|
|
||||||
### Read
|
### Read
|
||||||
|
|
||||||
|
|||||||
@@ -270,22 +270,45 @@ kritisch.
|
|||||||
POST https://api.familywall.com/api/wallmood
|
POST https://api.familywall.com/api/wallmood
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
**Body-Parameter:**
|
**Body-Parameter (verifiziert via FW_DEBUG=1):**
|
||||||
|
|
||||||
| Parameter | Pflicht | Wert |
|
| Parameter | Pflicht | Wert |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `wall_message_id` | ja (verifiziert) | Post-ID aus `get_activities` (Format `wall/23431854_31119189`) |
|
| `wall_message_id` | ja | Post-ID aus `get_activities` (z.B. `wall/23431854_31119189`) |
|
||||||
| `moodType` | vermutlich ja | `"LIKE"` zum Liken, `"NONE"` zum Unliken (zu verifizieren) |
|
| `moodType` | ja | `"STAR"` (einziger bekannter Wert — entspricht dem Like-Button in der App) |
|
||||||
|
|
||||||
**Hinweis:** Parameter-Name `wall_message_id` wurde durch API-Fehlermeldung
|
**Verhalten (verifiziert):**
|
||||||
(`"missing value in: wall_message_id"`) verifiziert. Vorheriger Wert `wallId` war falsch.
|
- 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"`
|
||||||
|
|
||||||
**Verhalten:** Gleicher Endpoint für Like und Unlike. `moodType`-Werte und
|
**Response-Struktur (verifiziert):**
|
||||||
Response-Struktur noch zu verifizieren via `FW_DEBUG=1`.
|
```
|
||||||
|
a00.r.r → vollständiges Wall-Message-Objekt
|
||||||
|
.metaId → Post-ID (= wallMessageId)
|
||||||
|
.wallMessageId → Post-ID (identisch zu metaId)
|
||||||
|
.refType → Aktivitätstyp (z.B. "STATUS")
|
||||||
|
.refAction → Letzte Aktion (z.B. "MOOD_STAR")
|
||||||
|
.text → Post-Text
|
||||||
|
.postAccountId → Account-ID des Post-Autors
|
||||||
|
.accountId → Account-ID (identisch)
|
||||||
|
.moodMap → dict: accountId → ["STAR"] wenn geliked
|
||||||
|
.moodStarShortcut → "true" wenn Like-Shortcut aktiv
|
||||||
|
.comments[] → Liste von Kommentaren/Moods
|
||||||
|
.commentId → Kommentar-ID (Format wallComment/...)
|
||||||
|
.accountId → Account-ID des Kommentators
|
||||||
|
.mood → Mood-Typ (z.B. "STAR")
|
||||||
|
.text → Kommentartext (falls vorhanden)
|
||||||
|
.creationDate → Erstelldatum (ISO 8601)
|
||||||
|
.creationDate → Erstelldatum des Posts (ISO 8601)
|
||||||
|
.modifDate → Letztes Änderungsdatum (ISO 8601)
|
||||||
|
.familyId → Kreis-ID (Format family/...)
|
||||||
|
.rights.canUpdate → "true"/"false"
|
||||||
|
.rights.canDelete → "true"/"false"
|
||||||
|
```
|
||||||
|
|
||||||
Ein Like erzeugt serverseitig einen neuen Wall-Eintrag (Nebeneffekt).
|
**Like-Zustand bestimmen:** `moodMap[accountId]` enthält `["STAR"]` wenn der
|
||||||
|
jeweilige Account geliked hat. Leere Map oder fehlender Key = kein Like.
|
||||||
**Response-Struktur:** zu verifizieren beim ersten echten Call
|
|
||||||
|
|
||||||
## Noch zu verifizieren
|
## Noch zu verifizieren
|
||||||
|
|
||||||
@@ -302,4 +325,4 @@ Ein Like erzeugt serverseitig einen neuen Wall-Eintrag (Nebeneffekt).
|
|||||||
- ~~`taskmark`: korrekter Parameter-Name~~ → **`taskId`** (nicht `metaId`!) (verifiziert)
|
- ~~`taskmark`: korrekter Parameter-Name~~ → **`taskId`** (nicht `metaId`!) (verifiziert)
|
||||||
- ~~`metadelete`: korrekter Parameter-Name + Response-Struktur~~ → **`id`**, Response `"true"` (verifiziert)
|
- ~~`metadelete`: korrekter Parameter-Name + Response-Struktur~~ → **`id`**, Response `"true"` (verifiziert)
|
||||||
- ~~`wallmood`: Parameter-Name `wallId`~~ → **`wall_message_id`** (verifiziert via API-Fehlermeldung)
|
- ~~`wallmood`: Parameter-Name `wallId`~~ → **`wall_message_id`** (verifiziert via API-Fehlermeldung)
|
||||||
- `wallmood`: `moodType`-Werte (`"LIKE"` / `"NONE"`?), Toggle vs. explizit, Response-Struktur
|
- ~~`wallmood`: `moodType`-Werte, Toggle vs. explizit, Response-Struktur~~ → vollständig verifiziert via FW_DEBUG=1 (siehe oben)
|
||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mcp-familywall"
|
name = "mcp-familywall"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
description = "MCP server for Family Wall — read your family's lists and tasks via Claude"
|
description = "MCP server for Family Wall — read your family's lists and tasks via Claude"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
@@ -487,15 +487,16 @@ def like_post(post_id: str, like: bool = True) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
JSON success indicator or an error message.
|
JSON success indicator or an error message.
|
||||||
"""
|
"""
|
||||||
# wallmood is a toggle endpoint — same endpoint for like and unlike.
|
# wallmood toggles the STAR mood on a wall post (same endpoint for like/unlike).
|
||||||
# The 'like' parameter controls the intended state; since the endpoint
|
# Verified via FW_DEBUG=1:
|
||||||
# toggles server-side state, it is sent as 'moodType' to allow the server
|
# - Parameter 'wall_message_id': post ID as returned by get_activities
|
||||||
# to differentiate.
|
# - Parameter 'moodType': "STAR" (Family Wall's internal like type)
|
||||||
# Verified: correct parameter name is 'wall_message_id' (API error message confirmed).
|
# - Response a00.r.r: full wall message object with moodMap showing current state
|
||||||
# 'moodType' values ("LIKE" / "NONE") still to be confirmed via FW_DEBUG=1.
|
# The endpoint is a toggle — calling it again removes the mood.
|
||||||
|
# 'like=False' relies on this toggle behaviour (call again to undo).
|
||||||
params: dict[str, Any] = {
|
params: dict[str, Any] = {
|
||||||
"wall_message_id": post_id,
|
"wall_message_id": post_id,
|
||||||
"moodType": "LIKE" if like else "NONE",
|
"moodType": "STAR",
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -503,12 +504,13 @@ def like_post(post_id: str, like: bool = True) -> str:
|
|||||||
except RuntimeError as exc:
|
except RuntimeError as exc:
|
||||||
return f"Error: {exc}"
|
return f"Error: {exc}"
|
||||||
|
|
||||||
# The response structure is not yet fully verified — return raw JSON
|
# Extract moodMap from response to determine actual resulting state.
|
||||||
# if the expected shape is absent so the caller can inspect it.
|
|
||||||
try:
|
try:
|
||||||
result_data = data["a00"]["r"]["r"]
|
wall_obj = data["a00"]["r"]["r"]
|
||||||
if result_data is None:
|
if not isinstance(wall_obj, dict):
|
||||||
raise KeyError("empty result")
|
raise TypeError("a00.r.r is not a dict")
|
||||||
|
mood_map: dict[str, Any] = wall_obj.get("moodMap") or {}
|
||||||
|
account_id: str = wall_obj.get("postAccountId", "")
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return json.dumps(
|
return json.dumps(
|
||||||
{"warning": "Unexpected wallmood response structure", "raw": data},
|
{"warning": "Unexpected wallmood response structure", "raw": data},
|
||||||
@@ -516,8 +518,12 @@ def like_post(post_id: str, like: bool = True) -> str:
|
|||||||
indent=2,
|
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).
|
||||||
|
now_liked = any("STAR" in moods for moods in mood_map.values())
|
||||||
|
|
||||||
return json.dumps(
|
return json.dumps(
|
||||||
{"liked": like, "id": post_id},
|
{"liked": now_liked, "id": post_id, "author": account_id},
|
||||||
ensure_ascii=False,
|
ensure_ascii=False,
|
||||||
indent=2,
|
indent=2,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user