Skip to main content
Glama
finledger

finledger

by anikam13

FinLedger

A local financial ledger with three read surfaces, plus an MCP server so an agent can query them:

  • expenses: spending accounts, reconciled against peer reimbursements

  • investments: brokerage balances, holdings, and activity

  • income: payroll (gross, withholdings, take-home)

Expenses and investments share a store and nothing else. An account carries an explicit domain, and every expense query joins through it, so a share purchase cannot reach the reimbursement matcher.

The matcher is rules-first. It abstains when it is not sure. A human or agent confirms before a match shrinks net spend.

Real transactions, paystubs, and API keys stay on your machine (~/.finledger/ledger.db, .env). This repository ships code and a synthetic eval set only.

Install

Python 3.10+. The ledger, matcher, MCP loop, and eval harness are standard library. pypdf is optional and only needed to import paystub PDFs.

pip install -e .

Related MCP server: notion-household-finance-mcp

MCP server

python3 -m finledger.mcp_server --db ~/.finledger/ledger.db

18 tools, namespaced expenses_*, investments_*, and income_*, plus savings_rate, accounts, sync, and reconcile.

Cursor example (~/.cursor/mcp.json):

{
  "mcpServers": {
    "finledger": {
      "command": "python3",
      "args": ["-m", "finledger.mcp_server"]
    }
  }
}

The default ledger path is ~/.finledger/ledger.db.

CLI

finledger sync
finledger reconcile
finledger review
finledger serve

finledger serve opens a local desk on :8770. On macOS you can also double-click scripts/Expense Desk.command.

Optional live sources (put credentials in .env, never commit it):

Source

How

shim.finance (card + Venmo)

SHIM_API_KEY

SnapTrade (checking + brokerages)

SNAPTRADE_CLIENT_ID, SNAPTRADE_CONSUMER_KEY, SNAPTRADE_USER_ID, SNAPTRADE_RECOVER

Card CSV backfill

finledger sync --card-csv PATH --card-account-id ID

Paystub PDF

python3 scripts/paystub_import.py statement.pdf (needs pypdf)

Copy .env.example to .env.

Public eval

The published gold set is synthetic. It is generated by scripts/make_sample_data.py and lives in data-sample/. Every transaction row is marked synthetic: true. It is a coverage set for matcher behaviours (clean match, fan-in, bundling, peer-outbound parent, merchant credits, weak notes, cross-source twins). It is not anonymized real data.

python3 scripts/eval_public.py
# equivalent:
python3 -m reconcile.eval --matcher rules_v0

Numbers you can reproduce from this repo

Measured on data-sample/ with rules_v0 (window ±90 days, auto-match threshold 0.75):

Metric

Value

evaluable examples

22 (2 unsure labels skipped)

exact-set accuracy

72.7% (16/22)

edge P / R / F1

81.2% / 61.9% / 70.3%

auto-match precision

85.7% (n=14; 12 tp, 2 fp)

auto-match recall of gold matches

66.7%

Re-run python3 scripts/eval_public.py to refresh these. Two remaining false positives on the sample are real matcher weaknesses, including the emoji recall-lift rule overreaching.

What is not in this repo

A private gold set of about 92 labeled examples was used during development. It names real people and real purchases and is not published. Do not treat the sample numbers as a reproduction of that set. Different corpus, different size, different scores.

This repository does not claim 100% auto-match precision.

Matcher

See reconcile/README.md. Short version:

Name

Behavior

baseline

Nearest charge within ±$1 and a date window. Empty if none.

rules_v0

Amount fit + date + note/merchant overlap, with vetoes. Auto-match if confidence >= 0.75; else abstain.

rules_v0_llm

Same as rules_v0, then optional Groq call on review residue (GROQ_API_KEY).

Label the sample corpus with python3 labeling/app.py (defaults to data-sample/).

License

MIT

Available Tools

18 tools
accountsC

Every connected account, split by domain (expense vs investment).

Inputs: no named parameters.

context_notesA

Free-text goals, career plans, and constraints written by the user. These are statements of intent, not figures derived from the ledger — do not treat them as data.

Inputs: no named parameters.

expenses_outstandingA

What is still owed to you. Only charges with at least one confirmed reimbursement are counted as shared; charges nobody has paid toward are excluded because the data cannot distinguish a shared cost from an ordinary purchase.

Inputs: no named parameters.

expenses_recurringD

Charges repeating on a roughly monthly cadence at a stable amount, with annualized cost.

Inputs: no named parameters.

expenses_resolveB

