finance-mcp-server
# finance-mcp-server
Your personal finance tracker as an MCP server. Sync your bank via SimpleFIN —
or backfill from a CSV — into a local SQLite database and ask Claude about it:
spending, subscriptions, cash flow, merchant history, debt payoff. Everything
stays on your machine; the only thing that leaves is the answer to a question
you asked.

*The bundled HUD (`npm run hud`) rendering a synthetic demo dataset — net worth,
per-account balances, category spending, subscription price-hike flags, and a
30-day cash-flow projection with the low point marked.*
The analytics engine in `src/core/` is pure, dependency-free TypeScript,
kept separate from the MCP and storage layers so a future app can share
the same core.
## Setup
```bash
npm install
npm run build
```
## Get your data in
### Live bank sync (SimpleFIN) — recommended
The primary data source. Live account balances and ongoing transaction sync via
SimpleFIN Bridge (read-only bank aggregation, ~$15/yr) — no CSV and no specific
budgeting app required. Get a one-time **setup token** from
[bridge.simplefin.org](https://bridge.simplefin.org) (My Account), then:
```bash
npm run link -- "<paste-setup-token>"
```
This claims the token into a durable access URL stored **locally** in
`data/finance.db` (it never leaves your machine) and runs an initial 365-day
sync. After that, balances are live — `finance_sync` (or just ask Claude to
sync) pulls new transactions. You can also link from within Claude via the
`finance_link_bank` tool, but the CLI keeps the token out of the chat
transcript. The database lives at `data/finance.db` (override with the
`FINANCE_DB_PATH` env var).
### Optional: Rocket Money CSV backfill
Purely optional — SimpleFIN alone runs the whole tracker. If you're coming from
Rocket Money, you can backfill history from *before* your bank's sync window.
Export from Rocket Money (Settings → Export Data → CSV), then:
```bash
npm run import -- "C:/path/to/rocket-money-export.csv"
```
Re-running with an updated export is safe — rows dedupe by a stable hash, so
only genuinely new transactions are added.
## Local HUD (dashboard)
A glanceable dashboard that reads `finance.db` fresh on every load — net
worth + account balances, this month's spending by category, subscriptions
with price-hike flags, and a 30-day cash-flow sparkline with the low point
marked. Fully offline (no CDN, no external calls); localhost only.
```bash
npm run hud # → http://localhost:4321 (Ctrl+C to stop)
```
Leave it running and bookmark it; it self-refreshes every 2 minutes and
re-reads the DB, so once your bank is linked the balances stay current.
Override the port with `HUD_PORT`.
## Use it with Claude
**Claude Desktop, one-click (`.mcpb`)** — the easiest path. Grab
`finance-mcp.mcpb` from the [latest release](../../releases/latest) (or build it
yourself, below), then drag it onto **Settings → Extensions** in Claude Desktop.
It'll ask for a **Database file path** — leave the default for a fresh store, or
point it at an existing `finance.db` to reuse that data. The bundle is
self-contained (bundled Node deps incl. the native SQLite binary) and, being
compiled, is **win32-x64 only** for now; on other platforms use the manual
config below after `npm install && npm run build`.
**Build the `.mcpb` yourself:**
```bash
npm install && npm run build
npm i -g @anthropic-ai/mcpb # the official packer
npm prune --omit=dev # ship prod deps only (do this in a copy, or re-`npm install` after)
mcpb pack . finance-mcp.mcpb
```
`manifest.json` at the repo root defines the bundle. It ships **no data** — the
SQLite file (and the SimpleFIN credential inside it) always lives at the external
path you configure, never in the bundle.
**Claude Desktop, manual** — add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"finance": {
"command": "node",
"args": ["/absolute/path/to/finance-mcp-server/dist/index.js"],
"env": { "FINANCE_DB_PATH": "/absolute/path/to/finance-mcp-server/data/finance.db" }
}
}
}
```
**Claude Code** — `claude mcp add finance -- node /absolute/path/to/finance-mcp-server/dist/index.js`
Then ask things like:
- "What did I spend on gas last quarter?"
- "List my subscriptions and flag any price hikes."
- "How much have I paid Amazon over the last year?"
- "Forecast my cash flow for the next 30 days starting from $1,200."
- "Given these balances and APRs, avalanche vs snowball — which saves more?"
## Tools
| Tool | What it does |
|---|---|
| `finance_import_csv` | Import a Rocket Money CSV (idempotent) |
| `finance_data_overview` | Count, date span, per-category totals |
| `finance_search_transactions` | Filter by date/category/merchant/amount/flow |
| `finance_spending_by_category` | Inflow/outflow by category over a range |
| `finance_list_subscriptions` | Recurring charges + price-hike flags |
| `finance_cash_flow_forecast` | N-day projection with low-point warning |
| `finance_merchant_history` | Every charge from a merchant + summary |
| `finance_debt_payoff_plan` | Avalanche/snowball simulation |
| `finance_link_bank` | Connect a bank via a SimpleFIN setup token |
| `finance_balances` | Live per-account balances + net worth |
| `finance_sync` | Pull new transactions + refresh balances |
| `finance_disconnect_bank` | Forget the SimpleFIN connection |
| `finance_add_category_rule` | Map a merchant substring → category (recategorizes matches) |
| `finance_list_category_rules` | List rules + re-apply them across the store |
| `finance_remove_category_rule` | Delete a rule |
## Fixing miscategorized transactions
CSV history carries Rocket Money's own categories, but transactions synced
live from SimpleFIN only have raw bank descriptors, so many land in
**other**. Fix them with rules — just tell Claude, e.g. *"categorize
anything from Menards as shopping."* Each rule matches a case-insensitive
substring against the merchant name / descriptor, recategorizes all matches
immediately (past and future), and sticks for every later import/sync.
## Privacy
`data/` and all `*.csv` files are gitignored. Real transaction history is never
committed and never sent anywhere except when you ask Claude a question that
requires reading it. The screenshot above is generated from synthetic data.
## License
MIT
TDQS
Scored across 15 tools
Each tool targets a distinct operation in the personal finance domain: import, search, analysis (categories, subscriptions, cash flow, merchant history), debt planning, bank connectivity, and rule management. No two tools have overlapping purposes; an agent can easily differentiate them.
All tool names follow the consistent snake_case pattern 'finance_verb_noun' (e.g., finance_import_csv, finance_search_transactions, finance_link_bank). This uniformity makes the tool set predictable and easy to navigate.
With 15 tools, the server is well-scoped for a personal finance assistant. It covers data import, querying, analysis, planning, and bank integration without being overwhelming. Each tool serves a clear purpose.
The tool set covers core workflows: importing, searching, categorizing (via rules), analyzing spending, detecting subscriptions, forecasting cash flow, planning debt payoff, and syncing bank transactions. Minor gaps exist, such as the lack of direct transaction editing or deletion, but these can be worked around.