Skip to main content
Glama
MoneyFlow MCP Server

MoneyFlow MCP Server

MoneyFlow

ci release license: MIT

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+

  • uv

  • 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 up
  1. In .env, set MF_OLD_REPO to the path of the old repo (it is only read, never copied or changed). local.sh refuses to run without it.

  2. ./local.sh up starts 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

./local.sh up

start everything, migrate, import, rebuild, provision Metabase

./local.sh refresh

import and rebuild only (containers must be running)

./local.sh status

containers, schema revision, row counts, Metabase health

./local.sh stop

stop the containers; data stays in .local/

  • URLs. Postgres on localhost:5434 (database moneyflow_dev), Metabase on http://localhost:3000. Both ports are set in .env (MF_PG_PORT, MF_MB_PORT).

  • Metabase first login. Use MB_ADMIN_EMAIL and MB_ADMIN_PASSWORD from .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 next up; change the JSON instead.

  • Reset. There is no reset command: ./local.sh stop, then delete .local/ by hand. The next ./local.sh up recreates the bind directories under .local/ before it starts the containers.

  • Passwords. up refuses to start while a password in .env is empty or still change-me; the message names the key only. Both ports are published on 127.0.0.1 only.

  • 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 ssh then dmesg | 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.sock to a local unix socket with ssh -L, and point DOCKER_HOST at that local socket.

Which Postgres

Postgres

Port

Databases

Used for

mf-pg (the docker run in AGENTS.md)

5433

moneyflow_test

the test suite only

local environment (./local.sh up)

5434

moneyflow_dev, metabase

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_dev

Everything 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

MIT

Available Tools

4 tools
category_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

    B3.2/5.0

    Scored across 4 tools

    Disambiguation4/5

    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.

    Naming Consistency3/5

    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.

    Tool Count5/5

    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.

    Completeness3/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      A lightweight Postgres MCP server for safe database exploration and query analysis, read-only by default, with multi-database support.
      4
      16 PyPI
      4
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Local MCP server for safe querying and inspecting PostgreSQL databases, with write and maintenance operations disabled by default.
      8
      32 npm
      1
      ISC
    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides a read-only PostgreSQL MCP server with schema introspection. Enforces least-privilege database roles to prevent any writes, even from malicious SQL.
      MIT
    • F
      license
      A
      quality
      B
      maintenance
      Enables 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
      -