1 Commits

Author SHA1 Message Date
marcus 3e021bf01a chore(v1.0.1): opus review findings — docstring confirmation patterns, pyproject.urls, gitignore fix, logging
**Critical:**
- Add IMPORTANT confirmation lines to toggle_task and like_post docstrings
- Add [project.urls] section with Gitea repository link to pyproject.toml

**Medium:**
- Fix .gitignore: test_*.py recursive pattern (remove leading slash)
- Add exception logging to clear_list() for failed deletions
- Update get_categories() docstring: clarify custom vs system category locale behavior
- Add Versioning Policy section to CHANGELOG.md

**Minor:**
- Fix CLI help text (remove "(read-only)" qualifier)
- Add language note to CLAUDE.md (German file, English code)
- Create tests/README.md with integration test documentation
- Update version to 1.0.1 in pyproject.toml

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-17 17:28:22 +02:00
7 changed files with 87 additions and 12 deletions
+7 -7
View File
@@ -42,11 +42,11 @@ htmlcov/
# uv # uv
uv.lock uv.lock
# Debug and probe scripts (root-level only) # Debug and probe scripts
/debug_*.py debug_*.py
/probe_*.py probe_*.py
/probe_*.txt probe_*.txt
/probe_out.txt probe_out.txt
/p*_err.txt p*_err.txt
/test_*.py test_*.py
reference/ reference/
+24
View File
@@ -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/), 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). 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 ## [1.0.0] 2026-04-17
### Added ### Added
+3
View File
@@ -1,5 +1,8 @@
# mcp-familywall # mcp-familywall
**Note:** This file is intentionally written in German (developer preference).
Code, docstrings, and commit messages are in English.
## Kontext ## Kontext
Dieses Projekt entwickelt `mcp-familywall` einen MCP-Server für den Dieses Projekt entwickelt `mcp-familywall` einen MCP-Server für den
+4 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project] [project]
name = "mcp-familywall" 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" description = "MCP server for Family Wall — manage your family's circles, lists, tasks, recipes, and meal plan via Claude"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
@@ -21,6 +21,9 @@ dependencies = [
"rich>=13.0", "rich>=13.0",
] ]
[project.urls]
Repository = "https://gitea.gecheckt.de/marcus/mcp-familywall"
[project.optional-dependencies] [project.optional-dependencies]
dev = [ dev = [
"pytest>=8.0", "pytest>=8.0",
+1 -1
View File
@@ -21,7 +21,7 @@ from mcp_familywall import __version__
@click.version_option(__version__, "-v", "--version", prog_name="mcp-familywall") @click.version_option(__version__, "-v", "--version", prog_name="mcp-familywall")
@click.pass_context @click.pass_context
def app(ctx: click.Context) -> None: 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: if ctx.invoked_subcommand is None:
click.echo(ctx.get_help()) click.echo(ctx.get_help())
+9 -3
View File
@@ -510,8 +510,9 @@ def get_categories(list_id: str, locale: str = "de") -> str:
"""Return the task categories available for a list as JSON. """Return the task categories available for a list as JSON.
Only shopping lists (taskListType=SHOPPING_LIST) have categories. TODO Only shopping lists (taskListType=SHOPPING_LIST) have categories. TODO
lists return an empty list. Categories are filtered by locale so only lists return an empty list. System categories are filtered by locale so only
the language-appropriate names are returned (default: German). 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 Use the returned ``id`` values as the ``category_id`` parameter in
``create_task`` and ``update_task``. ``create_task`` and ``update_task``.
@@ -1003,6 +1004,8 @@ def update_task(
def toggle_task(task_id: str, complete: bool) -> str: def toggle_task(task_id: str, complete: bool) -> str:
"""Mark a task as complete or incomplete. """Mark a task as complete or incomplete.
IMPORTANT: Ask the user for confirmation before calling this tool.
Args: Args:
task_id: Task metaId from get_tasks. task_id: Task metaId from get_tasks.
complete: ``True`` to mark done, ``False`` to reopen. complete: ``True`` to mark done, ``False`` to reopen.
@@ -1110,8 +1113,9 @@ def clear_list(list_id: str, only_open: bool = False) -> str:
try: try:
client.call("metadelete", {"id": meta_id}) client.call("metadelete", {"id": meta_id})
deleted_ids.append(meta_id) deleted_ids.append(meta_id)
except Exception: except Exception as e:
failed_ids.append(meta_id) failed_ids.append(meta_id)
logger.warning(f"Failed to delete {meta_id}: {e}")
client.logout() client.logout()
except FamilyWallError as exc: 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: def like_post(post_id: str, like: bool = True) -> str:
"""Like a wall post/activity with a STAR mood. """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 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 no discoverable endpoint or parameter to remove a like. Passing like=False
returns an error without making any API call. returns an error without making any API call.
+39
View File
@@ -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