A personal Go CLI and MCP server for Monarch Money's (unofficial) GraphQL API — the same API the web app uses — so you can pull accounts, transactions, budgets, cashflow, recurring bills, and net worth from the terminal, scripts, or an LLM connected over MCP.
The API client is written from scratch in pkg/monarch with zero
third-party dependencies (stdlib + golang.org/x/term for prompts): no
telemetry, no community client libraries, the only host contacted is
api.monarch.com. A supply-chain audit of the previous third-party client
motivated the rewrite; UPSTREAM.md documents how upstream fixes are tracked
without importing code.
⚠️ This is an unofficial API. Monarch can change or break it at any time, and heavy automated use is at your own risk.
Build from source:
go build -o monarch .monarch login
# Email: you@example.com
# Password: ******** (never echoed; requires a TTY)
# Two-factor code: 123456 (if MFA is enabled)On macOS the session token is stored in your login Keychain (service
monarch-cli), encrypted at rest; an existing session file from older
versions (~/Library/Application Support/monarch/session.json on macOS —
the ~/.config path applies on Linux) is migrated in automatically.
Elsewhere (or with MONARCH_SESSION_FILE=/path) it's a 0600 JSON file. Honest caveat: because
the item is written via Apple's security tool, any process running as you
can read it back the same way — Keychain protects the token at rest and while
the keychain is locked, not against same-user malware.
Alternatives:
monarch login --totp— generates the 2FA code from your TOTP secret, read fromMONARCH_TOTP_SECRETor a hidden prompt (never a CLI argument — argv is visible to other processes).monarch login --password-stdin— read the password from stdin for scripted use.MONARCH_TOKEN=<token>— use a bearer token you extracted yourself (web app devtools: any GraphQL request →Authorization: Token <token>header).
monarch whoami shows the current session; monarch logout deletes it.
Every data command accepts --json for raw output (pipe into jq).
monarch overview # accounts + this month's cashflow + recent activity
monarch accounts # balances by account + net worth line
monarch transactions --start 2026-07-01 --end 2026-07-31 --limit 100
monarch transactions --search "whole foods" --min 20
monarch transactions --category <id> --account <id> --tag <id>
monarch transactions --needs-review --has-notes --is-recurring
monarch transactions --all --csv > transactions.csv
monarch transactions --id <txID> # full detail incl. splits
monarch summary # lifetime totals
monarch budget --month 2026-07 [--csv]
monarch cashflow --start 2026-01-01 --end 2026-06-30 --top 15
monarch categories # category IDs for filtering
monarch recurring # subscriptions/bills + est. monthly total
monarch networth --start 2025-08-01 --timeframe month
monarch networth --daily # per-day aggregate balance
monarch holdings [--account id] # investment positions
monarch rules # auto-categorization rules
monarch goals # savings goals
monarch institutions # connection health (stale-balance culprits)Sign convention follows Monarch: expenses are negative amounts, income
positive. --min/--max bound the absolute amount and apply per fetched
page (combine with --all for whole-range filtering).
monarch whoami performs a live server check, not just a local one.
Optional env overrides: MONARCH_DEVICE_UUID (pin a token's device
identity), MONARCH_CLIENT_VERSION, MONARCH_USER_AGENT.
monarch mcp serves an MCP server on stdio with eighteen read tools:
get_accounts, get_transactions, get_transaction,
get_transaction_summary, get_budget, get_cashflow,
get_cashflow_summary, get_categories, get_tags, get_merchants,
get_recurring, get_networth_history, get_holdings, get_rules,
get_goals, get_institutions, get_credit_score, and check_session.
Register with Claude Code (read-only — recommended default):
go build -o ~/bin/monarch .
claude mcp add monarch --scope user -- ~/bin/monarch mcpClaude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"monarch": { "command": "/Users/you/bin/monarch", "args": ["mcp"] }
}
}The write tools cover transactions (update_transaction,
create_transaction, delete_transaction [confirm], bulk_categorize
and bulk_update_transactions [up to 25/call, dry-run by default],
set_transaction_splits [sum-validated]), budgets (set_budget_amount),
tags (create_tag / update_tag / delete_tag [confirm]), merchants
(update_merchant, merge_merchants [confirm]), categories
(create_category / update_category / delete_category [confirm]),
rules (create_rule / update_rule / delete_rule [confirm on
delete; back-applying needs apply_to_existing=true]), goals
(contribute_to_goal / withdraw_from_goal [confirm; moves real
money], create_goal / archive_goal / delete_goal [confirm on
archive/delete]), and accounts (refresh_accounts — a remote action that
re-syncs all accounts from their institutions; poll with the
refresh_status read). None are registered unless the server is started
with both the --allow-writes flag and MONARCH_MCP_ALLOW_WRITES=1; a
mismatch refuses to start. Register it as a separate server entry and only while you're actively
doing a cleanup session:
claude mcp add monarch-rw --scope user --env MONARCH_MCP_ALLOW_WRITES=1 -- \
~/bin/monarch mcp --allow-writesEvery tool call is rate-limited (30/min), capped at 3 concurrent API calls, and timed out at 30s; logs go to stderr and never contain the token.
make check # gofmt + vet + build + tests + govulncheck — required when deps change
go test . -update # regenerate golden files after intentional output changesArchitecture, the Monarch API contract (headers, MFA protocol, GraphQL quirks), and security invariants are documented in CLAUDE.md. Upstream drift-monitoring policy and watchlist: UPSTREAM.md.