All projects
AI/MCP / ● Active · v0.6.15

Actual MCP Server

Talk to your budget. Run it anywhere. Trust it in production.

Production-grade Model Context Protocol server that connects LibreChat, LobeChat, and Claude Desktop directly to your self-hosted Actual Budget. 63 tools, two transports, multi-budget switching at runtime.

1.3k
npm downloads / mo
v0.6.15
19k
Docker pulls
total · Docker Hub
17
GitHub stars
5 forks
63 tools
Most comprehensive
Across 12 categories
Synced 0m ago
01 / Audience

Who this is for

// Claude Desktop users
Want stdio transport, no Docker, no HTTP server. One npx command and you are done.
// LibreChat / LobeChat operators
Need a real HTTP server with auth and connection pooling for multiple chat users.
// Multi-budget families and businesses
Switch between Personal, Family, and Business budgets mid-conversation without restarting anything.
// Self-hosters with SSO
OIDC support means JWT-validated multi-user access with per-user budget ACLs. No shared tokens.

The problem

Most existing Actual Budget MCP servers were built as simple stdio bridges for single-user Claude Desktop sessions. They work fine on a developer laptop. They fall apart the moment you want a remote server for LibreChat or LobeChat, multi-user authentication, multiple budget files, or a real test suite covering more than the happy path.

Personal finance is an unforgiving domain. A misrouted transaction or a deleted category cascades through months of data. Operators need production tools, not toys.

What this does that the others do not

Two transports, one codebase

HTTP (--http) for remote clients like LibreChat. Stdio (--stdio) for local Claude Desktop. Same 63 tools either way. Most alternatives pick one.

Six exclusive ActualQL query tools

Search transactions by month, amount, category, or payee. Aggregated summaries instead of dumping raw rows into the AI context window. Token-efficient and unique to this server.

Runtime multi-budget switching

Configure N budget files. The AI calls actual_budgets_switch mid-conversation. Personal becomes Family becomes Business without restarting anything.

Production reliability primitives

Connection pooling (up to 15 concurrent sessions), exponential-backoff retry, full test suite (unit + E2E + integration). The plumbing nobody talks about until it breaks.

OIDC multi-user with per-budget ACLs

JWKS-validated JWTs, AUTH_BUDGET_ACL for per-user budget scoping. Casdoor-tested. The only Actual MCP with real multi-tenancy.

Architecture

Each AI client speaks MCP over its preferred transport. The server normalises both into the same internal tool dispatcher, which wraps every Actual Budget API call in a retry-and-pool layer before touching the local SQLite copy.

┌─────────────┐   MCP/HTTP    ┌──────────────────┐   Actual API   ┌──────────────┐
│  LibreChat  │ ◄────────────► │  Actual MCP      │ ◄────────────► │   Actual     │
│  LobeChat   │                │  Server          │                │   Budget     │
│  (remote)   │                │  (63 tools)      │                │   Server     │
└─────────────┘                └──────────────────┘                └──────────────┘

┌─────────────┐   MCP/stdio             │
│  Claude     │ ◄──────────────────────►│
│  Desktop    │                         │
│  (local)    │                         │
└─────────────┘                         │

                              retry + pool + ACL + SQLite mirror

Every Actual API call goes through withActualApi() in src/lib/actual-adapter.ts, which handles init / shutdown lifecycle, retry (3 attempts, exponential backoff), and concurrency limiting.

Decisions worth knowing about

63 narrow tools, not 6 generic ones

The MCP spec lets you ship one do_anything tool with a free-form prompt. I built 63 narrow tools instead, one per Actual operation, each with strict Zod-validated inputs. AI models route to the right tool more reliably; bad inputs fail at the schema, not after touching the database.

Why ship HTTP and stdio rather than just stdio

stdio is easier and most Actual MCPs stop there. But LibreChat and LobeChat are HTTP-native; forcing them through mcp-remote adds latency and an extra failure surface. Two transports doubles the test matrix but unlocks the production use case.

You cannot avoid the data volume

Actual Budget has no REST API. The official library downloads a local copy of your budget and syncs writes back. The server has to persist that copy or it re-downloads on every restart. Documented as a hard requirement in the Quick Start; misreading it is the number-one cause of failed first-time setups.

02 / Quick start

Run it in under a minute

# Pull and run with your Actual Budget credentials.
docker run -d --name actual-mcp-server-backend \
  -p 3600:3600 \
  -e ACTUAL_SERVER_URL=http://localhost:5006 \
  -e ACTUAL_PASSWORD=your_password \
  -e ACTUAL_BUDGET_SYNC_ID=your_sync_id \
  -e MCP_SSE_AUTHORIZATION=your_token \
  -v actual-mcp-data:/data \
  ghcr.io/agigante80/actual-mcp-server:latest

# Verify
curl http://localhost:3600/health
03 / Comparison

How it stacks against alternatives

Snapshot: 2026-03-20. Versions and feature flags reflect each project at that date.

Feature Actual MCP Server s-stefanov/actual-mcphenfrydls/actual-budget-mcpWGDev/ynab-mcp
Version v0.6.14v1.11.1v0.2.0v0.1.0
Tool count 63~22189
Setup and distribution
Transport HTTP + stdiostdio + SSEstdiostdio
Docker support ✓ Full (image + Compose)~ Image only
Published package ✓ npm✓ npm✓ npm✓ pip
Security and access
Authentication ✓ Bearer + OIDC~ Optional Bearer✗ None✓ Keyring
Multi-budget switching ✓ Runtime via tool✓ (YNAB native)
Production and reliability
Connection pooling ✓ Up to 15 sessions
Retry and backoff ✓ 3 attempts, exponential
Automated test suite ✓ Unit + E2E + integration
Analysis and reporting
ActualQL custom queries ✓ 6 exclusive toolsN/A
Bank sync ✓ GoCardless / SimpleFINN/A

When to choose another: s-stefanov for built-in read-only mode. henfrydls for Spanish UI and natural-language dates. ynab-mcp if you are on YNAB instead of Actual.