ezbookkeeping-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ezbookkeeping-mcphow much did I spend last month, broken down by category?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ezbookkeeping-mcp
Let AI assistants and scripts read and manage your self-hosted ezBookkeeping books, safely.
An MCP server and a command-line tool for ezBookkeeping v2.1.0. Both are built on one core, so Claude, Cursor, a custom agent or a PowerShell script all get the same tools and the same JSON.
What it does
Accounts and transactions: balances, filtered and paginated transaction lists, and add, edit or delete for expenses, income and transfers.
Categories and tags: list and create.
Analysis:
monthly income and expense with a per-category breakdown;
category reports;
net worth with a debt summary that lists overdraft, credit cards and personal debts separately;
cash flow in day, week or month buckets with a running balance;
recurring payment and subscription detection;
installment plans parsed from notes on debt accounts.
Bulk import: preview a file with ezBookkeeping's own parser, then import validated rows.
Exact money handling:
amounts are returned both as integer minor units (
kurus) and as decimal strings (tl);input with a comma or a dot is converted exactly;
totals are reported per currency and never summed across currencies.
Safe by default:
read and write tools are separated, and a read-only switch disables all writes;
every write has a dry run;
delete requires confirmation;
the API token is never printed.
Easy to deploy: two self-contained bundles (
cli.cjs,server.cjs) that run with plainnode. Nonode_modulesare needed, and they work from any directory.Full UTF-8 support: Turkish and other non-ASCII category, tag and account names work everywhere.
Related MCP server: lastro
Tools
Tool | Access | Description |
| read | ezBookkeeping version and the active configuration (never the token) |
| read | Accounts with balances, kind (asset/liability), liability type and per-currency totals |
| read | Transactions filtered by date, account, category, tag, type and keyword; cursor pagination or fetch-all |
| read | One transaction by id |
| read | Categories with full |
| read | Tags |
| read | Income, expense, net and category breakdown for 1–36 months |
| read | Expense or income by sub-category or parent category over a date range |
| read | Assets, liabilities and net worth per currency; debts split into overdraft, credit cards and personal debts |
| read | Inflow, outflow and running balance in day, week or month buckets |
| read | Recurring payments and subscriptions: cadence, average amount, confidence and next expected date |
| read | Installment plans parsed from liability account notes (grammar) |
| read | Preview a bank or export file through the server's import parser; saves nothing |
| write | Add an expense, income or transfer |
| write (destructive) | Change only the given fields of a transaction; keeps pictures and location |
| write (destructive) | Delete one transaction; requires |
| write | Create a primary category or a sub-category |
| write | Create a tag |
| write | Import up to 5,000 validated transactions in one request |
The MCP annotations match:
Read tools:
readOnlyHint: true,destructiveHint: false,idempotentHint: true.Edit and delete:
destructiveHint: true,idempotentHint: true.Add, create and import:
readOnlyHint: false,idempotentHint: false.
Every write tool accepts dryRun.
Quick start
From source
git clone https://github.com/Septillioner/ezbookkeeping-mcp.git
cd ezbookkeeping-mcp
npm install
npm run build # dist/cli.cjs and dist/server.cjsexport EZBK_BASE_URL=http://localhost:8090
export EZBK_TOKEN=<your ezBookkeeping API token>
node dist/cli.cjs accounts listPrebuilt bundles
Download ezbookkeeping-mcp-windows.zip from Releases.
It contains cli.cjs and server.cjs and works on any OS with Node.js 18.17 or newer, despite the name. Unzip it
anywhere and run node cli.cjs ping. For a step-by-step Windows setup, see
docs/DEPLOY_WINDOWS.md.
Create the API token in ezBookkeeping under Settings → API tokens.
Configuration
All settings are environment variables. The tools do not read .env files; .env.example lists
them for reference.
Variable | Default | Description |
|
| ezBookkeeping URL. A trailing |
| – | API token |
| – | Path to a file containing the token, used when |
|
| IANA timezone for dates, month boundaries and the |
|
|
|
|
| Per-request timeout in milliseconds (100–600000) |
| – | Comma-separated debt account ids to classify as overdraft |
|
| Log requests to stderr. |
|
| Bind address for the optional HTTP transport ( |
The token is resolved in this order: EZBK_TOKEN, then EZBK_TOKEN_FILE, then (Windows only)
C:\ezbookkeeping\API_TOKEN.txt. Token files are parsed leniently:
a BOM, CRLF line endings, blank lines and
#////;comments are allowed;the token can be bare,
KEY=value,KEY: value, quoted, or prefixed withBearer;when several lines qualify, a JWT-looking value wins.
MCP client setup
Cursor
~/.cursor/mcp.json (global) or .cursor/mcp.json (per project):
{
"mcpServers": {
"ezbookkeeping": {
"command": "node",
"args": ["/opt/ezbookkeeping-mcp/server.cjs"],
"env": {
"EZBK_BASE_URL": "http://localhost:8090",
"EZBK_TOKEN_FILE": "/home/you/.config/ezbookkeeping/API_TOKEN.txt",
"EZBK_TIMEZONE": "Europe/Istanbul"
}
}
}
}Claude Desktop
Config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
On Windows, use escaped backslashes in paths:
{
"mcpServers": {
"ezbookkeeping": {
"command": "node",
"args": ["C:\\ezbookkeeping\\mcp\\server.cjs"],
"env": {
"EZBK_BASE_URL": "http://localhost:8090",
"EZBK_TOKEN_FILE": "C:\\ezbookkeeping\\API_TOKEN.txt",
"EZBK_TIMEZONE": "Europe/Istanbul",
"EZBK_READ_ONLY": "true"
}
}
}
}The same blocks work in either client. Set EZBK_READ_ONLY to "true" or add "--read-only" to args for an
assistant that should only read; the write tools are then not listed at all.
node server.cjs --http 8765 serves stateless Streamable HTTP at POST http://127.0.0.1:8765/mcp.
CLI
node cli.cjs <resource> <action> [--flags] [--json] [--compact] [--out file.json] [--input file.json|-]node cli.cjs accounts list --json
node cli.cjs transactions list --from 2026-10-01 --to 2026-10-31 --account 3001 --json
node cli.cjs transactions list --keyword market --all --json
node cli.cjs transactions add --type expense --amount 125.50 --account 3001 --category 2011 \
--time "2026-10-21 12:30" --comment "Groceries" --dry-run
node cli.cjs transactions add --type transfer --amount "8.000,00" --account 3001 --to-account 3003 --category 4012
node cli.cjs transactions edit --id 123 --amount 99.90
node cli.cjs transactions delete --id 123 --yes
node cli.cjs stats monthly --month 2026-09 --months 3 --json
node cli.cjs stats categories --from 2026-09-01 --to 2026-09-30 --level parent
node cli.cjs networth
node cli.cjs cashflow --from 2026-01-01 --to 2026-10-31 --bucket month --json
node cli.cjs recurring --json
node cli.cjs installments --json
node cli.cjs import parse --type ofx --file statement.ofx --json
node cli.cjs tools list
node cli.cjs help transactions addCommand | Tool |
| reference reads |
|
|
|
|
| analysis reads |
|
|
| write tools |
| write tools |
Flags
Flags are the tool input names in kebab case (
--destination-account-id).Short aliases:
--account,--to-account,--category,--tag(s),--limit,--all,--yes,--q,--parent,--hidden,--type(file type forimport parse).Lists accept
3001,3003or["3001","3003"].Unknown flags and stray arguments are errors, so a typo never silently drops a filter.
Output and exit codes
Without
--json, the output is a short human-readable view.Exit codes:
0success;1API, network or configuration error;2usage error, validation error or read-only refusal.
Amounts and dates
Output: every amount is
{ "kurus": 12550, "tl": "125.50", "currency": "TRY" }.kurusis the integer the API stores (minor units of that currency).tlis the same value as a decimal string.Totals are lists with one entry per currency.
Amount input:
125.50,125,50,1.234,56,1,234.56,₺125,50,125.50 TLor a number.More than two decimals is rejected, never rounded.
1,234and1.234are rejected as ambiguous. Write1234,1234.00or1.234,00.
Date input:
YYYY-MM-DD(atodate covers the whole day),YYYY-MM-DD HH:mm[:ss]inEZBK_TIMEZONE, ISO 8601 with an offset, or unix seconds.Month boundaries are local midnight.
transactions adduses the current time when--timeis omitted.
JSON envelope
Every MCP result and every --json output has the same shape:
{
"ok": true, // false on any error
"data": { }, // present when ok
"error": { // present when !ok
"kind": "validation | auth | not_found | api | http | network | timeout | read_only | config | parse | internal",
"message": "human readable; never contains the token",
"httpStatus": 400, // optional
"apiErrorCode": 205001, // optional, ezBookkeeping error code
"issues": [{ "path": "amount", "message": "..." }], // optional, input validation
"context": { "importedCount": 3, "totalCount": 5 } // optional, from the server
},
"meta": {
"tool": "read_networth",
"access": "read", // or "write"
"readOnlyMode": false,
"timezone": "Europe/Istanbul",
"generatedAt": "2026-10-21T10:00:00+03:00",
"version": "0.1.0"
// plus tool-specific counters: count, pages, truncated, transactionsScanned, ...
}
}Money = { kurus, tl, currency }; Money[] = one entry per currency, sorted by currency code.
Command |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
How bots and agents use it
MCP clients (Claude, Cursor, agent frameworks):
Connect to
server.cjsand call the tools.Results come back as the JSON envelope, both as text and as
structuredContent.Failed calls set
isError.
Scripts and non-MCP agents call the CLI with an absolute path and --json. One install can be shared by
several bots, because nothing is read from the current directory.
# Windows PowerShell 5.1: make the console UTF-8 so non-ASCII names print correctly
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$r = node C:\ezbookkeeping\mcp\cli.cjs networth --json | ConvertFrom-Json
if (-not $r.ok) { throw "$($r.error.kind): $($r.error.message)" }
$r.data.debts.creditCards.totalOwed | ForEach-Object { "$($_.tl) $($_.currency)" }
# Large results: write the envelope to a UTF-8 file instead of parsing console output
node C:\ezbookkeeping\mcp\cli.cjs transactions list --from 2026-01-01 --all --compact --json --out tx.json > $null
$tx = Get-Content tx.json -Raw -Encoding UTF8 | ConvertFrom-Json
# Complex input as JSON on stdin avoids quoting problems
'{"type":"expense","amount":"349,90","accountId":"3004","categoryId":"2023","comment":"Streaming"}' |
node C:\ezbookkeeping\mcp\cli.cjs transactions add --input - --dry-run --jsonRecommendations for agent builders:
Give read-only agents
EZBK_READ_ONLY=true.Always run a write once with
dryRunand show it to the user before sending it for real.Branch on
error.kind, not on message text.Use
nextCursor(orfetchAllwithmaxItems) for long transaction lists.
Safety model
Guard | Behaviour |
Read-only mode |
|
Read/write separation |
|
Dry run | Every write accepts |
Confirm on delete |
|
Validation before writes | Accounts, sub-categories of the right type, hidden categories, tags, transfer direction, currencies and amount format are checked before any request. Ids are passed through as strings (int64-safe). Unknown input keys are rejected |
Edits preserve data | Edit sends back existing pictures and geolocation so they are not lost |
Token redaction | The token is registered as a secret and replaced with |
Network scope | Only |
Testing
npm run lint # Biome
npm run typecheck # tsc --noEmit
npm run coverage # Vitest + V8 coverage (thresholds: 90% on all metrics)
npm run build # esbuild bundles
npm run release # build + release/ezbookkeeping-mcp-windows.zipThe suite has 553 tests in 20 files, all passing. Coverage on src/:
Lines | Branches | Functions | Statements |
98.93% | 93.63% | 97.66% | 98.93% |
The tests cover:
unit tests for money, time, token, config, redaction, the parsers and the recurring detector;
every tool against success, the error envelope, 401/403/404/500, network failure, timeout, invalid input and empty data;
a real local HTTP mock of the v2.1.0 API with fictional fixtures, including Turkish names;
a 2,500-transaction dataset checked for complete pagination;
MCP protocol tests over in-memory, stdio and HTTP transports;
CLI JSON snapshots;
safety tests: exact ids, transfer direction, dry run sends nothing, and the token never appears in any output;
end-to-end tests of the built bundles.
Compatibility
ezBookkeeping v2.1.0: endpoints and field formats come from the v2.1.0 source. Every endpoint is listed with file and line references in docs/API_NOTES.md. Other versions may work but are untested.
Live check: a read-only smoke test passed against a live v2.1.0 instance on Windows 11 with Node.js 26.
Node.js: 18.17 or newer. CI runs on Ubuntu and Windows with Node 18, 20 and 22.
Known limitations
These points have only been tested against the mock server, not against a live instance:
Import (
read_import_parse,write_import_transactions) needsEnableDataImportturned on in the ezBookkeeping server config. Otherwise it returnsnot_found. The CSV column-mapping options have not been exercised live.Transfer incoming-side ids: without an account filter, the server returns only the outgoing side of transfers. Editing a transfer through its incoming-side id is untested.
Large ranges: the analysis tools read a whole date range with one
transactions/list/all.jsonrequest. Performance on many years of data is unknown (read_cashflowcaps ranges at about 10 years).Installment notes: ezBookkeeping has no installment feature.
read_installmentsparses free-text account comments with a documented, tolerant grammar, and returns notes in other formats as raw text.Liability signs: liability balances are assumed to be negative when money is owed.
Balance adjustments: these transactions are treated as deltas when reconstructing cash-flow history.
Contributing
Issues and pull requests are welcome.
Fork the repository and run
npm install.Keep changes covered by tests.
npm run checkruns lint, typecheck, coverage (90% thresholds) and the build.Base any new endpoint on the ezBookkeeping source and cite it in
docs/API_NOTES.md.Never commit tokens or personal financial data. Test fixtures must be fictional.
License
MIT © Ege İsmail Kösedağ
This server cannot be deployed
Maintenance
Related MCP Connectors
Personal finance for AI agents: budgets, receipts, net worth, spend checks. Read-only OAuth.
Personal finance for AI agents: accounts, budgets, goals, 9-strategy debt payoff, reports. OAuth 2.1
Personal finance ledger for AI agents — query spending, track bills, forecast cash flow.
Read-only banking and personal finance for AI agents: accounts, transactions, spending, budgets.
Related MCP Servers
- AlicenseBqualityAmaintenanceEnables AI assistants to query and manage self-hosted accounting data—invoices, balances, and books—through natural language, with read-only tools by default and optional scoped write operations.3047 PyPI1AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to operate a self-hosted financial platform over MCP, managing books, expenses, revenues, settlements, payments, accounts, categories, transfers, positions, and cash flow with idempotent and audited writes.MIT
- AlicenseNot gradedqualityAmaintenanceEnables compatible AI clients to read stored personal-finance data and, with explicit user authorization, perform supported mutations under the same ownership checks as the web app.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to read, write, and audit personal finance data over a single SQLite file, covering transactions, receipts (including receipt photos as image blocks), budgets, categories, and line-item price tracking. Every write is an idempotent, soft-deleted, audited upsert so agents can safely transcribe and organize spending.9 npmMIT