feat: add delete_circle tool (v0.7.2)
Implements `delete_circle(circle_id)` using the verified `adminwipefamily` endpoint. Protects the primary circle via `isFirstFamily` check. Probe circles family/23447370 and family/23447378 cleaned up during testing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,7 @@ und wird in Claude Desktop eingebunden.
|
|||||||
|
|
||||||
## Aktueller Stand
|
## Aktueller Stand
|
||||||
|
|
||||||
### Implementierte Tools (v0.7.1)
|
### Implementierte Tools (v0.7.2)
|
||||||
|
|
||||||
| Kategorie | Tools |
|
| Kategorie | Tools |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -34,7 +34,7 @@ und wird in Claude Desktop eingebunden.
|
|||||||
| Kategorien | `create_category`, `delete_category` |
|
| Kategorien | `create_category`, `delete_category` |
|
||||||
| Aktivitäten | `like_post` |
|
| Aktivitäten | `like_post` |
|
||||||
| Rezepte | `get_recipes`, `get_recipe`, `create_recipe`, `update_recipe`, `delete_recipe` |
|
| Rezepte | `get_recipes`, `get_recipe`, `create_recipe`, `update_recipe`, `delete_recipe` |
|
||||||
| Kreise | `create_circle`, `add_member_to_circle` |
|
| Kreise | `create_circle`, `delete_circle`, `add_member_to_circle` |
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
@@ -46,8 +46,9 @@ und wird in Claude Desktop eingebunden.
|
|||||||
- v0.6.0: Rezept-Box (get_recipes, get_recipe, create_recipe, delete_recipe) ✓
|
- v0.6.0: Rezept-Box (get_recipes, get_recipe, create_recipe, delete_recipe) ✓
|
||||||
- v0.6.1: update_recipe + Bugfix Zeilenumbrüche in create_recipe ✓
|
- v0.6.1: update_recipe + Bugfix Zeilenumbrüche in create_recipe ✓
|
||||||
- v0.7.0: create_circle + add_member_to_circle ✓
|
- v0.7.0: create_circle + add_member_to_circle ✓
|
||||||
- v0.7.1: get_lists scope fix + create_list circle_id + delete_list scope ✓ ← aktuell
|
- v0.7.1: get_lists scope fix + create_list circle_id + delete_list scope ✓
|
||||||
- v0.7.2: mpadditemtolist (Zutaten → Einkaufsliste)
|
- v0.7.2: delete_circle ✓ ← aktuell
|
||||||
|
- v0.7.3: mpadditemtolist (Zutaten → Einkaufsliste)
|
||||||
- v0.5.3: update_list (Umbenennen, emoji/color ändern), Sharing-Verwaltung
|
- v0.5.3: update_list (Umbenennen, emoji/color ändern), Sharing-Verwaltung
|
||||||
- v0.8.x: Erinnerungen + Wiederholungen (Premium-Account erforderlich)
|
- v0.8.x: Erinnerungen + Wiederholungen (Premium-Account erforderlich)
|
||||||
- v2.0: Schreibzugriff auf Wall-Posts (Erstellen, Kommentieren)
|
- v2.0: Schreibzugriff auf Wall-Posts (Erstellen, Kommentieren)
|
||||||
@@ -147,6 +148,7 @@ Fehler bei falschen Parametern kommen nicht immer auf Top-Level:
|
|||||||
| `acccreatefamily` | `name` | liefert numerische Kreis-ID als String in `a00.r.r` |
|
| `acccreatefamily` | `name` | liefert numerische Kreis-ID als String in `a00.r.r` |
|
||||||
| `accinvite` | `familyId`, `identifier`, `role="Unknown"`, `firstname` | nur für neue FW-Accounts |
|
| `accinvite` | `familyId`, `identifier`, `role="Unknown"`, `firstname` | nur für neue FW-Accounts |
|
||||||
| `accupdatefamily` | `name` | aktualisiert immer den PRIMARY Kreis (ignoriert `id`/`familyId`) |
|
| `accupdatefamily` | `name` | aktualisiert immer den PRIMARY Kreis (ignoriert `id`/`familyId`) |
|
||||||
|
| `adminwipefamily` | `scope` | Kreis-metaId; löscht Kreis + alle Inhalte; `a00.r.r="true"` bei Erfolg |
|
||||||
|
|
||||||
### Self-Like-Restriction
|
### Self-Like-Restriction
|
||||||
Eigene Posts können nicht geliked werden. API antwortet 200, macht aber nichts.
|
Eigene Posts können nicht geliked werden. API antwortet 200, macht aber nichts.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, tasks, and recipes directly from Claude.
|
MCP server for [Family Wall](https://www.familywall.com) -- read and manage your family's circles, lists, tasks, and recipes directly from Claude.
|
||||||
|
|
||||||
## Features (v0.7.1)
|
## Features (v0.7.2)
|
||||||
|
|
||||||
### Read
|
### Read
|
||||||
|
|
||||||
@@ -29,7 +29,8 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your
|
|||||||
- `create_recipe` -- create a new recipe (name, description, ingredients, instructions, prep/cook time, serves, url); use `\n` to separate ingredient lines
|
- `create_recipe` -- create a new recipe (name, description, ingredients, instructions, prep/cook time, serves, url); use `\n` to separate ingredient lines
|
||||||
- `update_recipe` -- update any field of an existing recipe (partial update — omitted fields unchanged)
|
- `update_recipe` -- update any field of an existing recipe (partial update — omitted fields unchanged)
|
||||||
- `delete_recipe` -- permanently delete a recipe (only own recipes)
|
- `delete_recipe` -- permanently delete a recipe (only own recipes)
|
||||||
- `create_circle` -- create a new Family Wall circle (group); note: circles cannot be deleted via API
|
- `create_circle` -- create a new Family Wall circle (group)
|
||||||
|
- `delete_circle` -- permanently delete a circle and all its content (primary circle is protected)
|
||||||
- `add_member_to_circle` -- invite a person to a circle by e-mail (for new Family Wall users only; existing accounts require in-app invitation)
|
- `add_member_to_circle` -- invite a person to a circle by e-mail (for new Family Wall users only; existing accounts require in-app invitation)
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|||||||
@@ -583,6 +583,31 @@ POST https://api.familywall.com/api/accupdatefamily
|
|||||||
|
|
||||||
**Verifiziert am:** 2026-04-16 via FW_DEBUG=1
|
**Verifiziert am:** 2026-04-16 via FW_DEBUG=1
|
||||||
|
|
||||||
|
### `adminwipefamily` – Kreis löschen
|
||||||
|
|
||||||
|
POST https://api.familywall.com/api/adminwipefamily
|
||||||
|
|
||||||
|
Löscht einen Kreis und alle zugehörigen Inhalte (Listen, Tasks, Rezepte, Wall-Posts).
|
||||||
|
|
||||||
|
**Body-Parameter:**
|
||||||
|
|
||||||
|
| Parameter | Pflicht | Wert |
|
||||||
|
|---|---|---|
|
||||||
|
| `scope` | ja | Kreis-metaId (z.B. `family/23447378`) |
|
||||||
|
|
||||||
|
**Response (Erfolg):**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "a00": { "r": { "r": "true" } } }
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hinweise:**
|
||||||
|
- Löscht unwiderruflich alle Inhalte des Kreises.
|
||||||
|
- Der primäre Kreis (`isFirstFamily="true"` in `famlistfamily`) kann NICHT gelöscht werden.
|
||||||
|
- MCP-Server prüft `isFirstFamily` vor dem Löschen via `famlistfamily` im gleichen Session-Call.
|
||||||
|
|
||||||
|
**Verifiziert am:** 2026-04-16 via FW_DEBUG=1 (family/23447371 erfolgreich gelöscht)
|
||||||
|
|
||||||
## Offene Punkte
|
## Offene Punkte
|
||||||
|
|
||||||
- Unlike-Endpoint (Service Worker blockiert Analyse)
|
- Unlike-Endpoint (Service Worker blockiert Analyse)
|
||||||
@@ -591,4 +616,3 @@ POST https://api.familywall.com/api/accupdatefamily
|
|||||||
- Sortierung von Kategorien via API
|
- Sortierung von Kategorien via API
|
||||||
- mpadditemtolist (Zutaten aus Rezept → Einkaufsliste)
|
- mpadditemtolist (Zutaten aus Rezept → Einkaufsliste)
|
||||||
- Einladung bestehender FamilyWall-Nutzer (accinvite nur für neue Accounts)
|
- Einladung bestehender FamilyWall-Nutzer (accinvite nur für neue Accounts)
|
||||||
- Kreis-Delete-Endpoint (API: "delete not supported" für family-Objekte)
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mcp-familywall"
|
name = "mcp-familywall"
|
||||||
version = "0.7.1"
|
version = "0.7.2"
|
||||||
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"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.7.1"
|
__version__ = "0.7.2"
|
||||||
|
|||||||
@@ -1289,6 +1289,95 @@ def add_member_to_circle(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Tool: delete_circle
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@mcp.tool()
|
||||||
|
def delete_circle(circle_id: str) -> str:
|
||||||
|
"""Permanently delete a Family Wall circle (group) and all its content.
|
||||||
|
|
||||||
|
IMPORTANT: Ask the user for confirmation before calling this tool.
|
||||||
|
|
||||||
|
This action cannot be undone. All lists, tasks, recipes, and wall posts
|
||||||
|
inside the circle are deleted along with it. The primary (first) circle
|
||||||
|
is protected and cannot be deleted.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
circle_id: Circle metaId from ``get_circles``
|
||||||
|
(e.g. ``"family/23447378"``). Must not be the primary circle.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON success indicator or an error message.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
email, password = get_credentials()
|
||||||
|
except RuntimeError as exc:
|
||||||
|
return f"Error: {exc}"
|
||||||
|
|
||||||
|
circle_name: str = circle_id
|
||||||
|
try:
|
||||||
|
with FamilyWallClient() as client:
|
||||||
|
client.login(email, password)
|
||||||
|
|
||||||
|
# Fetch the circle list to verify the target exists and is not primary.
|
||||||
|
circles_data = client.call("famlistfamily")
|
||||||
|
try:
|
||||||
|
raw_circles: list[dict[str, Any]] = circles_data["a00"]["r"]["r"]
|
||||||
|
if not isinstance(raw_circles, list):
|
||||||
|
raise TypeError("a00.r.r is not a list")
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
client.logout()
|
||||||
|
return "Error: Unexpected famlistfamily response structure."
|
||||||
|
|
||||||
|
target = next((c for c in raw_circles if c.get("metaId") == circle_id), None)
|
||||||
|
if target is None:
|
||||||
|
client.logout()
|
||||||
|
available = [c.get("metaId") for c in raw_circles]
|
||||||
|
return json.dumps(
|
||||||
|
{
|
||||||
|
"error": f"Circle not found: {circle_id!r}",
|
||||||
|
"available_circles": available,
|
||||||
|
},
|
||||||
|
ensure_ascii=False,
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
if target.get("isFirstFamily") == "true":
|
||||||
|
client.logout()
|
||||||
|
return json.dumps(
|
||||||
|
{
|
||||||
|
"error": "Cannot delete the primary circle.",
|
||||||
|
"id": circle_id,
|
||||||
|
"name": target.get("name"),
|
||||||
|
"hint": (
|
||||||
|
"The primary (first) circle cannot be deleted via the API. "
|
||||||
|
"Use the Family Wall app settings to manage it."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
ensure_ascii=False,
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
circle_name = target.get("name", circle_id)
|
||||||
|
|
||||||
|
# Verified — delete in the same session.
|
||||||
|
# adminwipefamily uses scope=<circle_metaId> and returns a00.r.r="true".
|
||||||
|
client.call("adminwipefamily", {"scope": circle_id})
|
||||||
|
client.logout()
|
||||||
|
except FamilyWallError as exc:
|
||||||
|
return f"Error: Family Wall API error: {exc}"
|
||||||
|
except Exception as exc:
|
||||||
|
return f"Error: Connection error: {exc}"
|
||||||
|
|
||||||
|
return json.dumps(
|
||||||
|
{"deleted": True, "id": circle_id, "name": circle_name},
|
||||||
|
ensure_ascii=False,
|
||||||
|
indent=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Tool: like_post
|
# Tool: like_post
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user