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:
@@ -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,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
|
||||
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user