Skip to main content
Glama
statementflow-mcp

statementflow-mcp

StatementFlow

Turn bank statements and mobile money exports into normalized, verified JSON transactions.

English · Français

CI License: MIT

Native PDFs, scanned PDFs (OCR), CSV, TSV, XLSX → ISO dates, cleaned labels, separated debits/credits, currencies detected when identifiable, opening/closing balances, accounting consistency checks and alerts on uncertain data. Built for French, European and UEMOA / francophone West African formats (FCFA amounts, Wave / Orange Money / MTN MoMo / Moov exports — provided lawfully by their owners).

  • 100% local rules engine — no API key, no paid service, no network calls;

  • CLI, REST API, MCP server (AI agents) and Python SDK;

  • no document storage: ephemeral in-memory processing.

⚠️ Honest performance note: the published metrics (synthetic test corpus of 32 documents / 447 transactions) are internal test results, not a guarantee on your real statements. Test on your own documents before any production use — that is exactly what the consistency checks, alerts and confidence scores are for.

Quick start

# install (dependencies: pdfplumber, openpyxl — all free)
pip install -e .

# optional, for scanned PDF OCR:
#   apt install tesseract-ocr poppler-utils

# convert a statement to JSON
statementflow parse statement.pdf --output result.json --pretty

# a whole folder of exports → one JSON per document
statementflow parse exports/ --outdir results/ --quiet

# accounting checks only
statementflow check result.json
from statementflow import parse_file
r = parse_file('statement.pdf')
print(r['totals'], r['checks']['opening_closing_ok'], r['confidence'])

Related MCP server: Statement Normalizer

Sample output (real excerpt, synthetic document)

{
  "schema": "statementflow/v1",
  "document": {"filename": "SYNTH_fr_societegenerale_A.pdf",
               "kind": "pdf", "pages": 1, "method": "text",
               "parser": "generic-columns-v3", "adapter": "generic-pdf"},
  "currency": "EUR",
  "opening_balance": 3812.53,
  "closing_balance": -3319.45,
  "transactions": [
    {"index": 1, "date": "2026-01-01", "label": "CB ABONNEMENT NETFLIX",
     "debit": 859.35, "credit": null, "balance": 2953.18, "currency": "EUR",
     "confidence": 1.0,
     "trace": {"page": 1, "method": "text", "source_row": 7}}
  ],
  "checks": {"chain_checked": 14, "chain_matches": 14, "chain_ok": true,
             "opening_closing_ok": true,
             "totals": {"count": 14, "debits": 7507.2, "credits": 6375.22}},
  "alerts": [],
  "confidence": 1.0
}

Full engine-generated examples: outputs/ (French statement, Wave CSV export, scanned PDF with alerts). Schema reference: docs/API.md.

Self-hosting

A Dockerfile is provided for local or private-network use (docker run --rm -p 127.0.0.1:8080:8080 statementflow). Do not expose it publicly as-is — see docs/DEPLOYMENT.md for what is ready, what needs configuration, and what must be secured first.

The four interfaces

Interface

Command / entry point

Use case

CLI

statementflow parse <file|folder>

local processing, shell scripts

REST API

uvicorn statementflow.api:app → /docs (OpenAPI)

HTTP integrations

MCP

statementflow-mcp (stdio)

AI agents (Claude, Cursor…)

Python SDK

from statementflow.sdk import Client

Python applications

# REST API (interactive docs at http://127.0.0.1:8080/docs)
uvicorn statementflow.api:app --host 127.0.0.1 --port 8080
# every private route requires X-API-Key (any non-empty key in local open mode)
curl -X POST http://127.0.0.1:8080/v1/analyze -H "X-API-Key: my-key" -F "file=@statement.pdf"
curl http://127.0.0.1:8080/v1/results/<job_id> -H "X-API-Key: my-key"

# MCP server (declare it in your MCP client)
statementflow-mcp

Ready-to-run integration examples: examples/ — Python, JavaScript/TypeScript, curl, n8n (importable JSON workflow), MCP client.

What the engine does

  • Input formats: native PDFs (pdfplumber), scanned PDFs (tesseract OCR at 300 dpi with automatic fallback), CSV/TSV/XLSX (separator sniffing, UTF-8 BOM, offset headers).

  • Amounts: 1 234,56 (FR, non-breaking space), 1.234,56 (DE/ES), 1,234.56 (UK), 1 234 567 XOF (integer FCFA), accounting parentheses (750,38), trailing minus 1.234,56-.

  • Dates: ISO, 31/01/2026, 31.01.2026, 31-01-2026, 2-digit years — always normalized to ISO 8601; impossible dates become null + alert (never invented).

  • Debit/credit: separate columns, signed amounts, or direction inferred from a "Sens/Type" column (RECEPTION/ENVOI/Cash-in…) — a positive amount with no direction signal is marked assumed debit + warning.

  • Accounting checks: line-by-line balance chain, global rule (opening + credits − debits = closing), duplicate handling (page repeats removed, adjacent duplicates flagged).

  • Alerts & confidence: every transaction carries a confidence score (lowered on null date, missing amount, low OCR quality) and traceability (page, method, source row); every document carries coded alerts (date_unparseable, currency_not_identified, chain_break, ocr_used…).

Test metrics (synthetic corpus — see tests/)

Measure

Value

Note

Transaction recall / precision

100% / 100%

447/447 extracted, 0 invented

Dates

98.0%

9 impossible generator dates → null + alert (strict calendar validation)

Labels, debits, credits, balances

100%

Perfectly converted documents

27/32

the other 5: documented honest behaviors

Currency

67%

5 CSVs with no currency in content → null + alert (never invented)

