monzo-mcp is an MCP (Model Context Protocol) server for the UK Monzo bank API, providing read-only access to banking data through Claude Code or any MCP client.
Purpose
This tool is used to securely query Monzo account information within an MCP client, including accounts, balances, pots, transactions, and spending analysis. Its main difference from other Monzo MCP implementations is that instead of using a raw bearer token that expires after 6 hours, it handles the full OAuth flow and automatically refreshes the token.
Main capabilities
- 7 read-only tools: no write operations, no money movement.
- Automatic OAuth refresh: tokens are refreshed automatically, with no need to manually regenerate them.
- Local transaction cache: a SQLite database persists transactions and can survive beyond Monzo's 90-day SCA window.
- On-demand automatic sync: if a cache read tool finds that syncing has not yet been done that day, it automatically performs an incremental sync, usually eliminating the need to manually call monzo_sync.
- Spending analysis: breakdown by category, top merchants, monthly comparisons.
- Transaction search: search cached history by merchant, payee (counterparty), description, or notes.
- Counterparty details: bank transfers (faster payments, p2p, Bacs) cache the recipient's name, sort code, and account number.
Usage
Requirements
- Python 3.13+ (tested on 3.13 and 3.14, with support for Linux, macOS, and Windows, and CI coverage)
- uv (recommended) or pip
- A Monzo account, and an OAuth client registered at developers.monzo.com Note: this package is not on PyPI (that name belongs to an unrelated project); instead, container images are published, as detailed in the Docker section.
Installation steps from source
- Register a Monzo OAuth client: go to developers.monzo.com to create an OAuth client, and set the redirect URL to http://localhost:6600/callback,记录 Client ID and Client Secret.
- Authentication: after running the authentication command, a browser will open for Monzo OAuth. After authorization, login must be approved in the Monzo App within 5 minutes to obtain full transaction history access (Monzo's SCA window).
- Register in Claude Code: on Windows, the console script is located at .venv\Scripts\monzo-mcp.exe. After registration, run monzo_sync in Claude Code to populate the local transaction cache; this should be done immediately after authentication to take advantage of the SCA window (up to about 11 months of history).
Docker Usage
The image is published at ghcr.io/partymola/monzo-mcp, with tags prefixed with v (:vX.Y.Z), and :latest follows the latest release. The container requires a mounted volume, with credentials and the transaction cache located at /data; if not mounted, the container will still start, but all tools will report being unconfigured, and the authorized content will be lost after the container is replaced. You must first register the OAuth client according to step 1 (authentication will prompt for the Client ID and secret, and they cannot be added afterward). The redirect URL is the same as for the source installation. The port published during authentication is only used for that step, so that the OAuth redirect can reach the container; binding to 127.0.0.1 restricts the callback listener to the local network. The container has no browser, so you need to copy the URL it prints. Then approve the login in the Monzo App within 5 minutes, and then reuse the same volume to register the server (-i is required because the server speaks JSON-RPC over stdin/stdout). After registration, monzo_sync should be called immediately, because the 11-month backfill closes 5 minutes after approval in the Monzo App; if missed, only 90 days of data can be obtained with no error indication. If you want the files to be readable, you can use a bind mount instead of a named volume; the container runs as root and writes credentials that are readable only by the owner, and not adding --user will cause the files to be owned by root.
Configuration
All configuration is via environment variables (optional). The container image sets the first two variables in /data, because the package-relative default paths resolve to the interpreter's lib directory and cannot be mounted; the third is set to 0.0.0.0, because the published port reaches the container's bridge interface, localhost binding will be rejected. Credential files (created by monzo-mcp auth): config/monzo_client.json (OAuth client ID and secret), config/monzo_tokens.json (access and refresh token, automatically refreshed).
Monzo SCA window
Monzo's Strong Customer Authentication (SCA) limits transaction history access: within 5 minutes after approval in the App, up to about 11 months of history can be fetched; after the window expires, only the most recent 90 days can be fetched. The local SQLite cache permanently retains all synced transactions, so monzo_sync should be run as soon as possible after monzo-mcp auth. If a specific range needs to be backfilled, a since parameter can be passed to monzo_sync (an ISO date such as 2026-01-01 or a date-time such as 2026-01-01T14:30:00Z). The most recent 90 days are available at any time; earlier ranges can only be fetched within the SCA window, requests outside the window will be rejected, and the sync will silently fetch only content newer than the latest cached transaction. Older cached transactions will only gain fields added in newer versions (for example, counterparty/payee details for bank transfers) after being re-fetched, and a full sync after authentication will do this for the history it re-pulls.
Limitations and security
- Zero write tools: cannot send funds, move funds between savings pots, or modify transactions.
- The Monzo API itself cannot send funds to external accounts.
- Tokens are stored as JSON files in the config/ directory (already added to gitignore).
- All API calls are GET requests authenticated with a Bearer token.
Troubleshooting
- If "SCA required" appears or only 90 days of history are available: re-run monzo-mcp auth and approve the login in the Monzo App within 5 minutes, then sync immediately.
- Token expired / no refresh: re-run monzo-mcp auth to reauthorize.
- "No transaction data available": the cache is empty, call monzo_sync after authentication (or any cache-reading tool, which will sync automatically) once.
- Under Docker, all tools report "not configured" or authentication cannot persist across restarts: /data is not mounted; the same volume must be passed to both the auth run and the server.
- auth is stuck at "Waiting for callback..." after approval: the callback was not delivered, press Ctrl-C and rerun; under Docker, check that the port is published (-p 127.0.0.1:6600:6600).
Development and license
For development environment setup, testing workflow, and pre-commit hooks, see CONTRIBUTING.md; for the changelog, see CHANGELOG.md. The license is GPL-3.0-or-later, see LICENSE for details.