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
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.