MoneyFlow MCP Server
This is a read-only MCP server for querying a MoneyFlow personal finance Postgres ledger.
Query signed kept spending per currency for a category over an inclusive date range.
Get category/subcategory/currency totals over a date range or a budget month, not both.
Find transactions with their ledger entry by date range, optional description/comment text, account, and limit.
Get a budget-cycle month summary: dates, days total/left, income, actual totals per currency, and cash in hand.
Use it over stdio from Claude Code against the local database; it does not write data.
Provides read-only tools for querying a personal finance ledger stored in a PostgreSQL database, enabling retrieval of category totals, transaction lookups, monthly budget summaries, and per-category spending over date ranges or budget months.
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., "@MoneyFlow MCP Server show my spending by category last month"
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.
MoneyFlow
Personal finance ledger. It has a pure core, Postgres storage and read-only MCP tools.
moneyflow.core: pure ledger build (ingest, categorize, arithmetic). It does no I/O.moneyflow.storage: Postgres via SQLAlchemy, with Alembic migrations.moneyflow.services: rebuilds the stored ledger and runs queries.moneyflow.api: an MCP server over stdio that exposes read-only tools.
Status: early (0.x). The API and the schema can change between minor versions.
Requirements
Python 3.12+
Postgres 16. Docker works.
Related MCP server: postgres-mcp-server
Quick start
git clone https://github.com/FreddieMcHeart/moneyflow.git
cd moneyflow
uv sync
docker run -d --name mf-pg -e POSTGRES_PASSWORD=mf -p 5433:5432 postgres:16
docker exec mf-pg createdb -U postgres moneyflow_dev
export MONEYFLOW_DATABASE_URL=postgresql://postgres:mf@localhost:5433/moneyflow_dev
uv run alembic upgrade head
uv run python -m moneyflow rebuild --db "$MONEYFLOW_DATABASE_URL"
uv run python -m moneyflow mcp --db "$MONEYFLOW_DATABASE_URL"Local environment
A Postgres and a Metabase in containers, filled from the old repo, with three dashboards. Everything it stores lives under .local/ (gitignored).
Prerequisites: docker (or podman; set MF_COMPOSE="podman compose") and uv.
cp .env.example .env # optional: `./local.sh up` creates .env with random passwords if it is missing
./local.sh upIn
.env, setMF_OLD_REPOto the path of the old repo (it is only read, never copied or changed). local.sh refuses to run without it../local.sh upstarts the containers, migrates, imports and rebuilds, and provisions Metabase. Run it again at any time: the import is incremental and prints inserted / updated / deleted / unchanged counts per table.
Command | What it does |
| start everything, migrate, import, rebuild, provision Metabase |
| import and rebuild only (containers must be running) |
| containers, schema revision, row counts, Metabase health |
| stop the containers; data stays in |
URLs. Postgres on
localhost:5434(databasemoneyflow_dev), Metabase onhttp://localhost:3000. Both ports are set in.env(MF_PG_PORT,MF_MB_PORT).Metabase first login. Use
MB_ADMIN_EMAILandMB_ADMIN_PASSWORDfrom.env.Dashboards. The JSON definitions are in
deploy/metabase/dashboards/(Month, Categories by cycle, Transactions). They are native SQL, upserted by name into the collection "MoneyFlow (provisioned)". Edits made in the Metabase UI inside that collection are overwritten by the nextup; change the JSON instead.Reset. There is no reset command:
./local.sh stop, then delete.local/by hand. The next./local.sh uprecreates the bind directories under.local/before it starts the containers.Passwords.
uprefuses to start while a password in.envis empty or stillchange-me; the message names the key only. Both ports are published on127.0.0.1only.Runtimes. The local environment was tested on podman only, not on Docker Desktop.
Memory. Metabase runs with JAVA_OPTS="-Xmx384m -XX:+UseSerialGC -XX:ReservedCodeCacheSize=64m -Xss512k -XX:TieredStopAtLevel=1" in deploy/compose.yml; the measured numbers are below.
Podman VM. The podman VM needs 4 GB: podman machine set --memory 4096 (the machine must be stopped first).
Podman VM memory, measured. Measured 2026-11-07 on a 4 GB podman VM (3.9 GB usable): peak Metabase java RSS about 900 MB during provisioning, VM used about 1.5 GB of 3.9 GB after up.
OOM check. On podman, run
podman machine sshthendmesg | grep -i 'killed process'; any line means the VM killed a process for memory.podman without a socket file. If the host has no podman API socket file, compose can reach the machine's socket over ssh: forward the machine's
/run/podman/podman.sockto a local unix socket withssh -L, and pointDOCKER_HOSTat that local socket.
Which Postgres
Postgres | Port | Databases | Used for |
| 5433 |
| the test suite only |
local environment ( | 5434 |
| development data and Metabase |
Tests never use moneyflow_dev. mf-pg stays as it is; nothing here deletes it. The Quick start above uses mf-pg for a throwaway dev database; with the local environment, point MONEYFLOW_DATABASE_URL at port 5434 instead.
Metabase licence
Metabase is released under the AGPL. This repo only references the image metabase/metabase by tag in deploy/compose.yml; the image is not shipped or copied here, and this repo stays MIT.
Use from Claude Code
The MCP server is read-only and talks to the local database. Take MF_READER_PASSWORD from .env:
claude mcp add moneyflow -- uv run --directory /path/to/moneyflow python -m moneyflow mcp --db postgresql://mf_reader:<MF_READER_PASSWORD>@localhost:5434/moneyflow_devEverything after -- is the server command. Use -s user or -s project before the name to change the scope (default local).
Tests and quality gates
uv run pytest -q
./check.sh./check.sh is also what CI runs. It covers tests, import contracts, CRAP, duplication and mutation testing. To set up the test database, see AGENTS.md.
Contributing
See CONTRIBUTING.md. Releases are automatic: semantic-release reads conventional commits on main and publishes a GitHub release and CHANGELOG.md.
Security
See SECURITY.md.
License
Available Tools
4 toolscategory_totalsA
Signed kept amount per (category, subcategory, currency), either over [date_from, date_to] (both inclusive) or over one budget month (YYYY-MM), not both.
Inputs: date_to, date_from, budget_month. Returns: result
find_transactionsC
Transactions with their ledger entry. text is a case-insensitive substring of description or comment.
Inputs: date_to (required), date_from (required), text, limit, +1 more. Returns: result
month_summaryA
One budget cycle: dates, days total and left, income and total actual per currency (original-currency amounts, never folded into one number) and cash in hand (null before the cash cutover). budget_month (YYYY-MM) defaults to the open cycle.
Inputs: budget_month. Returns: object
spendingB
Signed kept amount per currency for one category over [date_from, date_to], both inclusive.
Inputs: date_to (required), category (required), date_from (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 4 tools
spending and category_totals both aggregate signed amounts over date ranges and could be confused, but spending is scoped to one category while category_totals provides a multi-category breakdown. month_summary and find_transactions are clearly distinct from both.
find_transactions follows a verb_noun pattern, while spending, category_totals, and month_summary are noun-based. The names are readable, but the convention is mixed rather than predictable.
Four tools is a focused, well-scoped set for a reporting-oriented server, and each tool covers a distinct query need. There is no excessive surface area or obviously redundant tool.
The read-only reporting surface covers spending, category breakdowns, monthly summaries, and transaction search, but lacks transaction creation/editing, category/account listing, and budget management. These are notable gaps if the server is meant to support full budget workflows.
Maintenance
Related MCP Connectors
Query your real net worth, spending, transactions, budgets and portfolio from any MCP client.
Query, edit, and reconcile a hosted Beancount ledger: BQL, reports, files, and bank imports.
Managed Postgres MCP: projects, SQL, docs search, and storage buckets via OAuth.
Read-only finance MCP server. Connects your banks, cards, payment apps, books and payroll into one ledger for your AI. Can't move money. Open source (AGPL-3.0), free during beta.
Related MCP Servers
- AlicenseBqualityDmaintenanceA lightweight Postgres MCP server for safe database exploration and query analysis, read-only by default, with multi-database support.416 PyPI4MIT
- AlicenseAqualityCmaintenanceLocal MCP server for safe querying and inspecting PostgreSQL databases, with write and maintenance operations disabled by default.832 npm1ISC
- AlicenseNot gradedqualityDmaintenanceProvides a read-only PostgreSQL MCP server with schema introspection. Enforces least-privilege database roles to prevent any writes, even from malicious SQL.MIT
- FlicenseAqualityBmaintenanceEnables MCP clients to safely inspect and query an explicitly allowlisted subset of a Postgres database through four read-only tools: a readiness check, table listing, column description, and typed row selection with filters, ordering, and paging. It runs over stdio for local clients or Streamable HTTP for separately managed ones, with bound parameters, bounded reads, and read-only transactions.4-