feat(circles): add update_circle tool (v0.7.4)
Implements accupdatefamily endpoint (verified via FW_DEBUG=1): - Parameter 'scope' targets any circle (primary or secondary) - Without scope: renames the primary circle (API default) - Server always capitalises the first letter of the new name - Verifies circle existence via famlistfamily in same session - Response a00.r.r = full circle object with updated name Also corrects SPEC.md: accupdatefamily with scope= works for any circle, not just the primary (previous note was incomplete). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
__version__ = "0.7.3"
|
||||
__version__ = "0.7.4"
|
||||
|
||||
@@ -1342,6 +1342,96 @@ def create_circle(name: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tool: update_circle
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def update_circle(circle_id: str, name: str) -> str:
|
||||
"""Rename a Family Wall circle.
|
||||
|
||||
IMPORTANT: Ask the user for confirmation before calling this tool.
|
||||
|
||||
Only the circle name can be changed via the API. Note that the server
|
||||
always capitalises the first letter of the new name.
|
||||
|
||||
Args:
|
||||
circle_id: Circle metaId from ``get_circles``
|
||||
(e.g. ``"family/23431854"``).
|
||||
name: New display name for the circle.
|
||||
|
||||
Returns:
|
||||
JSON with ``{updated, id, name}`` on success, or an error message.
|
||||
"""
|
||||
if not name or not name.strip():
|
||||
return "Error: 'name' must not be empty."
|
||||
|
||||
try:
|
||||
email, password = get_credentials()
|
||||
except RuntimeError as exc:
|
||||
return f"Error: {exc}"
|
||||
|
||||
try:
|
||||
with FamilyWallClient() as client:
|
||||
client.login(email, password)
|
||||
|
||||
# Verify the circle exists before attempting the update.
|
||||
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,
|
||||
)
|
||||
|
||||
# Rename the circle.
|
||||
# Verified: accupdatefamily with scope=<circle_metaId> targets any circle,
|
||||
# both primary and secondary. The server capitalises the first letter.
|
||||
resp = client.call("accupdatefamily", {"scope": circle_id, "name": name})
|
||||
client.logout()
|
||||
except FamilyWallError as exc:
|
||||
return f"Error: Family Wall API error: {exc}"
|
||||
except Exception as exc:
|
||||
return f"Error: Connection error: {exc}"
|
||||
|
||||
# Response: a00.r.r = full circle object
|
||||
try:
|
||||
circle_obj: dict[str, Any] = resp["a00"]["r"]["r"]
|
||||
if not isinstance(circle_obj, dict) or "metaId" not in circle_obj:
|
||||
raise TypeError("unexpected shape")
|
||||
except (KeyError, TypeError):
|
||||
return json.dumps(
|
||||
{"warning": "Unexpected accupdatefamily response structure", "raw": resp},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
|
||||
return json.dumps(
|
||||
{
|
||||
"updated": True,
|
||||
"id": circle_obj.get("metaId"),
|
||||
"name": circle_obj.get("name"),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tool: add_member_to_circle
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user