bankstatementparser-lsp
Language Server Protocol server that lints MT940 bank-statement files as you type, backed by the bankstatementparser library.
Contents
Getting started
- What is bankstatementparser-lsp? — the problem it solves
- Install — PyPI, virtualenv, Docker
- Quick start — wire it to your editor in 60 seconds
Library reference
- Features — live MT940 diagnostics as you type
- Editor wiring — Neovim, VS Code, Helix, generic
- Using the helpers — call the diagnostic engine from Python
- The bankstatementparser suite — core lib and LSP server
Operational
- When not to use bankstatementparser-lsp — honest boundaries
- Development — gates, make targets
- Security — sandboxing posture
- Documentation — examples, guides
- Contributing — how to get changes in
- License — Apache-2.0
What is bankstatementparser-lsp?
A Language Server speaks the
Language Server Protocol (LSP) —
the editor-agnostic protocol that lets a single backend deliver
diagnostics to any LSP client (VS Code, Neovim, Helix, Emacs, …).
bankstatementparser-lsp is that backend for MT940 bank-statement
files (.mt940 / .sta): the SWIFT tag-and-line format parsed by the
bankstatementparser
library.
The diagnostic engine shares the MT940 tag patterns the
bankstatementparser parser relies on, so the squiggles you see in the
editor match the structure the parser will accept.
| Concern | How bankstatementparser-lsp handles it |
|---|---|
| Mandatory tags | Flags any missing :20:, :25:, :28C:, :60F:, :62F: tag |
| Balance lines | Validates :60F: / :62F: against C/D + YYMMDD + 3-letter currency + amount |
| Statement lines | Validates :61: against YYMMDD + C/D + amount |
| Information lines | Warns when an :86: line has no preceding :61: statement line |
| Live linting | Re-lints on open and on every change, publishing diagnostics back to the editor |
Install
| Channel | Command | Notes |
|---|---|---|
| PyPI | pip install bankstatementparser-lsp |
Pulls in bankstatementparser >= 0.0.11 + pygls |
| Source | git clone https://github.com/sebastienrousseau/bankstatementparser-lsp && cd bankstatementparser-lsp && poetry install |
For development |
| Docker (GHCR) | docker pull ghcr.io/sebastienrousseau/bankstatementparser-lsp:latest |
Multi-arch (linux/amd64, linux/arm64); runs bankstatementparser-lsp over stdio |
Requires Python 3.10 or later. Works on macOS, Linux, and Windows.
Verify the installation:
python -c "import bankstatementparser_lsp; print('bankstatementparser-lsp', bankstatementparser_lsp.__version__)"
# -> bankstatementparser-lsp 0.0.19
Using an isolated virtual environment (recommended)
python -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows
python -m pip install -U bankstatementparser-lsp
Quick start
The package installs a bankstatementparser-lsp console entry point that starts
the language server over stdio:
bankstatementparser-lsp
# -> (waiting on stdin for LSP JSON-RPC)
The command speaks LSP on stdin/stdout — it is meant to be launched by
your editor's LSP client, not used interactively. Wire it up
(Editor wiring) and open any MT940 statement file
(.mt940 / .sta); diagnostics light up as you type.
Features
For MT940 bank-statement documents (one statement of SWIFT-style
:tag: lines), bankstatementparser-lsp publishes diagnostics:
| Rule code | Severity | Behaviour |
|---|---|---|
missing-tag |
error | A mandatory tag (:20:, :25:, :28C:, :60F:, :62F:) is absent |
malformed-balance |
error | A :60F: / :62F: balance line does not match C/D + YYMMDD + 3-letter currency + amount |
malformed-statement-line |
error | A :61: statement line does not match YYMMDD + C/D + amount |
orphan-information-line |
warning | An :86: information line has no preceding :61: statement line |
Diagnostics are republished on textDocument/didOpen and
textDocument/didChange, so the editor stays in sync on every keystroke.
An empty or whitespace-only document produces no diagnostics.
The feature logic lives in a pure, importable engine
(diagnostics_for_mt940, returning Diagnostic objects with a
Severity); the LSP handlers are thin glue that map those objects to
lsprotocol types.
Editor wiring
Register bankstatementparser-lsp as the server cmd for MT940 files in
your editor's LSP client. MT940 files commonly use the .mt940 or .sta
extension; most editors will need a filetype mapping for them.
Neovim (built-in vim.lsp.config)
-- Map the MT940 extensions to a filetype.
vim.filetype.add({
extension = {
mt940 = "mt940",
sta = "mt940",
},
})
vim.lsp.config["bankstatementparser"] = {
cmd = { "bankstatementparser-lsp" },
filetypes = { "mt940" },
root_markers = { ".git" },
}
vim.lsp.enable("bankstatementparser")
VS Code (bundled scaffold)
A TypeScript language-client scaffold ships at
editors/vscode/ — runnable straight from source:
cd editors/vscode
npm install
npm run compile
# Press F5 in VS Code to launch an Extension Development Host.
bankstatementparser.serverCommand (default bankstatementparser-lsp) is
exposed as a setting; the extension activates for .mt940 / .sta files.
Helix / Emacs / generic LSP
Any client that can spawn a stdio language server will work. The
command is bankstatementparser-lsp and the documents are MT940
statement files (.mt940 / .sta).
Using the helpers
Because the diagnostic engine is pure, you can call it directly — no editor or server process required. This is exactly what the server runs on each edit:
from bankstatementparser_lsp.diagnostics import diagnostics_for_mt940
# A clean MT940 statement produces no diagnostics.
clean = (
":20:STARTUMS\n"
":25:1234567890\n"
":28C:00001/001\n"
":60F:C230101EUR1000,00\n"
":61:2301020102C500,00NTRFNONREF//abc\n"
":86:Salary payment\n"
":62F:C230102EUR1500,00"
)
assert diagnostics_for_mt940(clean) == []
# Missing mandatory tags surface as errors.
diagnostics = diagnostics_for_mt940(":20:ONLY\n:61:2301020102C5,00NTRF")
print(len(diagnostics), "issue(s)")
# -> e.g. "4 issue(s)"
# Each diagnostic carries a 0-based range, a severity, and a rule code.
for d in diagnostics:
print(d.line, d.code, d.message)
# -> 0 missing-tag Missing mandatory MT940 tag: :25:
# ...
Each Diagnostic exposes line, col_start, col_end, severity
(a Severity enum matching the LSP numeric scale), message, and a
stable code — which the server maps to lsprotocol.Diagnostic before
publishing.
The runnable version of this snippet lives in
examples/01_lsp_helpers.py. See also
02_severity_filtering.py (grouping
by severity),
03_lsp_conversion.py (the
lsprotocol conversion the server performs), and
04_server_publish.py (the server's
lint-and-publish path driven by a fake LanguageServer, so it runs
without an editor).
The bankstatementparser suite
bankstatementparser-lsp is part of a set of independently installable packages
built around the bankstatementparser
library — pick whichever ones your stack needs:
| Package | Role |
|---|---|
bankstatementparser |
Core library + CLI (MT940 / CAMT parsing) |
bankstatementparser-lsp |
Language Server Protocol server (this package) |
flowchart LR
A["Editor (VS Code / Neovim / …)"] -->|LSP over stdio| B["bankstatementparser-lsp"]
B -->|diagnostics_for_mt940| C["diagnostic engine (MT940 tag patterns)"]
C -->|Diagnostic objects| B
B -->|publishDiagnostics| A
When not to use bankstatementparser-lsp
- You're not editing MT940 statements. The server targets the SWIFT
MT940 tag-and-line format (
.mt940/.sta); for CAMT XML or other formats use a format-appropriate language server. - You need full parsing, not editor diagnostics. Use the core
bankstatementparserlibrary to parse statements into structured records.
Development
bankstatementparser-lsp uses Poetry and
mise.
git clone https://github.com/sebastienrousseau/bankstatementparser-lsp.git
cd bankstatementparser-lsp
mise install
poetry install
A Makefile orchestrates the quality gates (kept in lockstep with CI):
| Target | What it runs |
|---|---|
make check |
All gates (REQUIRED before commit) |
make test |
pytest --cov=bankstatementparser_lsp --cov-branch --cov-fail-under=100 |
make lint |
ruff check + ruff format --check |
make type-check |
mypy --strict |
make examples |
Run the example scripts |
Current state (v0.0.19): 94 tests passing, 100% line + branch
coverage against a 100% enforced floor, mypy --strict clean,
interrogate 100% docstring coverage. The suite includes documentation
and example regression tests
(tests/test_docs_accuracy.py,
tests/test_regression_docs.py,
tests/test_regression_examples.py)
that execute every documented snippet and every examples/*.py script.
Security
- No filesystem writes. The server reads from the editor's in-memory document buffer; no scratch files, no temp directories.
- MT940 parsing is a pure-
reline scanner over text from the editor — noeval, no shelling out, no XML, no network. - Lint findings are returned as
lsprotocol.Diagnosticobjects with no stack traces, so the editor never sees an internal path or exception message. - Dependencies are pinned via
poetry.lockand audited bypip-auditand Bandit in CI.
To report a vulnerability, please use GitHub private vulnerability reporting rather than a public issue.
Documentation
- Runnable examples:
examples/ - VS Code scaffold:
editors/vscode/ - Release history: CHANGELOG.md
- Core library docs: docs.bankstatementparser.com
- LSP specification: microsoft.github.io/language-server-protocol
Contributing
Contributions are welcome — see the
contributing instructions.
Thanks to all the
contributors
who have helped build bankstatementparser-lsp.
Ecosystem
bankstatementparser is part of a modular financial ecosystem. Optional companion packages provide specialized loaders, writers, AI agents, language servers, and transport protocol adapters:
| Package | GitHub Repository | PyPI | Role | Description |
|---|---|---|---|---|
bankstatementparser |
sebastienrousseau/bankstatementparser |
Core Engine | Unified parser for CAMT (052/053), PAIN.001, CSV, OFX, QFX, MT940, and PDF statements | |
bankstatementparser-mcp |
sebastienrousseau/bankstatementparser-mcp |
AI Protocol | Model Context Protocol (MCP) server exposing statement tools to LLMs & AI agents | |
bankstatementparser-lsp |
sebastienrousseau/bankstatementparser-lsp |
Developer Tooling | Language Server Protocol (LSP) with live SWIFT MT940 statement validation & diagnostics | |
bankstatementparser-transport-ebics |
sebastienrousseau/bankstatementparser-transport-ebics |
Transport | Automated bank statement retrieval over EBICS 3.0 (H005) and 2.5 (H004) protocols |
|
bankstatementparser-writer-xlsx |
sebastienrousseau/bankstatementparser-writer-xlsx |
Output Writer | Formats and exports parsed banking transactions into styled Microsoft Excel (.xlsx) workbooks |
|
bankstatementparser-writer-qif |
sebastienrousseau/bankstatementparser-writer-qif |
Output Writer | Serializes transactions into standard Quicken Interchange Format (.qif) exchange files |
|
bankstatementparser-writer-ofx |
sebastienrousseau/bankstatementparser-writer-ofx |
Output Writer | Serializes transactions into standard Open Financial Exchange (.ofx) XML/SGML files |
|
bankstatementparser-writer-swift |
sebastienrousseau/bankstatementparser-writer-swift |
Output Writer | Exports transactions to SWIFT MT940 customer statements and MT942 interim reports | |
bankstatementparser-loader-bai2 |
sebastienrousseau/bankstatementparser-loader-bai2 |
Input Loader | Parses BAI2 cash-management and account balance statements | |
bankstatementparser-loader-mt942 |
sebastienrousseau/bankstatementparser-loader-mt942 |
Input Loader | Parses SWIFT MT942 interim transaction reports with credit/debit summary reconciliation | |
bankstatementparser-loader-cfonb |
sebastienrousseau/bankstatementparser-loader-cfonb |
Input Loader | Parses French CFONB 120 / AFB120 120-byte fixed-width banking statement files | |
bankstatementparser-loader-camt054 |
sebastienrousseau/bankstatementparser-loader-camt054 |
Input Loader | Ingests ISO 20022 CAMT.054 real-time debit/credit notification stream XML | |
bankstatementparser-loader-sepa |
sebastienrousseau/bankstatementparser-loader-sepa |
Input Loader | Ingests ISO 20022 SEPA PAIN.002 payment status reports and PAIN.008 direct debit mandates | |
bankstatementparser-loader-bacs |
sebastienrousseau/bankstatementparser-loader-bacs |
Input Loader | Parses UK BACS Standard 18 / Faster Payments 106-byte fixed-width transmission files |
License
Licensed under the Apache License, Version 2.0.
Built on pygls and
lsprotocol by the
Open Law Library, and on the core
bankstatementparser library that
powers the validators and schemas.
Any contribution submitted for inclusion shall be licensed as above, without additional terms.
Metadata
Release files for bankstatementparser-lsp 0.0.19
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bankstatementparser_lsp-0.0.19.tar.gz | 20.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bankstatementparser_lsp-0.0.19-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.3 kB
Release files / bankstatementparser_lsp-0.0.19.tar.gz
| Download URL | bankstatementparser_lsp-0.0.19.tar.gz |
|---|---|
| Size | 20.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c58436b1eec844caf25479c69dc6f793c90f7901f6a9de36c03a5870946288c2
|
|
BLAKE2b-256 checksum How to use checksums |
8e14e30baf4064176630b04a80469035d29a98b1bfa52de980cbcc094dcb1ecd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.
Transparency logRelease files / bankstatementparser_lsp-0.0.19-py3-none-any.whl
| Download URL | bankstatementparser_lsp-0.0.19-py3-none-any.whl |
|---|---|
| Size | 17.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
606b20907d2836f0128d8770dde4c944b3035e074a90c766ad5eb886e96c85ad
|
|
BLAKE2b-256 checksum How to use checksums |
1952139d9e3d2980ebe0e93736da954f5e0a9f3de150cc3ef70de12c4f6a3f1e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 1, 2026.
Transparency log