actual-mcp
Provides tools for interacting with an Actual Budget instance, enabling management of accounts, transactions, categories, budget months, schedules, payees, and category groups.
Click on "Install 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., "@actual-mcpList my accounts and their balances."
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.
actual-mcp
An MCP server for Actual Budget — with a per-tool safety layer.
Actual has no HTTP or MCP surface of its own; it ships a Node SDK. This wraps that SDK as an MCP server so any agent — Claude Desktop, Cursor, your own — can read and edit your budget in natural language.
The difference from a plain wrapper: every tool carries its own risk. A read is a read. A mutation says so. And a delete can never fire on the agent's say-so — it returns a confirmation token and refuses until you call it again with confirm: true. The model can plan freely; it cannot quietly wipe a category because a prompt drifted.
Giving an agent write access to your finances is a liability unless the tools themselves carry the seatbelt. The safest place to enforce a rule is the tool, not the prompt.
Requirements
Node.js 20+
A running, self-hosted Actual sync server (the
actual-serveryou sync your budget to — not the desktop app). You need its URL, its password (if set), and the Sync ID of the budget you want to expose.
Related MCP server: YNAB MCP Server
Quick start
1. Find your Sync ID
In Actual: Settings → Show advanced settings → Sync ID. It's a UUID like a1b2c3d4-....
2. Add the server to your MCP client
Edit claude_desktop_config.json (Claude → Settings → Developer → Edit Config):
{
"mcpServers": {
"actual": {
"command": "npx",
"args": ["-y", "actual-mcp"],
"env": {
"ACTUAL_SERVER_URL": "https://actual.example.com",
"ACTUAL_PASSWORD": "your-server-password",
"ACTUAL_SYNC_ID": "your-sync-id"
}
}
}
}Restart Claude Desktop. You'll see the tools appear under the 🔌 icon.
Any stdio MCP client works — point it at npx -y actual-mcp with the same four env vars. In Cursor: Settings → MCP → Add new and use the same command/args/env shape.
3. Ask it things
What did I spend on groceries last month?
List my accounts and their balances.
Move R$200 from Dining to Savings for July.
Add a R$54.90 transaction to Nubank, payee "Uber", category Transport, dated today.Configuration
Env var | Required | What |
| ✅ | Your Actual sync server URL. |
| ✅ | Sync ID of the budget to open. |
| — | Server password. Omit if the server has none. |
| — | Where the SDK caches the budget. Defaults to |
Amounts are integer minor units, matching the Actual SDK — R$200.00 is
20000, and outflows are negative (-5490= R$54.90 spent).
The safety model
Level | Tools | Behaviour |
🟢 read-only | all | Never touch data. |
🟡 mutating | all | Change data; run immediately. |
🔴 guarded | all | Change data; refuse until |
Every tool's level is exposed three ways so the seatbelt is visible before a call: in the tool description, in MCP readOnlyHint / destructiveHint annotations, and — for guarded tools — as a hard refusal at call time.
What a guarded call looks like. The agent tries to delete, and gets back a refusal with the exact arguments and a confirmation token:
// → delete_category { "id": "cat-abc-123" }
// ← (isError)
⚠️ "delete_category" is a destructive action and needs confirmation.
It will run with:
{ "id": "cat-abc-123" }
To proceed, call "delete_category" again with "confirm": true.
Confirmation token: 75aa4f772b62Only an explicit re-invocation clears it:
// → delete_category { "id": "cat-abc-123", "confirm": true }
// ← { "ok": true }The human reading the transcript sees precisely what "yes" authorized.
Tools (28)
Tool | Level | Args |
| 🟢 | — |
| 🟡 |
|
| 🟡 |
|
| 🔴 |
|
| 🟢 | — |
| 🟡 |
|
| 🟡 |
|
| 🔴 |
|
| 🟢 |
|
| 🟡 |
|
| 🟡 |
|
| 🔴 |
|
| 🟢 | — |
| 🟢 |
|
| 🟡 |
|
| 🟡 |
|
| 🟢 | — |
| 🟢 |
|
| 🟡 |
|
| 🟡 |
|
| 🟢 | — |
| 🟡 |
|
| 🟡 |
|
| 🔴 |
|
| 🟢 | — |
| 🟡 |
|
| 🟡 |
|
| 🔴 |
|
Troubleshooting
"actual-mcp is not configured" —
ACTUAL_SERVER_URLorACTUAL_SYNC_IDis missing from the client'senvblock.Can't connect / auth fails — check the URL is the sync server (not the desktop app) and the password matches. Test it by logging into that URL in a browser.
Wrong or empty data — the Sync ID points at a different budget file. Re-copy it from Settings → Show advanced settings → Sync ID.
Tools don't appear in Claude Desktop — fully quit and reopen; check the config file is valid JSON.
Verify your setup
Before wiring it into an agent, confirm the server can reach your Actual instance. This prints only counts — never names or amounts:
ACTUAL_SERVER_URL=https://actual.example.com \
ACTUAL_SYNC_ID=your-sync-id \
ACTUAL_PASSWORD=your-password \
npm run smoke✓ connected to Actual
accounts: 1
categories: 63
category groups: 17
budget months: 21
✓ clean shutdownDevelop
npm install
npm run build
npm run inspect # @modelcontextprotocol/inspector against the built server
npm run smoke # connection check (counts only)License
MIT © Mauricio Juba · TYPE:ZERO
Not affiliated with Actual Budget. Built on the official @actual-app/api.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Type-zero-labs/actual-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server