fix(wall-posts): add delete_wall_post and fix add_comment response parser (v1.3.1)

- Fix add_comment response parser: corrected to a00.r.r.comment.commentId structure
- Fix add_comment error handling: return errors directly instead of warnings
- Add delete_wall_post: permanently delete wall posts via metadelete endpoint
- Add delete_wall_post to README.md Wall & Activities section
- Update SPEC.md with correct walladdComment response structure
- Update SPEC.md metadelete to include wall posts as supported type
- Update CHANGELOG.md with v1.3.1 bugfixes and additions
- Version bumped to 1.3.1 in pyproject.toml

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 23:25:45 +02:00
parent 0e7c4da362
commit 35cbfd3061
5 changed files with 77 additions and 17 deletions
+15
View File
@@ -10,6 +10,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
This project follows Semantic Versioning (SemVer).
Breaking changes (removed tools, changed parameters) increment the major version.
## [1.3.1] 2026-04-17
### Fixed
- **`add_comment` response parser**: corrected response structure from `a00.r.r` with `metaId`
to nested `a00.r.r.comment.commentId`; response now includes `"created": true` flag
- **`add_comment` error handling**: now returns error messages directly instead of warnings
### Added
- **`delete_wall_post`** — permanently delete a wall post using the `metadelete` endpoint
(identical to deleting tasks and recipes)
### Notes
- All wall post tools now complete CRUD operations (Create, Read, Update via like_post, Delete)
- Test post (wall/16282169_31146617) removed from production after verification
## [1.3.0] 2026-04-17
### Added
+2 -1
View File
@@ -2,7 +2,7 @@
MCP server for [Family Wall](https://www.familywall.com) — manage your family's circles, lists, tasks, recipes, and meal plan directly from Claude.
## Tools (v1.3.0)
## Tools (v1.3.1)
### Wall & Activities
@@ -12,6 +12,7 @@ MCP server for [Family Wall](https://www.familywall.com) — manage your family'
| `create_wall_post` 🔒 | Create a new status post on the wall |
| `add_comment` 🔒 | Add a comment to a post |
| `like_post` 🔒 | Like or unlike a wall post/activity |
| `delete_wall_post` 🔒 | Permanently delete a wall post |
### Circles & Members
+4 -3
View File
@@ -269,6 +269,7 @@ POST https://api.familywall.com/api/metadelete
- Tasks: `task/<id>`
- Rezepte: `recipe/<id>`
- Essensplan-Einträge: `dish/<id>` und `meal/<id>`
- Wall-Posts: `wall/<id>` (v1.3.1+)
**Response:**
```
@@ -337,8 +338,8 @@ POST https://api.familywall.com/api/walladdComment
**Response:**
```
a00.r.r → Kommentar-Objekt
.metaId → neue Kommentar-ID
a00.r.r.comment → Kommentar-Objekt (nested)
.commentId → neue Kommentar-ID
.text → Kommentartext
.creationDate → Timestamp (ISO 8601)
```
@@ -346,7 +347,7 @@ a00.r.r → Kommentar-Objekt
**Bekannte Einschränkungen:**
- `mood` und `clientOpId` sind optional und werden ignoriert
**Verifiziert am:** 2026-04-17 via Briefing und Integration
**Verifiziert am:** 2026-04-17 via Briefing und Integration (Response-Struktur in v1.3.1 korrekt dokumentiert)
### `taskcategoryput` Kategorie erstellen/aktualisieren
POST https://api.familywall.com/api/taskcategoryput
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "mcp-familywall"
version = "1.3.0"
version = "1.3.1"
description = "MCP server for Family Wall — manage your family's circles, lists, tasks, recipes, and meal plan via Claude"
readme = "README.md"
requires-python = ">=3.12"
+55 -12
View File
@@ -2042,9 +2042,8 @@ def get_wall_posts(limit: int = 20) -> str:
raw_author: str = item.get("accountId", "")
mood_map: dict[str, Any] = item.get("moodMap") or {}
liked_by_me = (
item.get("moodStarShortcut") == "true"
or any("STAR" in moods for moods in mood_map.values())
liked_by_me = item.get("moodStarShortcut") == "true" or any(
"STAR" in moods for moods in mood_map.values()
)
like_count = sum(len(moods) for moods in mood_map.values() if isinstance(moods, list))
@@ -2164,22 +2163,66 @@ def add_comment(post_id: str, comment: str) -> str:
return _err(f"Connection error: {exc}")
try:
comment_obj = data["a00"]["r"]["r"]
if not isinstance(comment_obj, dict) or "metaId" not in comment_obj:
raise TypeError("unexpected shape")
except (KeyError, TypeError):
response_obj = data["a00"]["r"]["r"]
if not isinstance(response_obj, dict):
raise TypeError("a00.r.r is not a dict")
comment_obj = response_obj.get("comment")
if not isinstance(comment_obj, dict) or "commentId" not in comment_obj:
raise TypeError("comment object missing or invalid")
except (KeyError, TypeError) as exc:
return _err(f"Unexpected walladdComment response structure: {exc}")
return json.dumps(
{"warning": "Unexpected walladdComment response structure", "raw": data},
{
"created": True,
"id": comment_obj.get("commentId"),
"post_id": post_id,
"text": comment_obj.get("text"),
"date": comment_obj.get("creationDate"),
},
ensure_ascii=False,
indent=2,
)
# ---------------------------------------------------------------------------
# Tool: delete_wall_post
# ---------------------------------------------------------------------------
@mcp.tool()
def delete_wall_post(post_id: str) -> str:
"""Permanently delete a wall post.
IMPORTANT: Ask the user for confirmation before calling this tool.
Args:
post_id: Wall post metaId from get_wall_posts
(e.g. ``"wall/16282169_31146617"``).
Returns:
JSON success indicator or an error message.
"""
try:
data = _authenticated_call("metadelete", {"id": post_id})
except RuntimeError as exc:
return _err(str(exc))
try:
result = data["a00"]["r"]["r"]
if result != "true":
raise ValueError(f"Unexpected result: {result}")
except (KeyError, ValueError) as exc:
return json.dumps(
{"warning": "Unexpected metadelete response structure", "error": str(exc), "raw": data},
ensure_ascii=False,
indent=2,
)
return json.dumps(
{
"id": comment_obj.get("metaId"),
"post_id": post_id,
"text": comment_obj.get("text") or comment_obj.get("comment"),
"date": comment_obj.get("creationDate"),
"deleted": True,
"id": post_id,
},
ensure_ascii=False,
indent=2,