{
  "markdown": "# iso20022-bank-profile-mcp: The ISO 20022 Bank Clearing-Profile Server\n\n[![PyPI Version][pypi-badge]][07]\n[![Python Versions][python-versions-badge]][07]\n[![License][license-badge]][01]\n[![Tests][tests-badge]][tests-url]\n[![Quality][quality-badge]][quality-url]\n[![OpenSSF Scorecard][scorecard-badge]][scorecard-url]\n[![Documentation][docs-badge]][docs-url]\n\n**A fully local, closed-world [Model Context Protocol][mcp] server that\nmanages, validates, and serves bank-specific ISO 20022 clearing profiles /\nrule packs** — the market-practice rules that sit *beyond* structural XSD\nvalidation. It is a foundational member of the\n[ISO 20022 MCP Suite](#the-iso-20022-mcp-suite) and a sibling of\n[`iso20022-readiness-suite-mcp`](https://github.com/sebastienrousseau/iso20022-readiness-suite-mcp),\nwhose readiness gateway can consume the profiles this server serves.\n\n> **The November 2026 milestones.** As the major schemes (CBPR+, HVPS+, T2,\n> FedNow) tighten their ISO 20022 requirements — structured postal addresses\n> chief among them — a payment that was fine yesterday can be rejected\n> tomorrow. `iso20022-bank-profile-mcp` turns those scheme rules into\n> versioned, agent-callable clearing profiles: `list_profiles` and\n> `get_profile` serve them, `lint_payload` evaluates a payload against one,\n> and `validate_profile_definition` vets a bank-supplied rule pack. **v0.0.2**,\n> stdio by default (plus an optional OAuth 2.1 HTTP transport), 4 read-only\n> tools, premium rule-pack entitlement gating, Python 3.10+.\n\n## Contents\n\n- [Overview](#overview)\n- [The ISO 20022 MCP Suite](#the-iso-20022-mcp-suite)\n- [Install](#install)\n- [Quick Start](#quick-start)\n- [Tools](#tools)\n- [HTTP transport & authentication](#http-transport--authentication)\n- [How it fits the suite](#how-it-fits-the-suite)\n- [Open-core vs premium](#open-core-vs-premium)\n- [When not to use iso20022-bank-profile-mcp](#when-not-to-use-iso20022-bank-profile-mcp)\n- [Development](#development)\n- [Security](#security)\n- [Documentation](#documentation)\n- [License](#license)\n- [Contributing](#contributing)\n- [Acknowledgements](#acknowledgements)\n\n## Overview\n\nThe [Model Context Protocol][mcp] (MCP) is an open standard that lets AI agents\nand assistants discover and call external tools in a uniform way.\n**iso20022-bank-profile-mcp** owns the *market-practice profile layer* of the\nISO 20022 MCP Suite: the scheme-specific and bank-specific rules a payment must\nsatisfy to clear, which live *above* the XSD and vary by clearing system.\n\nA **clearing profile** is pure data — a `profile_id`, its `market_practice`,\nthe messages it supports, and a list of declarative `custom_rules`. The server\nships open baseline profiles (`Generic`, `CBPR+`, `SEPA_Instant`, `FedNow`) and\nexposes four read-only tools to discover them, fetch them in full, lint a\npayload against one, and validate a candidate rule pack.\n\nIt is a **fully local, closed-world** server: no network surface, no\nsub-servers, no meta-client. Every tool computes from the bundled profile data\nand returns typed, JSON-serialisable output; on any failure — a bad input, an\nunparseable payload, an unknown profile — it returns an `{\"error\": ...}`\npayload rather than raising into the client transport. XML payloads are parsed\nwith `defusedxml` only (no XXE / billion-laughs).\n\n- **Website:** <https://sebastienrousseau.github.io/iso20022-bank-profile-mcp/>\n- **Source code:** <https://github.com/sebastienrousseau/iso20022-bank-profile-mcp>\n- **Bug reports:** <https://github.com/sebastienrousseau/iso20022-bank-profile-mcp/issues>\n\n```mermaid\nflowchart TD\n    A[\"MCP client<br/>(Claude Desktop, IDE, agent)\"] -->|stdio| B[\"iso20022-bank-profile-mcp<br/>(clearing-profile server)\"]\n    B --> C[\"ProfileEngine<br/>(bundled JSON + register() seam)\"]\n    C --> D[\"Generic\"]\n    C --> E[\"CBPR+\"]\n    C --> F[\"SEPA_Instant\"]\n    C --> G[\"FedNow\"]\n    H[\"iso20022-readiness-suite-mcp<br/>(readiness gateway)\"] -.consumes profiles.-> B\n```\n\n## The ISO 20022 MCP Suite\n\n`iso20022-bank-profile-mcp` is one of a set of coordinated, vendor-neutral MCP\nservers for the ISO 20022 migration. Dependency ranges are kept aligned across\nthe suite, so the servers co-install cleanly in a single Python environment.\n\n| Server | Scope | Install |\n|------|------|------|\n| [`iso20022-readiness-suite-mcp`](https://github.com/sebastienrousseau/iso20022-readiness-suite-mcp) | Orchestration gateway: readiness scoring, remediation, clearing-profile linting, and bank-response simulation over the foundational servers | `pip install iso20022-readiness-suite-mcp` |\n| [`iso20022-evidence-pack-mcp`](https://github.com/sebastienrousseau/iso20022-evidence-pack-mcp) | Compiles readiness findings, remediation diffs and simulated responses into a sealed, Ed25519-signable audit evidence pack | `pip install iso20022-evidence-pack-mcp` |\n| [`structured-address-fix-mcp`](https://github.com/sebastienrousseau/structured-address-fix-mcp) | ISO 20022 postal-address classification, assessment, and remediation for the Nov 2026 structured-address cliff | `pip install structured-address-fix-mcp` |\n| [`iso20022-mcp`](https://github.com/sebastienrousseau/iso20022-mcp) | Unified gateway meta-tools (`search` / `describe` / `validate` / `generate` / `parse`) across the ISO 20022 message catalogue | `pip install iso20022-mcp` |\n| [`camt053-mcp`](https://github.com/sebastienrousseau/camt053-mcp) | ISO 20022 camt.05x bank statements: parse, validate, filter, reverse; MT94x migration; CBPR+ readiness | `pip install camt053-mcp` |\n| [`pain001-mcp`](https://github.com/sebastienrousseau/pain001-mcp) | Generate & validate ISO 20022 pain.001 payment-initiation files (v03–v12, pain.008, SEPA) with rulebook checks | `pip install pain001-mcp` |\n| [`reconcile-mcp`](https://github.com/sebastienrousseau/reconcile-mcp) | Reconcile ISO 20022 payments and statements; match initiations to their bank-side outcomes | `pip install reconcile-mcp` |\n| [`bankstatementparser-mcp`](https://github.com/sebastienrousseau/bankstatementparser-mcp) | Parse bank statements (MT940/MT942 and camt) into structured, agent-friendly data | `pip install bankstatementparser-mcp` |\n\nWhere the foundational servers each do one message job well and the readiness\ngateway composes them, **this server** owns the clearing profiles: it manages,\nvalidates, and serves the market-practice rule packs the rest of the suite\nlints against.\n\n## Install\n\n**iso20022-bank-profile-mcp** runs on macOS, Linux, and Windows and\nrequires **Python 3.10+** and **pip**. It pulls in the MCP SDK, `pydantic`,\nand `defusedxml` automatically — all published on PyPI.\n\n```sh\npython -m pip install iso20022-bank-profile-mcp\n```\n\nOr run it without installing, straight from PyPI, with\n[`uvx`](https://docs.astral.sh/uv/):\n\n```sh\nuvx iso20022-bank-profile-mcp\n```\n\n<details>\n<summary>Using an isolated virtual environment (recommended)</summary>\n\n```sh\npython -m venv venv\nsource venv/bin/activate        # macOS/Linux\nvenv\\Scripts\\activate           # Windows\npython -m pip install -U iso20022-bank-profile-mcp\n```\n</details>\n\n## Quick Start\n\nFor the 10-minute install → MCP client config → first conversation tutorial,\nsee [`docs/quickstart.md`](docs/quickstart.md).\n\nLaunch the server over stdio (the FastMCP default transport):\n\n```sh\niso20022-bank-profile-mcp\n```\n\nRegister it with any MCP client (e.g. Claude Desktop) by adding it to the\nclient's configuration:\n\n```json\n{\n  \"mcpServers\": {\n    \"iso20022-bank-profile\": { \"command\": \"iso20022-bank-profile-mcp\" }\n  }\n}\n```\n\nThe command speaks MCP on stdin/stdout — it is meant to be launched by an MCP\nclient, not used interactively. The agent can then call the tools below.\n\nYou can also invoke the tools in-process — without a transport — straight\nthrough the FastMCP instance. This mirrors what an agent receives over stdio;\neverything is local, so no other servers are needed:\n\n```python\nimport asyncio\n\nfrom iso20022_bank_profile_mcp import server\n\n\nasync def main() -> None:\n    async def call(name, args):\n        result = await server.server.call_tool(name, args)\n        # mcp 2.x returns a CallToolResult (use .content); 1.x returns\n        # the content list, or a (content, meta) tuple.\n        content = getattr(result, \"content\", None)\n        if content is None:\n            content = result[0] if isinstance(result, tuple) else result\n        return content[0].text if content else \"\"\n\n    # Which clearing profiles can I target?\n    print(await call(\"list_profiles\", {}))\n    # -> {\"profile_id\": \"...\", \"market_practice\": \"...\", \"rule_count\": ...}, ...\n\n    # Lint a payload against a profile: a CBPR+ address missing its town.\n    payload = \"<Document><PstlAdr><Ctry>DE</Ctry></PstlAdr></Document>\"\n    print(await call(\"lint_payload\",\n                     {\"payload_content\": payload, \"profile_id\": \"CBPR+\"}))\n    # -> {\"profile_id\": \"CBPR+\", \"is_compliant\": false,\n    #     \"findings\": [{\"code\": \"CBPR_MISSING_TOWN\", \"locator\": \"TwnNm\", ...}]}\n\n\nasyncio.run(main())\n```\n\n## Tools\n\nAll tools return JSON-serialisable data; on a domain, validation, or value\nerror they return an `{\"error\": ...}` payload rather than raising. Every tool\nis a pure, local, read-only, idempotent, closed-world lookup — no network, no\nsub-servers.\n\n- `list_profiles` — List the available clearing profiles as lightweight summaries (`profile_id`, `market_practice`, `tier`, `entitled`, `supported_messages`, `rule_count`). Use it to discover the `profile_id` values the other tools accept and see which ones the current caller is entitled to.\n- `get_profile` — Return one clearing profile in full, including its rule bodies. On a **premium** profile the caller must be entitled, otherwise it returns a `BP_NOT_ENTITLED` error (see [Open-core vs premium](#open-core-vs-premium)).\n- `lint_payload` — Evaluate a raw ISO 20022 payload against a clearing profile and return the findings (a compliant payload yields none). Like `get_profile`, a **premium** profile requires an entitlement or it returns `BP_NOT_ENTITLED`.\n- `validate_profile_definition` — Validate a bank-supplied profile / rule-pack definition supplied as raw JSON, confirming its shape and that every rule uses a known assertion verb.\n\n## HTTP transport & authentication\n\nstdio is the default and needs no authentication — one process per operator,\nlaunched by the client, no network surface. For **shared, multi-tenant\ndeployments** the server also speaks an optional streamable-HTTP transport:\n\n```sh\niso20022-bank-profile-mcp --transport=http --bind=127.0.0.1:8080\n```\n\n`--bind` defaults to `127.0.0.1:8080` (loopback-only), so exposing the server\nbeyond the host is an explicit opt-in (e.g. `--bind=0.0.0.0:8080`). The HTTP\ntransport **refuses to start without authentication** — it never serves an\nunauthenticated endpoint. Two auth modes apply, strongest first:\n\n- **OAuth 2.1 resource server (RFC 9728)** — set\n  `ISO20022_BANK_PROFILE_OAUTH_ISSUER` and\n  `ISO20022_BANK_PROFILE_OAUTH_AUDIENCE` (both required), with optional\n  `ISO20022_BANK_PROFILE_OAUTH_JWKS_URL` (defaults to\n  `<issuer>/.well-known/jwks.json`) and `ISO20022_BANK_PROFILE_OAUTH_SCOPES`.\n  Every request must carry `Authorization: Bearer <jwt>`; the token is\n  validated against the JWKS and its `iss` / `aud` / `exp` / `nbf` / required\n  scopes. Failures are rejected `401` / `403` with an RFC 9728\n  `WWW-Authenticate` challenge, and protected-resource metadata is served at\n  `/.well-known/oauth-protected-resource`. This server validates tokens from\n  your existing authorization server (Okta, Auth0, Entra ID, …); running the\n  authorization server is out of scope.\n\n  ```sh\n  ISO20022_BANK_PROFILE_OAUTH_ISSUER=https://auth.example.com \\\n  ISO20022_BANK_PROFILE_OAUTH_AUDIENCE=https://mcp.example.com/mcp \\\n    iso20022-bank-profile-mcp --transport=http --bind=0.0.0.0:8080\n  ```\n\n- **Static dev-mode token** — set `ISO20022_BANK_PROFILE_TOKEN` to a shared\n  secret; every request must then send `Authorization: Bearer <secret>`. This\n  is a single shared secret with no expiry and no scopes — intended for local\n  development, not production.\n\nAn optional `X-MCP-Tenant` request header is forwarded into the tool-visible\nrequest context for multi-tenant scoping. See\n[`docs/transport.md`](docs/transport.md) for the full setup.\n\n## How it fits the suite\n\nThis server is the **profile authority** for the ISO 20022 MCP Suite. The\nsibling [`iso20022-readiness-suite-mcp`](https://github.com/sebastienrousseau/iso20022-readiness-suite-mcp)\ngateway scores and remediates payments *against* clearing profiles; those\nprofiles are exactly what this server manages, validates, and serves. Aligning\non one profile source keeps the readiness gateway and any bank's own tooling\nevaluating a payment against the same market-practice rules.\n\nThe profile catalogue is extensible at the seam the whole suite shares. The\n`ProfileEngine` loads the open baseline from bundled JSON with\n`ProfileEngine.from_bundled()`, and exposes `ProfileEngine.register(profile)`\nto add (or replace) a profile at runtime. A **premium, bank-specific rule\npack** is the same shape as a bundled profile — a `ClearingProfile` with a\n`profile_id`, a `market_practice`, its `supported_messages`, and a list of\n`custom_rules` — so a deployment that embeds this server can register its\nlicensed packs and serve them alongside the open baseline without changing the\ntool surface. See [`docs/profiles.md`](docs/profiles.md) for the rule\nmini-language and the `register()` seam.\n\n## Open-core vs premium\n\nThe server is **open core**: the baseline scheme profiles and the profile\nengine are open source and always available. Higher-tier, institution-specific\ncapabilities are commercial add-ons that plug into the same profile-engine seam\n(the engine already exposes a `register()` hook for runtime-loaded rule packs).\n\n| Capability | Tier |\n|---|---|\n| Profile engine + rule mini-language | **Open Source** |\n| Baseline scheme profiles (Generic, CBPR+, SEPA_Instant, FedNow) | **Open Source** |\n| Entitlement gate for premium profiles (tier, scopes, allowlist) | **Open Source** |\n| Bank-specific / proprietary scheme rule packs | **Paid** |\n| Stateful profile-version history & audit logs | **Paid** |\n\nNothing in the open-source tier is time-limited or feature-gated.\n\n### How the entitlement gate works\n\nEvery clearing profile carries a `tier`: `\"open\"` (the baseline profiles —\nunrestricted and always accessible) or `\"premium\"` (a licensed rule pack). A\nbundled premium **sample** profile, `ACME_Premium`, ships so you can exercise\nthe gate. `list_profiles` reports each profile's `tier` and a per-caller\n`entitled` boolean; `get_profile` and `lint_payload` on a **premium** profile\nreturn a `BP_NOT_ENTITLED` error unless the caller is entitled.\n\nEntitlement is granted by **either** of two independent sources (ORed):\n\n- **OAuth scope** (HTTP transport) — a token bearing the `profile:premium`\n  scope is entitled to every premium profile; a token bearing\n  `profile:<profile_id>` is entitled to just that one.\n- **Environment allowlist** (stdio / dev) — `ISO20022_BANK_PROFILE_ENTITLEMENTS`\n  lists the premium `profile_id` values (comma- or space-separated) the\n  operator is licensed for; `*` grants all of them.\n\n```sh\n# stdio: license the ACME_Premium sample pack for this process\nISO20022_BANK_PROFILE_ENTITLEMENTS=ACME_Premium iso20022-bank-profile-mcp\n```\n\nThe gate ships in this release; the premium **rule packs** themselves (and\nstateful version history / audit logs) remain a paid, out-of-tree concern.\nSee [`docs/profiles.md`](docs/profiles.md) for the full entitlement model.\n\n## When not to use iso20022-bank-profile-mcp\n\n- **You have no MCP client.** This server only makes sense paired with an\n  MCP-aware host (Claude Desktop, the IDE plugins, an agent framework).\n- **You need structural XSD validation or message generation.** Those live in\n  the foundational suite servers (`iso20022-mcp`, `camt053-mcp`,\n  `pain001-mcp`). This server evaluates market-practice rules *above* the XSD;\n  it does not parse, generate, or structurally validate messages.\n- **You want an end-to-end readiness score and remediation.** That is the job\n  of `iso20022-readiness-suite-mcp`, which consumes these profiles. Use it if\n  you want scoring, remediation, and bank-response simulation composed\n  together.\n- **You need a long-lived network service without auth.** stdio is the default\n  (one process per operator, no network surface); the optional\n  [HTTP transport](#http-transport--authentication) exists for shared,\n  multi-tenant deployments but always requires authentication (OAuth 2.1 or a\n  static dev-mode token) — it will not serve an unauthenticated endpoint.\n- **You need streaming responses.** Tool calls return whole values, not\n  streams.\n\n## Development\n\n**iso20022-bank-profile-mcp** uses [Poetry](https://python-poetry.org/) and\n[mise](https://mise.jdx.dev/).\n\n```bash\ngit clone https://github.com/sebastienrousseau/iso20022-bank-profile-mcp.git && cd iso20022-bank-profile-mcp\nmise install\npoetry install\npoetry shell\n```\n\n> **Note:** the server is fully local and closed-world, so the test suite runs\n> with nothing else installed. See [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\nA `Makefile` orchestrates the quality gates (kept in lockstep with CI):\n\n```bash\nmake check        # all gates (REQUIRED before commit): lint + type-check + test\nmake test         # pytest (100% line + branch coverage)\nmake lint         # ruff + black\nmake type-check   # mypy --strict\nmake security     # bandit\n```\n\n## Security\n\n`iso20022-bank-profile-mcp` returns errors as data — every tool catches the\ndocumented domain, validation, and value errors and returns an\n`{\"error\": ...}` envelope; it never propagates raw exceptions to the MCP\nclient. Payloads reached through the clearing-profile engine are parsed with\n`defusedxml` only (no XXE / billion-laughs), and the server opens no network\nsockets. Reporting practice, supported versions, the attack surface, and the\nfull supply-chain posture (SLSA L3 provenance, PEP 740 attestations, SBOMs, and\nthe NIST SP 800-218 SSDF practice mapping) are documented in\n[`SECURITY.md`](SECURITY.md). Vulnerabilities go via GitHub Private\nVulnerability Reporting, not public issues.\n\n## Documentation\n\n- [`README.md`](README.md) — this file\n- [`CHANGELOG.md`](CHANGELOG.md) — release notes\n- [`SECURITY.md`](SECURITY.md) — disclosure + supported versions\n- [`SUPPORT.md`](SUPPORT.md) — how to get help\n- [`ROADMAP.md`](ROADMAP.md) — what's shipped (HTTP transport, premium entitlement gating) and what's next (richer bank rule packs)\n- [`MAINTAINERS.md`](MAINTAINERS.md) — who can merge\n- [`docs/quickstart.md`](docs/quickstart.md) — 10-minute install → first conversation\n- [`docs/profiles.md`](docs/profiles.md) — the clearing profiles, the rule mini-language, premium rule packs, and the entitlement gate\n- [`docs/transport.md`](docs/transport.md) — the optional HTTP transport and OAuth 2.1 setup\n- [`glama.json`](glama.json) — Glama directory manifest\n\n---\n\n## MCP Registry\n\n`mcp-name: io.github.sebastienrousseau/iso20022-bank-profile-mcp`\n\n---\n\n## License\n\nLicensed under the [Apache License, Version 2.0][01]. Any contribution submitted\nfor inclusion shall be licensed as above, without additional terms.\n\n## Contributing\n\nContributions are welcome — see the [contributing instructions][04]. Thanks to\nall [contributors][05].\n\n## Acknowledgements\n\nBuilt alongside the foundational servers of the ISO 20022 MCP Suite and the\n[Model Context Protocol][mcp] Python SDK.\n\n[01]: https://opensource.org/license/apache-2-0/\n[04]: https://github.com/sebastienrousseau/iso20022-bank-profile-mcp/blob/main/CONTRIBUTING.md\n[05]: https://github.com/sebastienrousseau/iso20022-bank-profile-mcp/graphs/contributors\n[07]: https://pypi.org/project/iso20022-bank-profile-mcp/\n[mcp]: https://modelcontextprotocol.io\n[docs-badge]: https://img.shields.io/badge/Docs-iso20022--bank--profile-blue?style=for-the-badge\n[docs-url]: https://sebastienrousseau.github.io/iso20022-bank-profile-mcp/\n[license-badge]: https://img.shields.io/pypi/l/iso20022-bank-profile-mcp?style=for-the-badge\n[pypi-badge]: https://img.shields.io/pypi/v/iso20022-bank-profile-mcp?style=for-the-badge\n[python-versions-badge]: https://img.shields.io/pypi/pyversions/iso20022-bank-profile-mcp.svg?style=for-the-badge\n[quality-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/iso20022-bank-profile-mcp/ci.yml?branch=main&label=Quality&style=for-the-badge\n[quality-url]: https://github.com/sebastienrousseau/iso20022-bank-profile-mcp/actions/workflows/ci.yml\n[scorecard-badge]: https://api.scorecard.dev/projects/github.com/sebastienrousseau/iso20022-bank-profile-mcp/badge?style=for-the-badge\n[scorecard-url]: https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/iso20022-bank-profile-mcp\n[tests-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/iso20022-bank-profile-mcp/ci.yml?branch=main&label=Tests&style=for-the-badge\n[tests-url]: https://github.com/sebastienrousseau/iso20022-bank-profile-mcp/actions/workflows/ci.yml\n",
  "bytes": 21101,
  "sha": "8f0066267b8c344fa9f4393bbb235437e76a5ddcc0755065a7de871fecabc8e4",
  "repo_slug": "sebastienrousseau/iso20022-bank-profile-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_sebastienrousseau_iso20022_ban_b6e82809/readme"
}