The User MCP feature is complete on branch mcp. 127 MCP tests passing, bin/ci green, all code-review follow-ups addressed.
What shipped
Feature summary:
- Per-user MCP server at POST /mcp/:token (Streamable HTTP, token-in-URL)
- ~93 tool classes across 15 permission domains:
- 13 writable (CRU) — Accounts, Expenses, Debts + DebtPayments, Investments, Goals, Habits + HabitCompletions, Sports + sport logs, Birthdays, MarketLists + Items, Notes (ActionText), Countdowns, Construction (Project + Phase + Expense), TodoBoard (singleton) + TodoCards
- 2 read-only — Gamification (9 tools), Analytics (3 tools wrapping Dashboard::DataAggregator + User::AnalyticsCalculator)
- Token management + activity log UI at /settings/mcp with Pundit policies
- Raw tokens shown once, SHA256-digest storage, 60 req/min/token rate limit
- Side effects fire normally (XP, notifications, challenges) — MCP calls are first-class user actions
Stats:
- 49 MCP-related commits on the mcp branch (plus design spec + plan + annotation refreshes)
- 127 MCP tests: 100% passing
- Full bin/ci passes (rubocop, brakeman, bundler-audit, Rails test suite)
How to test manually when you're back
- bin/dev to boot the server
- Sign in, visit http://localhost:3000/settings/mcp, click "New token"
- Check the permissions you want, submit — the raw token is shown once; copy it
- Point an MCP client (Claude Desktop, Claude Code) at https:///mcp/ or test with curl: curl -X POST http://localhost:3000/mcp/ \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}'
- Activity is tracked at /settings/mcp/activity
Minor follow-ups deferred (not blocking)
- Token prefix length is 8 chars; spec says 6 — cosmetic
- Rack app's authorized? has a tiny redundant active? check after find_by_raw_token already filters — dead code
- More system tests (regenerate, activity filter, non-owner 403) — existing coverage is via integration/model tests
- No test for the sensitive-key redaction in activity logging — the logic is there and unit-level trivial