ZenMoney 个人财务 MCP 服务器

ZenMoney MCP 服务器为 AI 助手提供 ZenMoney 个人财务数据的统一访问能力,支持账户、交易、预算、标签、商户、货币汇率等查询以及交易的创建、编辑和删除,适用于个人记账、预算管理和财务数据分析。

  • by roher-roher
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 roher-roher/zenmoney-mcp

使用说明

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:

  1. Open Zerro.app and log in with your ZenMoney account
  2. Open browser DevTools (F12) → Application → Local Storage
  3. Find the token key 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-dd format
  • 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 account and amount; money leaves the account
  • income — requires account and amount; money arrives on the account
  • transfer — requires from_account, to_account and from_amount. to_amount defaults to from_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.

  • amount is a shortcut that sets whichever leg is non-zero — it only works for plain expenses/income. For transfers set income and/or outcome explicitly.
  • Changing income_account / outcome_account also 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-dd format (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, or deleted
  • date_from / date_to — date range in yyyy-MM-dd format

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