statementflow-mcp
Supports parsing Orange Money mobile money export files, converting them into normalized JSON transactions with date and amount normalization, debit/credit separation, accounting consistency checks, and alerts.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
StatementFlow
Turn bank statements and mobile money exports into normalized, verified JSON transactions.
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.jsonfrom 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 |
| local processing, shell scripts |
REST API |
| HTTP integrations |
MCP |
| AI agents (Claude, Cursor…) |
Python SDK |
| 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-mcpReady-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 minus1.234,56-.Dates: ISO,
31/01/2026,31.01.2026,31-01-2026, 2-digit years — always normalized to ISO 8601; impossible dates becomenull+ 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 → |
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 → |
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 passedMeasured 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-IDon 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
Metrics come from a synthetic corpus; real statements (batch layouts, exotic fonts, graphical headers) can fail — alerts and confidence exist to flag it.
OCR confidence is capped (≤ 0.75, 0.6 if low); very low-quality scans can yield wrong amounts — always check
chain_break/ocr_low_confidencealerts.Currency is never guessed: documents without a readable currency →
currency: nullalert (provide
--currency-hint).
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).Encrypted/password-protected PDFs are rejected with an explicit error.
Legacy binary
.xlsis not supported (XLSX only).Scanned-page rotation/orientation is not auto-corrected (tesseract runs without OSD) — heavily skewed scans may degrade amounts.
Amounts are read as floats: precision is guaranteed up to ~1e13 units (beyond realistic statements; a safe chain-break alert appears instead).
Documentation
docs/API.md— full JSON schema, endpoints, alert codesdocs/MCP.md— MCP server and exposed toolsdocs/ARCHITECTURE.md— design, adapters, extension guidedocs/FORMATS.md— supported formats and statement templatesdocs/SECURITY.md— data handling, limits, legal notesdocs/BILLING.md— usage metering, quotas, future billing (no gateway integrated)docs/DEPLOYMENT.md— self-hosting: ready / needs config / must securedocs/PILOT.md— zero-budget pilot kit: demo script, evaluation sheet, templatesdocs/TROUBLESHOOTING.md— common errors and fixesdocs/DEPENDENCIES.md— dependency licenses
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.
This server cannot be deployed
Maintenance
Related MCP Connectors
Turn bank statement PDFs, CSVs, XLSX and OFX into categorised transactions plus a summary.
Turn bank statement PDFs into categorized, balance-checked transactions and reports.
Convert PDF bank statements into structured transactions, accounts, and balances.
Bank statement PDFs become CSV or JSON transactions with dates, amounts and balances.
Related MCP Servers
- AlicenseAqualityDmaintenanceConverts PDF bank statements into structured data (Markdown, JSON, CSV, JSONL) with verified transactions and balance checks, enabling agents to audit numbers.510 npmMIT
- AlicenseNot gradedqualityBmaintenanceDeterministic 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

bankstatementlyofficial
AlicenseAqualityBmaintenanceParse 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).181MIT- AlicenseAqualityCmaintenanceConverts 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.5MIT