Modernize MCP server with structured output and 2025 protocol features#11
Conversation
…completions, progress
- every tool now returns a typed Pydantic model so FastMCP advertises an outputSchema and emits structured content alongside a text fallback
- add human-friendly titles to all tools, resources, and prompts
- add parameterized resource templates: accounts://{account_id}/holdings and accounts://{account_id}/history
- add a completions handler for the prompt `category` arg and resource-template `account_id`, backed by live monarch data (best-effort, never raises)
- report progress via injected Context in the two batch tools (complete overview, spending patterns)
- fix get_account_holdings to pass the required account_id (the underlying library always required it)
- keep track_usage result-size logging accurate for model returns
- expand tests to 202: structured-output schema coverage, resource templates, completions, progress, titles, plus migrating string-shape assertions to structured ones
- bump the cited MCP protocol version to 2025-11-25 and note the stateless draft (we already log to stderr) - record the newly adopted structured output, titles, resource templates, completions, and progress features - update stale metrics to 202 tests / 19 tools / mypy-clean
|
Claude finished @jamiew's task in 2m 58s —— View job Code Review — mcp-upgrade PR #11Overall: Approve with minor suggestions. This is a well-scoped, well-tested modernization. The structured output models are cleanly designed, the new features (titles, resource templates, completions, progress) follow the 2025-06-18 spec faithfully, and the View full reviewWhat's good
Issues1.
|
- documents the structured output, titles, resource templates, completions, and progress work under today's date.
- the real client returns dicts like `{"accounts": [...]}` / `{"categories": [...]}`, so the new `list[...]`-typed models were collapsing successful calls to empty results
- add an `extract_list(response, key)` helper beside `extract_transactions_list` and use it in `get_accounts`, `get_transaction_categories`, and both autocompletion helpers
- make `InstitutionsResult` a passthrough since the institutions payload is a dict (credentials/accounts/subscription) with no flat list
- update the affected test mocks to the real dict shapes so the regression can't slip through again
- drop a dead `period` key in `get_spending_summary` and note why the transaction tools use `model_validate` (mypy list invariance)
- correct the tool count (22 → 19) and drop references to the removed `get_transactions_batch` and nonexistent `get_usage_analytics` - note that `get_account_holdings` now requires an `account_id` - document structured output, resource templates, completions, and progress reporting - replace the bogus `get_usage_analytics` README table row with `get_spending_summary`
- fix console-script entry point: it pointed at async `main()`, so `uvx monarch-mcp-jamiew` launched a coroutine that was never awaited and the server never started; add a sync `run()` wrapper instead - floor `monarchmoneycommunity>=1.3.2` since the git pin isn't in the wheel - rewrite README Setup as a uvx-first, per-client layout (Claude Desktop, Claude Code, Codex, + other clients + from-source) - document the OIDC release/publish flow in README and CLAUDE.md
consulted the latest MCP spec and pulled in the worthwhile 2025-06-18 features we were missing. the big one is structured tool output — every tool now returns a typed pydantic model so clients get a real outputSchema + machine-readable results (with a text fallback for older clients). also added the lighter-weight niceties: titles, resource templates, completions, and progress.
titles on every tool/resource/promptaccounts://{account_id}/holdingsandaccounts://{account_id}/historycategoryarg and templateaccount_id, backed by live monarch data (best-effort, never raises)get_account_holdingsto pass the requiredaccount_id— the underlying library always required it, so the no-arg version was a latent bugto test:
uv run python scripts/ci.py→ ruff + format + mypy + pytest all greenuv run python server.pystarts clean (logs to stderr, stdout stays empty)