Measured by script (scripts/mesure_corpus.py) on the frozen synthetic corpus; v0.2.0 also fixed a harness bug in the published precision formula (weighted by transactions, not documents — the real value was already 1.0).

Test suite: 206 pytest tests (units, strict calendar dates, schema v0.2, corpus with frozen non-regression thresholds, API auth matrix, CLI, real JSON-RPC MCP, malformed files, security, accounting). CI runs them on Python 3.10/3.11/3.12 at every push and pull request.

python -m pytest tests/ -q          # 206 passed

Measured performance (local reference, i7-class laptop, 2026-11-07)

Document

Size

Transactions

Time

Native PDF (14 tx)

3 KB

14

0.09 s

Multi-page PDF (40 tx)

5 KB

40

0.08 s

Scanned PDF (OCR, tesseract-bound)

125 KB

12

~3 s

CSV (Wave export)

1 KB

12

< 0.01 s

CSV 100,000 rows

3.5 MB

100,000

4.1 s

OCR time is dominated by tesseract (per page); the row cap (200,000 by default) bounds memory. v0.2.0 also removed a quadratic alert-indexing path (100k rows: 268 s → 4.1 s).

Security & privacy

  • No storage: bytes are processed in memory and never written to disk by the engine; OCR temp files live in an OS temp dir and are removed.

  • API authentication is mandatory (v0.2.0): every private route requires X-API-Key (401 otherwise); results are bound to the submitting key (404 for any other key); server-side keys exist only as SHA-256 hashes, compared in constant time; admin operations require a separate key (STATEMENTFLOW_ADMIN_KEY); per-key quotas → 429.

  • API: results kept in process memory for at most RESULTS_TTL_S (default 15 min), then purged; a restart wipes everything. Structured errors + X-Request-ID on every response; uploaded filenames sanitized (path traversal stripped).

  • No logging of banking data (only sanitized filename, size, error codes).

  • Strict limits: 20 MB / 200 pages / 200,000 rows by default (STATEMENTFLOW_* env vars); the row cap is enforced during CSV/XLSX parsing (ZIP-bomb protection).

  • The product does not ask for bank passwords, OTP codes or account access — it only processes documents the user is authorized to transmit. It is not GDPR-certified and claims no regulatory compliance without an independent legal audit — see docs/SECURITY.md.

API keys are managed server-side:

statementflow keys create    # random key + SHA-256 hash (rotation documented)
statementflow keys hash      # hash an existing key (stdin)

Local CLI/SDK use never requires a key or an account.

Maturity status

Beta — developer preview. The engine is feature-complete on its target formats and protected by 206 tests, but it has only been validated on the synthetic corpus: no real bank statement has been processed yet. Treat every result as unverified until a pilot on documents you are authorized to process confirms it (docs/PILOT.md). Not certified for any compliance framework.

Commercial offer (v0.3.0)

StatementFlow is open source (MIT) and fully usable self-hosted for free. A managed service is also available as prepaid credits: 1 credit = 1 PDF page or 50 CSV/TSV/XLSX rows (charged only on successful processing).

Pack

Credits

Price (XOF)

Starter

500

5,000 FCFA

Pro

2,500

20,000 FCFA

Business

10,000

60,000 FCFA

Payments via mobile money/card (SasPay); credits activate only after server-side payment confirmation (signed webhook + gateway status re-check). Managed keys carry a prepaid balance (402 when exhausted), usage is metered, and the whole purchase flow is testable locally with the built-in payment simulator. Full details: docs/PRICING.md (grille), docs/BUSINESS_CASE.md (market analysis, financial simulation, license strategy), docs/TERMS.md / docs/PRIVACY.md (templates pending legal review).

Known limitations

  1. Metrics come from a synthetic corpus; real statements (batch layouts, exotic fonts, graphical headers) can fail — alerts and confidence exist to flag it.

  2. OCR confidence is capped (≤ 0.75, 0.6 if low); very low-quality scans can yield wrong amounts — always check chain_break / ocr_low_confidence alerts.

  3. Currency is never guessed: documents without a readable currency → currency: null

    • alert (provide --currency-hint).

  4. Tested formats: French, DE/NL/ES/UK, UEMOA (XOF), mobile money (Wave, Orange Money, MTN MoMo, Moov). Other banks may need an adapter (docs/FORMATS.md).

  5. Encrypted/password-protected PDFs are rejected with an explicit error.

  6. Legacy binary .xls is not supported (XLSX only).

  7. Scanned-page rotation/orientation is not auto-corrected (tesseract runs without OSD) — heavily skewed scans may degrade amounts.

  8. Amounts are read as floats: precision is guaranteed up to ~1e13 units (beyond realistic statements; a safe chain-break alert appears instead).

Documentation

License

MIT — see LICENSE.

Contributing

See CONTRIBUTING.md. Golden rule: every fix ships with a non-regression test; the test corpus is never modified to make results look better.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Converts PDF bank statements into structured data (Markdown, JSON, CSV, JSONL) with verified transactions and balance checks, enabling agents to audit numbers.
    5
    10 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Deterministic bank-statement parsing for AI agents: messy CSV/OFX exports to clean, categorized ledger rows. In-memory only, no storage, no external calls, no LLM in the loop.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Parse and query bank statements — turn PDF statements into structured transactions, accounts, and balances, with balance-reconciliation checks. A deterministic financial memory for AI agents, served as a hosted streamable-HTTP endpoint (API key or OAuth).
    18
    1
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Converts customer-supplied PDF bank statements into checked Excel, CSV, or JSON with balance validation. Runs locally with your own MainBook API key or against MainBook's hosted endpoint, and it never connects to bank accounts.
    5
    MIT