diff --git a/.gitignore b/.gitignore index 9835658..bb92ddf 100644 --- a/.gitignore +++ b/.gitignore @@ -42,11 +42,11 @@ htmlcov/ # uv uv.lock -# Debug and probe scripts (root-level only) -/debug_*.py -/probe_*.py -/probe_*.txt -/probe_out.txt -/p*_err.txt -/test_*.py +# Debug and probe scripts +debug_*.py +probe_*.py +probe_*.txt +probe_out.txt +p*_err.txt +test_*.py reference/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ba18a..844672e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Versioning Policy + +This project follows Semantic Versioning (SemVer). +Breaking changes (removed tools, changed parameters) increment the major version. + +## [1.0.1] – 2026-04-17 + +### Added +- IMPORTANT confirmation notes in docstrings for write operations (`toggle_task`, `like_post`) +- `[project.urls]` section in `pyproject.toml` with Gitea repository link +- Language note in CLAUDE.md explaining German/English split +- `tests/README.md` documentation for running integration tests + +### Changed +- `.gitignore` patterns now recursive (test_*.py without leading slash) +- CLI help text updated (removed "(read-only)" qualifier) +- `clear_list()` now logs exception reasons for failed deletions +- `get_categories()` docstring clarifies custom vs. system category locale behavior + +### Fixed +- Exception handling in `clear_list()` with detailed logging + +--- + ## [1.0.0] – 2026-04-17 ### Added diff --git a/CLAUDE.md b/CLAUDE.md index 1f5a3d6..3c7c296 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,8 @@ # mcp-familywall +**Note:** This file is intentionally written in German (developer preference). +Code, docstrings, and commit messages are in English. + ## Kontext Dieses Projekt entwickelt `mcp-familywall` – einen MCP-Server für den diff --git a/pyproject.toml b/pyproject.toml index 8e07625..e84b909 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "mcp-familywall" -version = "1.0.0" +version = "1.0.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" @@ -21,6 +21,9 @@ dependencies = [ "rich>=13.0", ] +[project.urls] +Repository = "https://gitea.gecheckt.de/marcus/mcp-familywall" + [project.optional-dependencies] dev = [ "pytest>=8.0", diff --git a/src/mcp_familywall/cli.py b/src/mcp_familywall/cli.py index 9e8af66..fc3ed9c 100644 --- a/src/mcp_familywall/cli.py +++ b/src/mcp_familywall/cli.py @@ -21,7 +21,7 @@ from mcp_familywall import __version__ @click.version_option(__version__, "-v", "--version", prog_name="mcp-familywall") @click.pass_context def app(ctx: click.Context) -> None: - """mcp-familywall — MCP server for Family Wall (read-only).""" + """mcp-familywall — MCP server for Family Wall.""" if ctx.invoked_subcommand is None: click.echo(ctx.get_help()) diff --git a/src/mcp_familywall/server.py b/src/mcp_familywall/server.py index 00675aa..c6903aa 100644 --- a/src/mcp_familywall/server.py +++ b/src/mcp_familywall/server.py @@ -510,8 +510,9 @@ def get_categories(list_id: str, locale: str = "de") -> str: """Return the task categories available for a list as JSON. Only shopping lists (taskListType=SHOPPING_LIST) have categories. TODO - lists return an empty list. Categories are filtered by locale so only - the language-appropriate names are returned (default: German). + lists return an empty list. System categories are filtered by locale so only + the language-appropriate names are returned (default: German). Custom categories + have no locale field and are always displayed regardless of the locale parameter. Use the returned ``id`` values as the ``category_id`` parameter in ``create_task`` and ``update_task``. @@ -1003,6 +1004,8 @@ def update_task( def toggle_task(task_id: str, complete: bool) -> str: """Mark a task as complete or incomplete. + IMPORTANT: Ask the user for confirmation before calling this tool. + Args: task_id: Task metaId from get_tasks. complete: ``True`` to mark done, ``False`` to reopen. @@ -1110,8 +1113,9 @@ def clear_list(list_id: str, only_open: bool = False) -> str: try: client.call("metadelete", {"id": meta_id}) deleted_ids.append(meta_id) - except Exception: + except Exception as e: failed_ids.append(meta_id) + logger.warning(f"Failed to delete {meta_id}: {e}") client.logout() except FamilyWallError as exc: @@ -1782,6 +1786,8 @@ def delete_circle(circle_id: str) -> str: def like_post(post_id: str, like: bool = True) -> str: """Like a wall post/activity with a STAR mood. + IMPORTANT: Ask the user for confirmation before calling this tool. + Note: Unlike (like=False) is not yet supported. The Family Wall API offers no discoverable endpoint or parameter to remove a like. Passing like=False returns an error without making any API call. diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..15f12d1 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,39 @@ +# Tests + +Integration tests for mcp-familywall. + +## Prerequisites + +Tests require valid Family Wall credentials to run against the live API. +Credentials are loaded from: + +1. **OS Keyring** (recommended) — set via `mcp-familywall setup` +2. **Environment variables** — `FW_EMAIL` and `FW_PASSWORD` + +## Running Tests + +```bash +uv run pytest tests/ +``` + +For verbose output: + +```bash +uv run pytest tests/ -v +``` + +## Test Coverage + +- Circles management (create, list, update, delete, members) +- Lists and tasks (CRUD operations) +- Categories (system and custom) +- Recipes and meal planning +- Activity feed and reactions +- Date validation and error handling + +## Notes + +- Tests create temporary circles, lists, and tasks for verification +- All test objects are cleaned up after execution +- Do not run tests against production data — use test credentials only +- Some tests are marked as skipped if premium features are unavailable