firefly-iii-mcp-server
firefly-iii-mcp-server
An MCP (Model Context Protocol) server that exposes a curated, task-shaped surface of 41 tools over the Firefly III personal-finance API. Designed for an AI agent doing personal accounting on behalf of a human: record, review, budget, save, summarise.
Rather than mirroring Firefly's ~230 REST operations 1:1, this server is a facade with a thin anti-corruption layer that:
strips the JSON:API envelope (
data: { type, id, attributes: {...} }) on every response,flattens Firefly's currency-keyed maps into
{ currency_code, ... }arrays,collapses per-account/per-bill/per-budget/per-category transaction list variants into a single
list_transactionswith filters,normalises errors into one envelope with stable codes,
keeps amounts, IDs, and dates as strings (no float drift, no silent coercion).
The 41-tool catalogue and the capability groups deliberately not exposed in v1 are documented below.
Install
Requires Bun ≥ 1.3.
bun installNo build step — Bun runs TypeScript directly from src/index.ts.
Configuration
Two environment variables, both required. The server fails fast at startup if either is missing.
Variable | Description |
| Base URL of your Firefly III instance, no trailing slash. Example: |
| Personal Access Token. Get one in Firefly III: Options → Profile → OAuth → Personal Access Tokens → Create New Token. |
A .env.example is provided. Copy it to .env for local development (never commit .env).
Run
# stdio transport (the only supported transport in v1)
FIREFLY_III_URL=https://demo.firefly-iii.org \
FIREFLY_III_TOKEN=your-pat-here \
bun startOn success the server logs firefly-iii-mcp-server: ready on stdio to stderr (stdout is reserved for the MCP protocol).
MCP client configuration
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"firefly-iii": {
"command": "bun",
"args": ["run", "/absolute/path/to/firefly-iii-mcp/src/index.ts"],
"env": {
"FIREFLY_III_URL": "https://demo.firefly-iii.org",
"FIREFLY_III_TOKEN": "your-pat-here"
}
}
}
}opencode
Add to ~/.config/opencode/opencode.json (or your project-local opencode.json):
{
"mcp": {
"firefly-iii": {
"type": "local",
"command": ["bun", "run", "/absolute/path/to/firefly-iii-mcp/src/index.ts"],
"environment": {
"FIREFLY_III_URL": "https://demo.firefly-iii.org",
"FIREFLY_III_TOKEN": "your-pat-here"
},
"enabled": true
}
}
}Tools
All 41 tools are listed below. Their schemas are exposed to MCP clients through the server's tool catalogue.
Transactions (6)
list_transactions— browse recent transactions, filter by date / type / accountget_transaction— fetch one transaction with all its splitssearch_transactions— free-text and operator search (amount_min:,category:,tag:, …)create_transaction— record a withdrawal, deposit, or transfer (single or multi-split)update_transaction— edit fields on an existing transactiondelete_transaction— delete a transaction by ID
create_transaction and update_transaction may return an overridden_fields envelope alongside the projected transaction. It lists fields the agent sent that Firefly's rule engine then overwrote (e.g. you sent category: "Food" and a rule rewrote it to "Groceries"). The envelope is absent when no diff is detected. v1.1 limitation: only the first split is diffed.
Accounts (5)
list_accounts— list accounts, filter by type oractiveget_account— single account with current balance (historic balance viadate)create_account— create asset / expense / revenue / liability / cash accountupdate_account— update account metadatadelete_account— delete an account by ID
Categories (3)
list_categories— list categoriesupsert_category— create or update a categorydelete_category— delete a category
Tags (3)
list_tags— list tagsupsert_tag— create or update a tagdelete_tag— delete a tag by ID
Budgets (3)
list_budgets— list budgets enriched with limit / spent / remaining for a periodupsert_budget— create or update a budget; optionally set its limit in the same calldelete_budget— delete a budget by ID (Firefly clears its budget-limit rows; transactions are not deleted)
Bills (3)
list_bills— recurring expected expenses withnext_expected_matchandpaid_datesupsert_bill— create or update a bill (subscription, etc.)delete_bill— delete a bill by ID (matched transactions are detached, not deleted)
Piggy banks (5)
The piggy-bank cluster uses an explicit create_* + update_* rather than a single upsert_* because Firefly's create-side schema requires four fields (name, accounts, target_amount, start_date) while the update-side schema requires none — the same asymmetric-required-fields pattern as rules CRUD.
list_piggy_banks— savings goals with progress (current_amount,target_amount,percentage)create_piggy_bank— define a new savings goalupdate_piggy_bank— rename, retarget, or re-attach accounts; partial update. Does NOT acceptcurrent_amount— balance changes go throughcontribute_piggy_bank, which is the single auditable path for moving money into or out of a piggy bank.delete_piggy_bank— delete a savings goal by ID (linked accounts and transactions are untouched)contribute_piggy_bank— add to (positive) or withdraw from (negative) a piggy bank
Rules (5)
list_rules— list rules; passrule_group_idto scope to one group, else lists all rulesget_rule— fetch one rule with its triggers and actionscreate_rule— create a rule in a group; triggers and actions are flat arrays (order derived from array index)update_rule— update a rule; passingtriggers: []oractions: []clears the listdelete_rule— delete a rule by ID
Rule groups (5)
list_rule_groups— list rule groupsget_rule_group— fetch one rule groupcreate_rule_group— create a rule groupupdate_rule_group— update a rule group's metadatadelete_rule_group— delete a rule group (cascades: all rules in the group are deleted)
Summary & insights (2)
get_financial_summary— net worth, income, expense, balance for a period; flattened across currenciesget_spending_insights— breakdown bycategory/budget/tag×expense/income
System (1)
get_system_info— Firefly version, primary currency, authenticated user
Shared conventions
Pagination on every
list_*/search_*tool:{ items, page, total_pages, total_items, has_more }.pageis 1-indexed.limitdefaults to 25 and is capped at 100 (over-limit requests are clamped, not rejected; the response includeslimit_clamped_to: 100).Amounts, IDs, dates are strings. Amounts are decimal strings (
"-1012.12"). IDs are numeric strings ("42"). Dates areYYYY-MM-DD.Currency by code, not ID.
currency_code: "EUR", nevercurrency_id: 1.Errors are returned as a uniform envelope (see below); the tool result is marked
isError: trueso clients can detect failure.
Error envelope
{
"ok": false,
"error": {
"code": "validation_error",
"message": "The amount is required.",
"field_errors": { "transactions.0.amount": ["The amount is required."] },
"http_status": 422,
"trace_id": "f54f1c80-7d9b-4a3e-9b71-1c0c7b3d3a1b"
}
}code is one of: validation_error, not_found, unauthenticated, forbidden, rate_limited, upstream_error, network_error, internal_error. HTML error pages from upstream are never leaked — they are converted into a safe synthetic upstream_error.
Example tool calls
List recent withdrawals in March 2026
Input to list_transactions:
{ "start": "2026-03-01", "end": "2026-03-31", "type": "withdrawal", "limit": 3 }Output (structuredContent):
{
"items": [
{
"id": "1042",
"type": "withdrawal",
"date": "2026-03-15",
"amount": "42.50",
"currency_code": "EUR",
"description": "Groceries",
"category": "Food",
"source_name": "Checking",
"destination_name": "Supermarket"
}
],
"page": 1,
"total_pages": 4,
"total_items": 12,
"has_more": true
}Record a withdrawal
Input to create_transaction:
{
"type": "withdrawal",
"date": "2026-03-20",
"amount": "12.99",
"description": "Coffee",
"source": "Checking",
"destination": "Daily Cafe",
"category": "Food",
"tags": ["weekly"]
}source / destination accept either a numeric account ID ("7") or a free-form name; the server routes to Firefly's *_id vs *_name automatically.
Set a monthly budget for groceries with a limit
Input to upsert_budget:
{
"name": "Groceries",
"active": true,
"limit": {
"start": "2026-03-01",
"end": "2026-03-31",
"amount": "400.00",
"currency_code": "EUR"
}
}Output (structuredContent):
{
"id": "5",
"name": "Groceries",
"active": true,
"limit": {
"start": "2026-03-01",
"end": "2026-03-31",
"amount": "400.00",
"currency_code": "EUR"
}
}Not exposed in v1
The following capability groups are deliberately omitted from v1 to keep the tool catalogue small and the agent's planning surface tractable: user / group admin, server configuration, currency admin, destructive admin (destroyData/purgeData), chart endpoints, autocomplete (*AC), webhooks, attachments (binary I/O over MCP is a separate design problem), per-currency / per-parent transaction list duplicates, exports, bulk update, currency exchange rates, recurrences, transaction links, object groups, available budgets, preferences, per-resource event/attachment sub-lists, and narrow insight slices.
Development
bun install # install dependencies
bun run typecheck # tsc --noEmit (TypeScript kept as a dev dep purely for typechecking)
bun test # bun's built-in test runner (shape helpers, error mapping, tool catalogue, decimal, integration)
bun run dev # bun --watch run src/index.tsThe catalogue test (tests/tool-catalogue.test.ts) asserts that exactly the 41 tools named in EXPECTED_TOOL_NAMES in src/tools.ts are registered. Update the catalogue, its expected names, and this README together when adding or removing a tool.
License
MIT