Record a decision on an inbound payment. Pass charge_ids to link reimbursements. Empty charge_ids = not a reimbursement. disposition=charge_missing when it is a repayment but the parent charge(s) are not in the ledger. Decisions survive re-runs.

Inputs: inbound_id (required), charge_ids, disposition.

expenses_review_queueA

Inbound payments the matcher would not auto-match, best candidate first. These need a human or agent decision via expenses_resolve.

Inputs: limit.

expenses_runwayC

Spending-account balances plus trailing monthly net burn.

Inputs: months.

expenses_spendA

Spend in a window, grouped. Returns gross, reimbursed, and net. Net subtracts only CONFIRMED reimbursements — an unreviewed auto-match is a proposal, not a fact.

Inputs: end, start, group_by.

income_contributionsC

Payroll deductions year-to-date, each classified savings / cost / offset, plus employer contributions.

Inputs: year.

income_statementsC

Individual pay statements in a window.

Inputs: end, start.

income_summaryA

Year-to-date earnings from payroll. IMPORTANT: net_pay_ytd is only what reached a bank account; payroll_savings_ytd (401k/Roth/HSA/ESPP) also belongs to the user. Use disposable_ytd = net_pay + payroll_savings when judging whether income covers spending. imputed_offset_ytd is booked as both an earning and a deduction and nets to zero.

Inputs: year.

investments_balancesB

Latest balance per investment account, plus the total.

Inputs: no named parameters.

investments_holdingsC

Current holdings, aggregated by ticker across accounts by default.

Inputs: by_symbol.

investments_summaryB

Portfolio value plus what actually entered and left over a trailing window. BUY/SELL are excluded from cash figures — they move money within an account, not into or out of it.

Inputs: months.

investments_transactionsD

Investment activity in a window.

Inputs: end, start.

reconcileB

Re-run the matcher over inbound payments. Confirmed decisions are preserved.

Inputs: no named parameters.

savings_rateA

What share of earnings is being kept, combining payroll savings with what survives spending. Income is year-to-date and spend is a trailing window, so the ratio is an estimate — read the caveats array before quoting the number.

Inputs: no named parameters.

syncB

Pull every source into the store. Idempotent and additive; never deletes.

Inputs: card_csv_path.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3/5.0

    Scored across 18 tools

    Disambiguation5/5

    Each tool has a clearly defined role within its domain: expenses, investments, income, savings, or general ledger management. The distinct prefixes (expenses_, investments_, income_) prevent cross-domain confusion, and within domains, tools like spend vs. outstanding vs. runway vs. review_queue are semantically distinct. Even the less prefixed tools (reconcile, sync, accounts) are obviously separate from the financial queries.

    Naming Consistency4/5

    The dominant pattern is domain-prefix + descriptive noun (e.g., expenses_spend, investments_balances, income_summary), which is highly consistent. However, a few tools like reconcile, sync, accounts, and savings_rate do not follow the prefix scheme, creating minor inconsistency. The syntax is all snake_case with no verb conjugations, so the deviation is not jarring.

    Tool Count4/5

    Eighteen tools is on the higher end of typical MCP servers, but the breadth of the domain—expenses, investments, income, savings, notes, accounts, sync—justifies the count. Each tool addresses a specific financial question or action, and none feel redundant. The size is slightly above the ideal 3-15 range but well within the acceptable limit for a comprehensive financial ledger service.

    Completeness4/5

    The tool surface covers the core lifecycle of financial data aggregation: reading balances, transactions, and summaries, plus actions like reconciliation and decision resolution. There are minor gaps, such as no direct way to create or edit transactions or notes, but these are likely handled externally or intentionally read-only. The inclusion of sync and review queues ensures operational completeness for the stated purpose.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables interaction with local Beancount accounting ledgers through structured tools for viewing accounts, balances, and transactions, as well as inserting/removing transactions and answering natural-language questions via BeanQuery. Provides deterministic, validated, and auditable financial data operations with offline-first functionality.
      1
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides tools for querying and writing finance records in a Notion-backed household finance workspace, enabling management of budgets, expenses, savings, and debt through natural language.
      MIT
    • A
      license
      B
      quality
      C
      maintenance
      Enables AI agents to manage personal finances with deterministic, grounded tools for cash-flow projection, drift detection, reconciliation, and Todoist integration. All figures trace back to a local SQLite database.
      55
      MIT
    • F
      license
      A
      quality
      C
      maintenance
      Enables AI agents to create accounts, record balanced double-entry transactions, query balances, and reconcile accounts against a SQLite-backed ledger through four MCP tools.
      4
      -