使用说明
ZenMoney MCP Server
A Model Context Protocol (MCP) server for the ZenMoney personal finance service. Provides AI assistants with access to your financial data: accounts, transactions, budgets, categories, and more — plus full create/read/update/delete support for transactions.
Features
- Accounts — balances, credit limits, account types (cards, cash, loans, deposits)
- Transactions — full history with filtering by date, account, and category
- Transaction CRUD — create expenses, income and transfers; edit and delete them
- Budgets — monthly spending limits by category
- Tags — hierarchical transaction categories
- Merchants — payees and payers
- Reminders — recurring transaction templates and planned instances
- Currencies — all instruments with exchange rates
- Caching — data is fetched once and served from memory; refresh on demand
- ID resolution — raw IDs are resolved to human-readable names (account titles, currency codes, tag names, merchant names)
Getting a Token
This server requires a ZenMoney OAuth2 access token. You can obtain one from Zerro.app:
- Open Zerro.app and log in with your ZenMoney account
- Open browser DevTools (F12) → Application → Local Storage
- Find the
tokenkey and copy its value
Alternatively, register your own OAuth2 application via the ZenMoney API.
Quick Start
No installation required — run directly with npx:
ZENMONEY_TOKEN=your-token npx -y @roher/zenmoney-mcp
Configuration
Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"zenmoney": {
"command": "npx",
"args": ["-y", "@roher/zenmoney-mcp"],
"env": {
"ZENMONEY_TOKEN": "your-token-here"
}
}
}
}
Claude Code
Add to ~/.claude/settings.json under mcpServers:
{
"zenmoney": {
"command": "npx",
"args": ["-y", "@roher/zenmoney-mcp"],
"env": {
"ZENMONEY_TOKEN": "your-token-here"
}
}
}
Then run /mcp in Claude Code to reconnect MCP servers.
VS Code
Add to your .vscode/mcp.json:
{
"servers": {
"zenmoney": {
"command": "npx",
"args": ["-y", "@roher/zenmoney-mcp"],
"env": {
"ZENMONEY_TOKEN": "your-token-here"
}
}
}
}
Building from Source
git clone https://github.com/roher-roher/zenmoney-mcp.git
cd zenmoney-mcp
npm install
npm run build
Then use node /path/to/zenmoney-mcp/build/index.js instead of npx in the configurations above.
Tools
| Tool | Description | Parameters |
|---|---|---|
get_accounts |
List all accounts with balances | include_archived? |
get_transactions |
Get transactions with filtering and pagination | date_from?, date_to?, account_id?, tag_id?, include_deleted?, limit?, offset? |
get_transaction |
Get one transaction by id | id |
create_transaction |
Create an expense, income, or transfer | type, date?, account?, amount?, from_account?, to_account?, from_amount?, to_amount?, tags?, merchant?, payee?, comment?, qr_code?, source?, hold?, latitude?, longitude? |
update_transaction |
Change fields of an existing transaction | id, date?, amount?, income?, outcome?, income_account?, outcome_account?, tags?, merchant?, payee?, comment?, qr_code?, hold? |
delete_transaction |
Delete a transaction (irreversible) | id |
get_tags |
List all categories/tags with hierarchy | — |
get_merchants |
List all merchants | — |
get_instruments |
List currencies with exchange rates | — |
get_budgets |
Get monthly budget entries | date?, tag_id? |
get_reminders |
List recurring transaction templates | — |
get_reminder_markers |
Get planned transaction instances | state?, date_from?, date_to? |
get_user |
Get user information | — |
refresh_data |
Invalidate cache and re-fetch from API | — |
Tool Details
get_accounts
Returns all user accounts (bank cards, cash, loans, deposits, e-wallets, debt trackers) with current balances and currency codes.
get_transactions
Returns transactions sorted by date (newest first). Supports filtering:
- date_from / date_to — date range in
yyyy-MM-ddformat - account_id — filter by income or outcome account UUID
- tag_id — filter by category UUID
- include_deleted — include soft-deleted transactions (default:
false) - limit / offset — pagination (default: 1000 / 0)
Response includes total count for pagination.
create_transaction
ZenMoney models every transaction as a pair of income / outcome legs, both with positive amounts. This tool hides that behind a type:
- expense — requires
accountandamount; money leaves the account - income — requires
accountandamount; money arrives on the account - transfer — requires
from_account,to_accountandfrom_amount.to_amountdefaults tofrom_amount, and is required when the two accounts use different currencies (that is how you record a currency exchange).
date defaults to today. Currencies are taken from the accounts involved.
Accounts, tags and merchants can be referenced either by UUID or by exact title (case-insensitive); an ambiguous title returns an error listing the candidate ids. Merchants must already exist — for arbitrary names use the free-text payee field instead.
// 1500 ₽ groceries, paid by card
{ "type": "expense", "account": "Tinkoff Black", "amount": 1500, "tags": ["Продукты"], "payee": "Пятёрочка" }
// currency exchange: 100 EUR from the euro account into 10 000 ₽ cash
{ "type": "transfer", "from_account": "EUR", "to_account": "Наличные",
"from_amount": 100, "to_amount": 10000 }
Fiscal receipts (qr_code)
qr_code holds the payload of the QR code printed on a Russian fiscal receipt — a plain query string, not a link to an image:
t=20200429T0822&s=8930.00&fn=9280440300302668&i=103878&fp=1218439113&n=1
| Field | Meaning |
|---|---|
t |
receipt timestamp, yyyyMMddTHHmm or yyyyMMddTHHmmss |
s |
total of the whole receipt |
fn |
fiscal drive number |
i |
fiscal document number |
fp |
fiscal sign |
n |
settlement type — 1 sale, 2 sale refund, 3 expense, 4 expense refund |
rnm |
cash register registration number (optional) |
The OFD link form (https://consumer.1-ofd.ru/v1?fn=…&fp=…&i=…&t=…&s=…&n=…) is accepted too. ZenMoney itself stores the field without validating it, but a value missing the receipt identifiers is useless, so this server rejects one before sending it.
s is not the transaction amount. One receipt is routinely split across several transactions, all carrying the same qr_code, so never reconcile a single transaction against it.
source records where a transaction came from (sms, push, split, plugin, api; omitted for manual entry). It is write-once — ZenMoney silently ignores any later change — so it is only available on create_transaction.
update_transaction
Only the fields you pass are modified. Nullable fields (tags, merchant, payee, comment, qr_code, hold) accept null to clear them.
amountis a shortcut that sets whichever leg is non-zero — it only works for plain expenses/income. For transfers setincomeand/oroutcomeexplicitly.- Changing
income_account/outcome_accountalso switches that leg to the new account's currency. - Deleted transactions cannot be edited (see below).
delete_transaction
Deletion is irreversible. ZenMoney flags the transaction as deleted and then refuses every subsequent write to that id — there is no "trash" you can restore from through the API. A mistaken delete can only be compensated by creating a new transaction.
This is not a choice this server makes; it is how the API behaves. Both documented deletion mechanisms — sending the object with deleted: true and sending an entry in the deletion array — produce the same tombstone, and a later deleted: false is silently ignored. Because there is no meaningful difference between them, only one delete is exposed.
update_transaction and delete_transaction both refuse up front to touch an already-deleted transaction rather than issuing a write the server would drop.
get_budgets
Returns budget entries (monthly spending/income limits per category). Filter by:
- date — month start date in
yyyy-MM-ddformat (e.g.2025-01-01) - tag_id — specific category UUID
get_reminder_markers
Returns planned transaction instances generated from reminders. Filter by:
- state —
planned,processed, ordeleted - date_from / date_to — date range in
yyyy-MM-ddformat
How It Works
The server uses the ZenMoney /v8/diff/ API endpoint — the only mechanism ZenMoney exposes, for both reads and writes.
Caching and sync:
- First run — performs a full sync (
serverTimestamp: 0) and saves the result to disk at~/.zenmoney-mcp/cache.json - Subsequent runs — loads cached data from disk and fetches only changes since the last sync (incremental diff), which is significantly faster
- Within a session — all tool calls are served from in-memory cache with no additional API requests
refresh_data— clears both disk and in-memory cache; the next tool call will perform a full sync
Writes: create/update/delete send the changed objects in the same /v8/diff/ request. The server replies with a diff of everything that changed since the last sync — the written object plus side effects such as recalculated account balances — and only that reply is merged into the cache, so no extra refresh is needed after a write.
Nothing is merged optimistically, and that is deliberate. ZenMoney answers 200 OK even when it decides to ignore a write, and the only evidence a change actually landed is the object coming back in the diff. These tools check for it and report an error when it is missing, rather than reporting success for a change the server dropped.
Writes send the complete object: the API validates strictly and rejects a transaction that is missing any field, including ones it never populates itself (qrCode, source, incomeBankID, outcomeBankID). Note that API v8 has no mcc field on transactions at all.
ID resolution: all internal IDs are automatically resolved to human-readable values — account names, currency codes (e.g. RUB, USD), tag titles, and merchant names.
License
MIT