Skip to main content

ZenMoney MCP Server

MCP server for trustworthy personal-finance analytics and explicitly confirmed user-entity changes over the ZenMoney API. The project started as a fork of nnslvp/zenmoney-mcp and is maintained here as a substantially extended version. It keeps its working data local and adds financially conservative calculations, atomic sync, and a two-step write workflow.

Complete tool catalog

Both local and remote modes expose 56 tools. They share 54 tools and use two mode-specific tools for synchronization and category suggestions.

Area Tools
Financial analytics get_net_worth, get_liquidity, analyze_spending, analyze_income, analyze_merchants, check_budget_health, get_upcoming_payments, analyze_trends, detect_recurring, get_account_flow, analyze_transfers, detect_anomalies, get_debts, convert_currency, get_exchange_rates, search_transactions
Planning analytics get_financial_snapshot, get_cash_flow, get_spending_baseline, compare_periods, get_emergency_fund_status, get_debt_service, forecast_cash_flow
Decision support plan_emergency_fund, plan_debt_payoff, compare_debt_strategies, plan_financial_goal, plan_multiple_goals, run_financial_scenario, build_financial_plan
Entity reads list_accounts, get_account, list_tags, get_tag, list_merchants, get_merchant, list_reminders, get_reminder, list_reminder_markers, get_reminder_marker, list_transactions, get_transaction, list_budgets, get_budget
Confirmed entity changes prepare_account_changes, prepare_tag_changes, prepare_merchant_changes, prepare_reminder_changes, prepare_reminder_marker_changes, prepare_transaction_changes, prepare_budget_changes, prepare_mixed_changes, get_change_proposal, apply_changes
Mode Mode-specific tools
Local stdio sync_data, suggest_category
Remote through OpenAI Secure MCP Tunnel force_sync, get_sync_status

Analytics

Question Tool
How much money do I have? get_net_worth
Can I afford a purchase? get_liquidity
Where does my money go? analyze_spending
Where does my income come from? analyze_income
Which merchants receive my money? analyze_merchants
Am I within budget? check_budget_health
What subscriptions do I have? detect_recurring
How are income and spending changing? analyze_trends
What transfers did I make? analyze_transfers
Are there unusual or duplicate expenses? detect_anomalies
Who owes whom? get_debts
What payments are coming up? get_upcoming_payments
Find matching transactions search_transactions
What happened on this account? get_account_flow
Convert currencies convert_currency, get_exchange_rates
Overall financial position get_financial_snapshot
Monthly cash flow get_cash_flow
Normal spending level get_spending_baseline
Compare periods compare_periods
Emergency fund coverage get_emergency_fund_status
Debt burden get_debt_service
30/60/90 day forecast forecast_cash_flow

The server also exposes paginated collection and exact resources for Account, Tag, Merchant, Reminder, ReminderMarker, Transaction, and Budget, plus currencies, synchronization status, and a cache-only financial snapshot at zenmoney://financial-snapshot. Reading a resource never starts synchronization.

Confirmed user-entity changes

All writes use two separate calls. Choose the entity-specific prepare tool for ordinary work, or prepare_mixed_changes when one proposal creates or changes several related entity types:

prepare_account_changes        prepare_tag_changes
prepare_merchant_changes       prepare_reminder_changes
prepare_reminder_marker_changes
prepare_transaction_changes    prepare_budget_changes
prepare_mixed_changes
get_change_proposal            apply_changes

Prepare validates 1–100 operations and returns an immutable field-by-field preview without writing to ZenMoney. After reviewing it, pass only its proposal_id to apply_changes; get_change_proposal reports state and results.

Preparation requires a successful full sync so that untouched ZenMoney fields can be preserved. Apply rejects the whole proposal before writing if any source entity changed since preparation. Related creates are submitted in dependency layers because the live API does not safely accept every dependency in one Diff request; a failed layer is never retried or rolled back automatically.

Create and update are supported for all seven user entities. Safe delete archives an Account, marks a Transaction or ReminderMarker deleted, or clears a Budget. Tag, Merchant, and Reminder deletion and all physical purge operations are not exposed. Prepared proposals expire after 24 hours. Terminal proposals are retained for 30 days, and an uncertain write or verification result becomes needs_review.

Planning analytics are deliberately conservative:

  • emergency-fund coverage requires explicit essential category IDs or a monthly essential-spending override;
  • debt service reports observed balances and payments but does not infer APR, minimum payments, or amortization schedules;
  • recurring-payment detection is a historical heuristic and is labeled as such;
  • cash-flow forecasts are transparent scenarios, not prediction guarantees.

