ledgerkit-mcp
Enables AI agents to interact with a double-entry ledger, offering tools for account management, balanced journal entries, balance queries, trial balance, and penny-perfect allocation. Built with safety by construction: no update/delete tools, idempotent posting, and an append-only journal.
README
ledgerkit-mcp
An MCP server that gives AI agents a double-entry ledger they cannot unbalance. Built on ledgerkit.
Agents are increasingly asked to touch money: record a sale, apply a refund, split a commission, reconcile a day. The failure mode is never that the model can't format a journal entry. It's that agents retry, and retries double-post; that models do decimal arithmetic in their heads, and drift; that "fix the balance" is one hallucinated tool call away from rewriting history. This server is a case study in designing tools for that caller: the invariants live below the tool surface, where no prompt can reach them.
What the agent gets
| Tool | What it does |
|---|---|
open_account |
Open an account (asset, liability, equity, income, expense) with an explicit overdraft policy |
post_entry |
Post a balanced entry: debits must equal credits, idempotency_key required |
get_balance |
Current or point-in-time balance of one account |
list_accounts |
Every account with type, policy, and balance |
list_entries |
The journal, newest first, paginated with a cursor |
trial_balance |
Every balance plus proof the books balance |
allocate |
Split an amount by ratios without losing a penny |
What the agent cannot do
There is no update, no delete, no "set balance", no unbalanced write. Corrections are reversal entries, the same as a real ledger. The agent cannot break an invariant because no tool exists that could: safety by construction beats safety by prompt.
Design rules for agent-facing tools
These are the decisions this repo exists to demonstrate.
1. Idempotency is required, not polite. Agents retry. Tool calls time out and get reissued, sessions resume, contexts compact and replay. post_entry requires an idempotency_key tied to the real-world event (order id, webhook event id), so every retry is a safe no-op that returns replayed: true. The same key with different contents is a loud conflict, never a silent overwrite. This survives server restarts, because the key index is rebuilt from the journal.
2. Errors are prompts. A rejected call returns a message written for the model that caused it: which rule was violated, with the numbers (debits 100.00 != credits 10.00), so the next attempt can be correct instead of merely different. An agent that gets "leg amounts must be positive; express direction with the side, not the sign" fixes itself. An agent that gets 400 Bad Request flails.
3. Reads respect the context window. list_entries paginates newest-first with a hard cap and a before_seq cursor. "Return the whole journal" stops being a plan around entry #500, and a tool that can flood the caller's context is a tool that degrades the caller.
4. The model should never do the arithmetic. allocate("100.00", [1,1,1]) returns ["33.34", "33.33", "33.33"], summing to exactly the original (largest-remainder method). Penny-perfect division is precisely the operation language models get plausibly wrong, so it's a tool, not a mental math exercise.
5. The journal is the only truth. Persistence is one append-only JSONL file. On boot, history replays through the same post() path as live traffic, so a tampered or damaged journal refuses to load rather than loading wrong. Balances are derived state, recomputable from the journal at any moment, which is also how point-in-time balances work.
Setup
git clone https://github.com/themusashimaru/ledgerkit-mcp
cd ledgerkit-mcp && npm install
Claude Code:
claude mcp add ledger \
--env LEDGER_FILE=$HOME/.ledgerkit/journal.jsonl \
-- npx tsx /ABSOLUTE/PATH/TO/ledgerkit-mcp/src/server.ts
Any MCP host, same shape:
{
"mcpServers": {
"ledger": {
"command": "npx",
"args": ["tsx", "/ABSOLUTE/PATH/TO/ledgerkit-mcp/src/server.ts"],
"env": { "LEDGER_FILE": "/Users/you/.ledgerkit/journal.jsonl" }
}
}
}
Configuration is two environment variables: LEDGER_CURRENCY (USD default, EUR, JPY, or CODE:decimals) and LEDGER_FILE (path to the journal; unset means in-memory, which is fine for a demo and wrong for anything real).
Then ask your agent to keep books:
"Open cash, revenue, and sales_tax_payable accounts. Record today's sale #1001: $108.75 collected, $100 revenue, $8.75 tax. Then show me the trial balance."
Tests
npm test # 17 tests over the real MCP protocol (in-memory transport)
npm run smoke # spawns the real stdio server, posts, restarts it, retries
The suite calls tools through an actual MCP client, not the handlers directly, because schema validation is half the contract. The smoke test kills the server mid-flow and proves a retried post_entry after reboot is a replay, not a double post.
Relationship to ledgerkit
The engine (src/engine/) is vendored from ledgerkit, a zero-dependency double-entry ledger: balanced-by-construction entries, bigint minor-unit money, append-only journal, idempotent posting. This repo is the agent-facing skin around it. The layering is the point: the engine enforces what must be true, the MCP layer decides what a language model should be allowed to ask for and how it should fail.
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。