From 0d8036fd4a3e3ed6af1c80668535e1b501540bf8 Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Thu, 16 Apr 2026 08:06:21 +0200 Subject: [PATCH] fix: get_categories always includes custom categories (v0.4.12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Custom categories (rights.canDelete=true) have no locale field set by the API and were silently excluded by the locale filter. They now bypass both the locale and taskListType filters so they always appear in get_categories output regardless of the locale parameter. Also: deleted 7 test categories (TEmojiApple, Obst & Gemüse (old), TestKategorie, ProbeKat2, [TEST]emoji=apple, ProbeKat1, TDelMeta) and restored 'Obst & Gemüse' (emoji 🍎) as a clean custom category. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 4 ++-- SPEC.md | 3 +++ pyproject.toml | 2 +- src/mcp_familywall/__init__.py | 2 +- src/mcp_familywall/server.py | 13 +++++++++---- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0416904..6cbf513 100644 --- a/README.md +++ b/README.md @@ -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. -## Features (v0.4.11) +## Features (v0.4.12) ### Read @@ -10,7 +10,7 @@ MCP server for [Family Wall](https://www.familywall.com) -- read and manage your - `get_members` -- list members of a circle (or all circles) - `get_lists` -- list all task lists (optionally filtered by circle) - `get_tasks` -- list tasks in a specific list (includes `category_id` field) -- `get_categories` -- list categories for a list (locale-filtered; `custom` flag marks user-created ones) +- `get_categories` -- list categories for a list (locale-filtered; custom categories always included; `custom` flag marks user-created ones) - `get_activities` -- list recent wall activities (author resolved to display name) ### Write (with confirmation prompt) diff --git a/SPEC.md b/SPEC.md index 2c88e67..5a77912 100644 --- a/SPEC.md +++ b/SPEC.md @@ -150,6 +150,9 @@ a01.r.r.updatedCreated[] → taskcategorysync (Kategorien/Abteilung .locale → Sprache des Namens (z.B. "de", "en", "ru", "fr", "es", "it", "nl", "pt", "sv", "ko", "ja") Jede Sprache = eigener Eintrag mit eigenem metaId/systemCategoryId + **Wichtig:** Custom-Kategorien (rights.canDelete='true') haben + kein locale-Feld gesetzt — sie werden sprachunabhängig + zurückgegeben und dürfen nie über locale gefiltert werden. .hiddenByTaskList → Liste von Listen-IDs, in denen die Kat. versteckt ist a02.r.r.updatedCreated[] → tasksync (Tasks) .metaId → eindeutige Task-ID diff --git a/pyproject.toml b/pyproject.toml index 0c6ceba..50a29a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mcp-familywall" -version = "0.4.11" +version = "0.4.12" description = "MCP server for Family Wall — read your family's lists and tasks via Claude" readme = "README.md" requires-python = ">=3.12" diff --git a/src/mcp_familywall/__init__.py b/src/mcp_familywall/__init__.py index 3d26edf..9b084a6 100644 --- a/src/mcp_familywall/__init__.py +++ b/src/mcp_familywall/__init__.py @@ -1 +1 @@ -__version__ = "0.4.1" +__version__ = "0.4.12" diff --git a/src/mcp_familywall/server.py b/src/mcp_familywall/server.py index 3aec20f..55b7407 100644 --- a/src/mcp_familywall/server.py +++ b/src/mcp_familywall/server.py @@ -391,12 +391,17 @@ def get_categories(list_id: str, locale: str = "de") -> str: # Filter by locale (exact match) and taskListType (when known). # sortingIndexByTaskList is NOT used for filtering: all categories are # assigned to all lists regardless of type, making it an unreliable signal. + # + # Custom categories (rights.canDelete=true) bypass both filters: they have + # no locale or taskListType set by the API and must always be returned. matched: list[tuple[int, dict[str, Any]]] = [] for cat in raw_cats: - if cat.get("locale") != locale: - continue - if list_type is not None and cat.get("taskListType") != list_type: - continue + is_custom = cat.get("rights", {}).get("canDelete") == "true" + if not is_custom: + if cat.get("locale") != locale: + continue + if list_type is not None and cat.get("taskListType") != list_type: + continue sort_val = int(cat.get("initialSortingIndex") or 0) matched.append((sort_val, cat))