Financial Planning

Phase 3 adds deterministic decision support on top of the factual analytics. Every result exposes inputs, assumptions, constraints, reasons, alternatives, and measurable outcomes; it does not execute or write a financial decision.

Question Tool
How fast can I build a 6-month emergency fund? plan_emergency_fund
Should I pay the high-interest loan first? plan_debt_payoff, compare_debt_strategies
Can I afford a car in 18 months? plan_financial_goal
Which of my goals conflict? plan_multiple_goals
What happens if my income falls by 20%? run_financial_scenario
How should I allocate my monthly free cash flow? build_financial_plan

Planning inputs that ZenMoney does not contain must be supplied explicitly:

{
  "emergency_fund": {
    "target_months": 6,
    "essential_category_ids": ["category-id"]
  },
  "debt_accounts": {
    "loan-account-id": {
      "apr_pct": 19.9,
      "minimum_payment": 15000
    }
  },
  "goals": []
}

Missing APR, minimum payments, or essential-spending configuration returns configuration_required; the server never invents those values. Calculations use zero investment return, Decimal money arithmetic, and future calendar month-end snapshots. Restricted deposits are excluded from emergency reserves unless explicitly enabled, and credit capacity is always excluded.

See docs/planning-semantics.md for the priority policy, formulas, rounding, data-quality labels, and limitations.

Runtime modes

The installed zenmoney-mcp command is the local stdio server for Codex, ChatGPT Desktop, Claude Desktop, and Cursor. It uses the shared SDK v2 registry and hardened runtime directly; it does not preserve an upstream server through a runtime overlay.

For a private remote deployment, zenmoney-mcp-http exposes Streamable HTTP at /mcp only inside Docker, and the OpenAI Secure MCP Tunnel client connects outbound to OpenAI. The remote registry excludes the local API-dependent sync_data and suggest_category tools. Its analytical tools remain read-only. Remote force_sync can request a cache refresh, while confirmed entity-change proposals are queued for the separate credentialed worker. get_sync_status and get_change_proposal report their respective progress. The MCP container still receives no ZenMoney token and cannot write the financial snapshot or call ZenMoney directly. See the remote operations runbook and threat model.

Hardening in this fork

The installed zenmoney-mcp command runs zenmoney_mcp.entrypoint against a shared SDK v2 registry with hardened database, synchronization, and analytics implementations:

  • HardenedDatabase adds idempotent migrations and strict FX handling;
  • HardenedSyncEngine validates responses and atomically replaces the live cache;
  • corrected analytics cover net worth, liquidity, budgets, debts, account flow, spending, transaction search, upcoming payments, and FX;
  • remaining analytics receive bounded runtime validation;
  • MCP discovery advertises the same limits enforced at runtime.

Key semantics:

  • net_worth includes only active accounts with in_balance=true;
  • excluded accounts are returned separately in net_worth_all_accounts;
  • credit is borrowing capacity, not an asset;
  • accessible savings and term deposits are not treated as equivalent liquidity;
  • budget periods respect the user's configured month-start day;
  • zero-budget and unbudgeted spending are surfaced explicitly;
  • debt-account balances are authoritative and attribution gaps remain visible;
  • account flow includes signed transfers in native and user currency;
  • missing or zero exchange rates fail explicitly instead of becoming a 1:1 rate;
  • full sync replaces the cache, preventing stale rows from surviving.

More detail is available in README-HARDENING.md.

Local installation with uvx

Install uv, then run the server from PyPI:

Get a personal API token at zerro.app/token, as documented in the official ZenMoney API wiki.

export ZENMONEY_TOKEN="replace-with-your-token"
uvx --from zenmoney-mcp-server zenmoney-mcp

uvx downloads the package into an isolated cached environment; cloning the repository or creating a virtual environment is not required.

To run the current main branch before its next PyPI release, use uvx --from git+https://github.com/ekho/zenmoney-mcp.git zenmoney-mcp.

The first hardened start performs additive SQLite migrations. Back up ~/.cache/zenmoney-mcp/zenmoney.db before the first run when preserving an existing cache matters. A full sync can recreate the cache from ZenMoney.

Private ChatGPT installation with OpenAI Secure MCP Tunnel

ChatGPT web cannot start the local stdio command. For private remote access, run the included Docker Compose deployment and connect it through OpenAI Secure MCP Tunnel. The MCP endpoint stays inside the Docker network; only the tunnel client makes an outbound connection to OpenAI.

