lastro
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., "@lastroRecord the rent expense for March and schedule its payment for April 1."
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.
Lastro
Self-hosted, MCP-first financial platform for personal, family, property,
project and business finances. Each independent financial scope is a Book.
Lastro is built to be operated by an AI agent over MCP as its primary interface, with a compact web app for review and direct edits. PostgreSQL is the source of truth.
The one idea worth knowing
Lastro separates economic facts from cash movements:
Expense ≠ Payment
Revenue ≠ ReceiptAn expense is split into settlements — its installments. A payment groups one or more settlements, may cover installments from several different expenses, and has its own due date. A payment's amount is derived from the active settlements it groups; it is never entered directly. The same holds for revenues and receipts.
That distinction is why a general "transactions" table appears nowhere in the schema.
Related MCP server: Agent Ledger
Quick start
Requires Bun 1.4+ and Docker.
cp .env.example .env
# set BETTER_AUTH_SECRET — openssl rand -base64 32
docker compose -f docker-compose.release.yml up -d --build
bun install
bun run bootstrap --email you@example.com --password 'a-long-passphrase'That prints an MCP credential once. Then:
Web app — http://localhost:3000
API — http://localhost:3001
MCP (Streamable HTTP) — http://localhost:3002/mcp
macOS on Apple Silicon can use Apple Container instead of Docker; see docs/install.md.
Connecting an agent
Lastro speaks MCP over Streamable HTTP and stdio. With the credential printed
by bun run bootstrap:
{
"mcpServers": {
"lastro": {
"url": "http://127.0.0.1:3002/mcp",
"headers": { "Authorization": "Bearer <credentialId>.<secret>" }
}
}
}A credential is bound to one Book. Calls name the Book they act on, and a credential issued for a different one is rejected rather than returning an empty result — so an agent cannot reach another agent's ledger even by asking for it. Give each agent its own Book and credential and they stay separated by construction:
bun run bootstrap --email you@example.com --password '...' --book Butler --agent agent:butler
bun run bootstrap --email you@example.com --password '...' --book Bartender --agent agent:bartenderSend x-book-id as well to assert which Book you expect: a token for a
different one is then rejected instead of writing to the wrong ledger.
The agent gets the whole product: catalog CRUD (institutions, accounts,
parties, categories), the expense and revenue cycles, transfers, positions and
cash flow. Every write takes a mandatory idempotency key, every destructive
tool requires an explicit confirmation: "confirm", and every mutation appends
an audit event naming the agent principal and the operator it acts for.
Architecture
apps/web Next.js operator interface (Tailwind CSS v4 + shadcn/ui)
apps/api authenticated HTTP/JSON API, hosts Better Auth
apps/mcp MCP adapter — stdio and Streamable HTTP
packages/domain entities and invariants, no framework
packages/application commands, queries, authorization, ports
packages/db PostgreSQL schema, migrations, port implementations
packages/contracts Zod schemas shared by API, MCP and the web app
packages/auth agent credentials, RBAC, Book membership
packages/config validated environment configuration
packages/testing PostgreSQL-backed integration suiteAPI, MCP and the web app call the same application handlers. Domain rules never
live in routes, tools or components. Only packages/db knows SQL.
Details in docs/architecture.md.
Invariants
Money is a
bigintamount plus an explicit currency; JSON carries amounts as validated decimal strings. No floats, anywhere.Every command and query is scoped to an authenticated
bookId.A settlement may only connect records from the same Book and currency.
Active settlements may never exceed their expense's total.
Status is derived from active settlements, never set directly.
Confirmed settlements are voided and replaced, never edited in place.
Every mutation is idempotent and appends an
AuditEvent.
Development
docker compose up -d # PostgreSQL 16 on :5432
bun install
bun run db:init # apply the schema
bun run check # typecheck, lint, unit tests, builds
bun run test:integration # real PostgreSQL, api + mcp, end to endChanging the schema: edit packages/db/src/schema.ts, then run
bun run db:generate to emit a migration.
Contributing
See CONTRIBUTING.md. Security reports go to SECURITY.md.
License
MIT — see LICENSE. UI primitives are copied from shadcn/ui, also MIT; see THIRD_PARTY_NOTICES.md.
This server cannot be deployed
Related MCP Connectors
Personal finance for AI agents — onboard, import statements, categorize & budget over MCP.
Headless API-first double-entry accounting & bookkeeping engine. 84 MCP tools over HTTP.
Personal finance ledger for AI agents — query spending, track bills, forecast cash flow.
Hosted MCP server for AI agent identity, permissions, verification, and reusable proof.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceA Model Context Protocol (MCP) server that keeps the books for your personal and business finances using double-entry accounting — driven entirely from an LLM.28MIT
- AlicenseNot gradedqualityAmaintenanceDouble-entry accounting ledger MCP server for autonomous agents that enables creating accounts, posting journal entries, and generating financial reports.MIT
- FlicenseNot gradedqualityBmaintenanceAn MCP server that enables AI agents to safely interact with a double-entry payments ledger, enforcing idempotency, policy-based access control, and human-in-the-loop approval for high-value actions.-
- AlicenseNot gradedqualityAmaintenanceMCP server for double-entry bookkeeping with idempotent writes, immutable entries, and audit trail. Enables trustworthy financial recording and verification through natural language.22MIT