An agentic budgeting companion. A local-first Model Context Protocol server that turns Claude (or any MCP client) into a financial advisor over your Monarch Money data — it knows where your household stands, keeps the books honest, measures progress against your goals, and looks ahead.
Important
Unofficial. Monarch Money has no public API. This server talks to Monarch's private GraphQL API and is not affiliated with, endorsed by, or supported by Monarch Money. Use at your own risk. See DISCLAIMER.md.
Monarch has no official API, so every Claude↔Monarch integration is a community-built wrapper. Rather than hand a third-party server full access to a live banking session, this is a purpose-built server you can read end to end, with one defining property:
It cannot move money — by construction. There is no transfer, payment, withdrawal, create, or delete code anywhere in it. The only write path can change a transaction's category, tags, or notes — nothing else. Capability denial is enforced by the code's absence of those tools, not by configuration you can misset.
It's read-and-categorize only, your session token never leaves your machine, and the whole thing is validated against real Monarch by a proper test pyramid.
Compound, task-oriented tools — each does a job, combining several API calls + computation
into one decision-ready result (not 1:1 API wrappers you could replace with curl):
| Tool | What it answers |
|---|---|
financial_overview |
"Where do we stand?" — net worth, this-month cash flow, month-over-month change |
spending_report |
Spending by category vs budget, over-budget flags, likely duplicates, vs prior period |
progress_vs_goals |
Actuals vs your stored goals — on track / drifting / off |
cashflow_forecast |
Upcoming bills + income → projected month-end position + shortfall warnings |
net_worth_trend |
Net worth over time, deltas by account type, biggest movers |
recurring_scan |
New / changed / "creeping" subscriptions and upcoming renewals |
account_inventory |
All accounts bucketed by retirement-planning role — tax-advantaged, taxable brokerage, cash, other assets, liabilities — with a net-worth rollup |
triage_uncategorized + apply_changeset |
Propose categories from your own history, then commit only what you approve |
# One-line shell installer (macOS / Linux)
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/mikelane/monarch-mcp/releases/latest/download/monarch-mcp-installer.sh | sh
# PowerShell (Windows)
irm https://github.com/mikelane/monarch-mcp/releases/latest/download/monarch-mcp-installer.ps1 | iex
# Cargo, prebuilt binary — no compile (fetches the release artifacts)
cargo binstall monarch-mcp
# Cargo (from crates.io) — compiles from source
cargo install monarch-mcp
# Or build from source
git clone https://github.com/mikelane/monarch-mcp
cd monarch-mcp
cargo install --path .monarch-mcp loginPrompts for your Monarch email, password, and MFA code. The session token is written to
~/.config/monarch-mcp/session.json (mode 0600) and reused for months — your password and
MFA secret are never stored.
Sign in with Apple/Google? Monarch's API needs email+password. Add a password in Monarch → Settings → Security; your SSO login keeps working alongside it.
Claude Code (works today, local stdio):
claude mcp add monarch-mcp -- monarch-mcp…or copy .mcp.json.example to .mcp.json in your project.
Streamable-HTTP (local, loopback-only):
monarch-mcp --httpStarts the same tool set over streamable-HTTP MCP instead of stdio, serving /mcp on
127.0.0.1:8770 by default. Override the bind address with MONARCH_HTTP_ADDR
(e.g. MONARCH_HTTP_ADDR=127.0.0.1:9000 monarch-mcp --http). A /healthz endpoint
returns ok for basic liveness checks.
Important
This mode refuses to bind any non-loopback address — a hard error, never a silent
fallback. It also rejects any request that carries a non-localhost Origin header (an
absent Origin, the normal case for non-browser MCP clients, is allowed), which stops
DNS-rebinding (a malicious webpage rebinding an attacker hostname to 127.0.0.1 so your
browser POSTs to localhost:8770); loopback binding alone doesn't catch that.
See ADR 0018.
There's still no auth and no tunnel here — this is Phase 1 of Claude Cowork support
(issue #88). Exposing the server beyond your machine is Phase 2, and it doesn't exist yet.
Note
Claude Cowork runs MCP servers in an isolated VM and currently can't reach a local
stdio server (known issue).
--http above is the first step toward supporting Cowork, but it's loopback-only —
Cowork's VM still can't reach it without the Phase 2 tunnel work. Use it from Claude
Code on your machine for now. See docs for the trade-offs.
"Give me a financial overview." · "How's our spending vs budget this month?" · "Any creeping subscriptions?" · "Are we on track for our goals?"
progress_vs_goals measures against a TOML file you point to with MONARCH_GOALS_FILE.
See goals.example.toml:
[savings_rate]
target_percent = 20.0
[emergency_fund]
target_months = 6.0- No money movement exists in the binary. The mutating path is an allowlist of
category/tags/notes; any other field in a change request is rejected and reported. - Your token stays local. Auth happens on your machine; the session lives in
~/.config/monarch-mcp/session.json(0600). Credentials are never logged. - Human-in-the-loop writes.
triage_uncategorizedonly proposes; nothing is written until you approve a changeset andapply_changesetcommits exactly that.
Reporting a vulnerability: see SECURITY.md.
Production Rust (rmcp + reqwest + tokio), built TDD/BDD-first, with a deliberate
Google test-size pyramid — because
testing only against mocks ships false confidence (it did, twice — see the ADRs):
| Tier | What | Count |
|---|---|---|
| Small | Hermetic, in-process unit tests (the aggregation/classification math) | ~270 |
| Medium | Behave BDD against a mock Monarch GraphQL server over loopback | ~57 |
| Large | Gated (MONARCH_LIVE=1) integration tests against real Monarch |
8 |
cargo test # small
cd bdd && uv run behave # medium (needs uv + the built binary)
MONARCH_LIVE=1 cargo test --test live_integration # large (needs a real session)The real GraphQL schema and the design decisions are documented in
docs/decisions/ (ADRs 0001–0003).
src/ Rust MCP server — client, tools, goals, server, error
bdd/ Python + behave acceptance suite + mock Monarch GraphQL server
tests/ Large/live integration tests (gated)
docs/decisions/ ADRs (auth flow, real schema, tier-2 schema)
docs/specs/ Design spec
Contributions welcome — see CONTRIBUTING.md for the dev setup
(mise / lefthook / clippy / rustfmt), the test-pyramid expectations, and the
TDD/BDD workflow. Also read CODE_OF_CONDUCT.md.
For the release process (secrets, merge→publish flow), see docs/RELEASING.md.
Dual-licensed under either of MIT or Apache-2.0 at your option. Unless you explicitly state otherwise, any contribution you submit shall be dual-licensed as above, without additional terms.