This mode requires Docker Engine with Compose v2, a ZenMoney token, an OpenAI tunnel runtime API key, and a tunnel ID associated with the target ChatGPT workspace. Clone the repository and create the non-secret environment file:

git clone https://github.com/ekho/zenmoney-mcp.git ~/zenmoney-mcp
cd ~/zenmoney-mcp
cp deploy/remote-mcp/.env.example deploy/remote-mcp/.env

Set CONTROL_PLANE_TUNNEL_ID in deploy/remote-mcp/.env. Provision the ZenMoney token and OpenAI key as separate file-backed Compose secrets using the ownership and permission commands in the remote operations runbook; do not put either secret in .env. Then pull and start the deployment:

docker compose --env-file deploy/remote-mcp/.env \
  -f deploy/remote-mcp/compose.yaml pull
docker compose --env-file deploy/remote-mcp/.env \
  -f deploy/remote-mcp/compose.yaml up -d --no-build --pull never
docker compose --env-file deploy/remote-mcp/.env \
  -f deploy/remote-mcp/compose.yaml ps

Complete the health checks and tunnel-client doctor from the runbook, then add the MCP app in ChatGPT Developer Mode with Connection = Tunnel and scan its tools.

ChatGPT Desktop and Codex

Add the server to ~/.codex/config.toml:

[mcp_servers.zenmoney]
command = "uvx"
args = ["--from", "git+https://github.com/ekho/zenmoney-mcp.git", "zenmoney-mcp"]
env_vars = ["ZENMONEY_TOKEN"]
tool_timeout_sec = 120

Restart the desktop client after changing MCP configuration. For ChatGPT web, use the private remote Streamable HTTP + Secure MCP Tunnel deployment in the operations runbook, not a local executable.

Claude Desktop or Cursor

{
  "mcpServers": {
    "zenmoney": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/ekho/zenmoney-mcp.git",
        "zenmoney-mcp"
      ],
      "env": {
        "ZENMONEY_TOKEN": "replace-with-your-token"
      }
    }
  }
}

Development

Clone the repository only when changing or testing the code locally:

git clone https://github.com/ekho/zenmoney-mcp.git ~/zenmoney-mcp
cd ~/zenmoney-mcp
uv sync --extra dev

Data flow

  1. Local sync_data reads /v8/diff/ directly through the local sync engine.
  2. In the remote deployment, the periodic worker reads /v8/diff/; remote force_sync only asks that credentialed worker to run immediately.
  3. Both modes publish a SQLite cache at ~/.cache/zenmoney-mcp/zenmoney.db or the configured ZENMONEY_DB_PATH; analytics read that cache locally.
  4. A local confirmed proposal is written synchronously. A remote confirmed proposal is persisted on the control volume and written by the worker.
  5. Only the local process or credentialed worker can call ZenMoney.

Testing

uv sync --extra dev
uv run python -m compileall -q src tests
uv run python -m pytest tests/ -v --ignore=tests/test_integration.py

The live integration test requires ZENMONEY_TOKEN and is excluded from CI.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zenmoney_mcp_server-0.5.1.tar.gz (101.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zenmoney_mcp_server-0.5.1-py3-none-any.whl (116.9 kB view details)

Uploaded Python 3

File details

Details for the file zenmoney_mcp_server-0.5.1.tar.gz.

File metadata

  • Download URL: zenmoney_mcp_server-0.5.1.tar.gz
  • Upload date:
  • Size: 101.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for zenmoney_mcp_server-0.5.1.tar.gz
Algorithm Hash digest
SHA256 4dc420d5bd25e2f9071f52918f2e36bab8d032f3341e034a33c36d551473d094
MD5 8ec187756e1cba8ddb28e5fbb8a6d882
BLAKE2b-256 bbc2ebd283b00dcf01d6c6b86aaea70877b4c86734bf687dd664b1f12841067d

See more details on using hashes here.

File details

Details for the file zenmoney_mcp_server-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: zenmoney_mcp_server-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 116.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for zenmoney_mcp_server-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f8ec357497400bb446b8a98a0d57f72b000e6de7b527481f8d3ade5ef824adfe
MD5 9b414756b9d5b3cfdcecb9f5a4139619
BLAKE2b-256 fec98b0e0f3d7c5d331c883662e363f2ac89e1113191c4ba867a892765fc939f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.2

2 files

This release

0.5.1 This release

2 files

0.5.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page