ledgerkit-mcp

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.

Category
Visit Server

README

ledgerkit-mcp

CI

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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured