LedgersHoard
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., "@LedgersHoardAdd a grocery expense of 45.30 to the food 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.
Ledger's Hoard
Local-first household ledger: accounts, categorised entries, monthly budgets, reports and bank CSV imports, stored in a single SQLite file on your own computer and exposed to an assistant through MCP.
Spanish version: README.es.md.
Run
Requires Node.js 22.13 or later (it uses the built-in node:sqlite). No native modules, no Docker.
npm install
npm run build
npm start # http://127.0.0.1:5180npm run open starts the server and opens the browser on Windows. npm run dev runs the API (node --watch) and Vite together with the /api proxy configured automatically.
The server binds to 127.0.0.1 only. If port 5180 is busy it walks up to the next free port and prints the address; set PORT_STRICT=1 to fail instead.
Environment variables
Variable | Purpose |
| Preferred port (default |
| Do not fall back to another port. |
| Data folder (default |
| Extra host names accepted behind a tunnel (see below). |
| MCP bridge: base URL of the running app (default |
| MCP bridge: where to read the bearer token (default |
Access from your phone (behind a tunnel)
The server binds 127.0.0.1 and only answers requests whose Host is localhost, 127.0.0.1 or [::1]. To reach it from your phone through a tunnel that fronts the app (a private mesh network, a reverse proxy), list the extra host names in LEDGER_ALLOWED_HOSTS, comma-separated, exact names or *.suffix: LEDGER_ALLOWED_HOSTS=my-pc.example,*.ts.net. Port and letter case are ignored, and the Origin of API calls must resolve to one of those hosts too (any scheme or port). Cross-site fetches are still refused; opening the app from another page (a link, a bookmarklet, the share sheet) is a normal navigation and works.
Once opened through the tunnel, the browser offers to install it (PWA).
Related MCP server: SMB
What it does
Resumen — month picker, income / expense / net / total balance tiles, budget bars per category (over budget in the danger colour, with a written "Superado" chip), recent entries and account balances.
Movimientos — filterable table (date range, account, category, free text) with a quick-add row at the top (Enter saves, Escape cancels), inline edit, delete with confirmation, and a transfer form to move money between accounts.
Cuentas — cash, bank, card, savings or other; currency per account; opening balance; archive instead of delete when there are entries.
Categorías — expense and income categories with optional parent, colour and a monthly budget editable in place. A Spanish default set (Comida, Casa, Transporte, Ocio, Salud, Suscripciones, Ropa, Regalos, Otros gastos; Nómina, Otros ingresos) is seeded the first time the table is empty.
Importar — paste or choose a bank CSV. Delimiter (
;,,, tab), header row, dates (DD/MM/YYYY,YYYY-MM-DD,DD-MM-YYYY), Spanish decimal comma and separate debit/credit columns are detected; the mapping can be corrected with selects; the preview shows the first 20 rows and how many are duplicates; commit reports added / skipped.Informes — 12-month income vs expense bars and expense-by-category donut, both inline SVG with a table view.
Ajustes — currency symbol; data folder and version shown read-only.
All money is stored as integer cents. User input like 12,50, 12.5, -3, 1.234,56 or 1,234.56 is parsed by shared/money.js (parseAmount), which the UI, the API and the tools all use.
Transfers are two entries linked by transfer_id; they change balances but are excluded from income/expense totals and budgets.
API
All routes are JSON, validated with zod, and answer errors as { "error": "…" } with a proper status code.
Route | Purpose |
|
|
| UI bootstrap: accounts with balances, categories, settings, data dir. |
| Accounts CRUD (delete only when unused). |
| Categories CRUD. |
| Entries; |
|
|
| Income, expense, net, per-category spent vs budget, per-account balance. |
| Budget status with a one-line verdict. |
| Per-month income / expense / net (defaults to the last 12 months). |
|
|
| Same body plus |
| Import history. |
|
|
| Tool catalogue (name, description, JSON schema, annotations) and the assistant instructions. |
|
|
Connect an assistant (MCP)
server/mcp.js is a stdio MCP server that proxies every call to the running app, so only one process ever opens the database. Keep the app running while the assistant works.
{
"command": "node",
"args": ["C:/path/to/ledgers-hoard/server/mcp.js"],
"env": { "LEDGER_URL": "http://127.0.0.1:5180", "LEDGER_TOKEN_FILE": "C:/path/to/ledgers-hoard/data/mcp-token" }
}faustus-plugin.json describes the app for Faustus (health check, launch hint and the MCP command with placeholders).
Tools (17):
Tool | Purpose |
| Accounts with current balance. |
| Create an account or update the one with the same name (case/accent-insensitive): type, currency (default EUR), opening balance as text, archived. |
| Categories with budgets, optionally by kind. |
| Record a movement: amount as text, kind |
| Filter by dates, account, category, text, tag; limit ≤ 200. |
| Free text over counterparty, note, tags and category. |
| Monthly totals, per category with budget, per account. |
| Budget vs spent per category with |
| Per-month income / expense / net between two months. |
| Balance of one account (or all) at a date. |
| Edit an entry's fields. |
| Delete an entry (destructive; removes both halves of a transfer). |
| Create or update a category by name. |
| Set or clear a monthly budget. |
| Analyse CSV text: columns, guessed mapping, sample rows, duplicates. |
| Import into an account with dedupe by hash (safe to repeat). |
| Move money between two accounts. |
Every description ends with a Sinónimos: line of Spanish words. Ambiguous account or category names return candidates so the assistant can ask instead of guessing.
Data and limits
data/ledgers-hoard.db— SQLite in WAL mode, schema migrations inserver/db.js(schema_versiontable).data/mcp-token— 32 random bytes written at every start; never committed.Requests are accepted only from
localhost/127.0.0.1origins; cross-site requests are rejected.CSV bodies up to 10 MB;
list_entriesreturns at most 200 rows per call for tools and 500 for the UI.No network calls are made by the server.
Verification
npm test # node --test tests/*.test.js — parser, CSV, reports, HTTP API, agent auth and tools
npm run build # vite build → dist/Tests use temporary data directories and never touch data/.
Layout
server/ app.js (Express), index.js (boot), db.js, accounts.js, categories.js, entries.js,
reports.js, csv.js, imports.js, dates.js, money.js, routes.js, agent-tools.js,
agent-routes.js, mcp.js, port.js
shared/ money.js (parseAmount / formatCents, used by server and client)
client/ React 19 + Vite + Tailwind v4 (pages: Resumen, Movimientos, Cuentas, Categorías, Importar, Informes, Ajustes)
scripts/ launch.mjs, dev.mjs
tests/ node:test suitesLicense: MIT (see LICENSE).
This server cannot be deployed
Maintenance
Related MCP Connectors
Personal finance for AI agents — onboard, import statements, categorize & budget over MCP.
- ManiloOAuthapp.manilo
Log, query, and edit expenses, budgets, and accounts in Manilo from any MCP-compatible AI assistant.
Log, query, and edit expenses, budgets, and accounts in Ledgy from any MCP-compatible AI assistant.
- ManiloOAuthapp.ledgy.api
Log, query, and edit expenses, budgets, and accounts in Manilo (formerly Ledgy) from any MCP-compatible AI assistant.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables local analysis of personal finance data from a Monter JSON export, answering questions about spending, subscriptions, debts, and more via MCP-capable assistants without any cloud servers.-
- FlicenseNot gradedqualityBmaintenanceEnables personal finance management through natural language, including tracking income/expenses, categories, loans, subscriptions, budgets, and AI-powered insights, all backed by a local SQLite database.1-
- AlicenseAqualityCmaintenanceEnables local-first expense logging, editing, and analysis through natural language conversation, backed by a SQLite database and accessible via MCP over stdio.8MIT
- AlicenseNot gradedqualityBmaintenanceEnables importing AI provider usage CSVs or syncing OpenRouter/OpenAI costs into a local SQLite ledger, then querying spend, budgets, and invoice-style summaries via MCP tools.12 npmMIT