ezbookkeeping-mcp
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
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ğ
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
Related MCP Connectors
Read-only personal finance for AI agents: budgets, receipts, net worth, bills. OAuth 2.1.
Read-only finance MCP server. Connects your banks, cards, payment apps, books and payroll into one ledger for your AI. Can't move money. Open source (AGPL-3.0), free during beta.
Multi-currency budgeting: read and update your accounts, transactions, categories and budgets.
Personal finance for AI agents: accounts, budgets, goals, 9-strategy debt payoff, reports. OAuth 2.1
Related MCP Servers
- AlicenseBqualityBmaintenanceEnables 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.3024 PyPI1AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables 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 gradedqualityBmaintenanceEnables 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.27 npmMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants and other MCP clients to read and manage personal finance data, including transactions, categories, tags, budgets, recurring items, manual and Plaid accounts, crypto holdings, and balance history, with full CRUD operations and token-efficient responses.41 npmMIT