monarch-mcp
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.
Why this exists
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.
The tools
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):
Quick start
1. Install
# 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 .
2. Authenticate (one time)
monarch-mcp login
Prompts 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.
3. Register with your MCP client
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 --http
Starts 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
Originheader (an absentOrigin, the normal case for non-browser MCP clients, is allowed), which stops DNS-rebinding (a malicious webpage rebinding an attacker hostname to127.0.0.1so your browser POSTs tolocalhost: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).
--httpabove 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.
4. Use it
"Give me a financial overview." · "How's our spending vs budget this month?" · "Any creeping subscriptions?" · "Are we on track for our goals?"
Goals (optional)
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
Security model
- 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.
How it's built
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):
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).
Project layout
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
Contributing
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.
License
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.