Python API reference

The importable Python surface: the generation engine the tools wrap, and the server module whose handlers can be called in-process without a transport.

camt-exceptions: ISO 20022 Exceptions & Investigations message generation.

Generation engine

Generate and validate ISO 20022 Exceptions & Investigations (E&I) messages.

This is the camt counterpart to the generation engines elsewhere in the suite: each supported message type bundles its official XSD plus a Jinja2 template.xml; generate_message() renders a record into XML and validate_xml() checks any XML against the bundled schema.

Currently supported:

  • camt.056.001.12 – FI to FI Payment Cancellation Request (recall or cancel a previously sent payment, e.g. a duplicate or erroneous transfer).

Additional E&I messages (camt.029 resolution of investigation, camt.026 unable to apply, camt.027 claim non-receipt, camt.087 request to modify) plug in by dropping their XSD + template.xml alongside and registering them in MESSAGE_TYPES.

class camt_exceptions.generator.MessageSpec(message_type, name, required)[source]

Bases: object

Static description of one supported E&I message type.

Parameters:
camt_exceptions.generator.generate_message(message_type, record)[source]

Render a validated E&I message to XML.

Parameters:
  • message_type (str) – e.g. "camt.056.001.12".

  • record (dict[str, Any]) – the message fields (see get_required_fields() for the required keys; transactions is a list of per-transaction dicts).

Return type:

str

Returns:

The rendered ISO 20022 XML as a string.

Raises:

ValueError – unknown message type, a missing required field, or output that fails XSD validation.

camt_exceptions.generator.get_required_fields(message_type)[source]

Return the required top-level fields for a message type.

Return type:

list[str]

Parameters:

message_type (str)

camt_exceptions.generator.list_message_types()[source]

Return every supported E&I message type and its human name.

Return type:

list[dict[str, str]]

camt_exceptions.generator.validate_xml(message_type, xml)[source]

Validate raw XML against a message type’s bundled XSD.

Return type:

dict[str, Any]

Returns:

{"message_type": ..., "is_valid": bool, "errors": [...]} – never raises on a validation failure or on malformed XML (only on an unknown message type).

Parameters:
  • message_type (str)

  • xml (str)

Tool, prompt and resource module

Every tool, the prompt and both resources are plain functions registered on the server object at import time, so they can be called in-process without a transport.

Model Context Protocol (MCP) server for ISO 20022 Exceptions & Investigations.

Exposes generation and validation of E&I camt messages – starting with camt.056 (FI to FI Payment Cancellation Request) – as MCP tools. Each tool is a thin wrapper over camt_exceptions.generator; tools return JSON-serializable data and, on a ValueError, return an {"error": ...} payload rather than raising.

Launching the server:
  • As a console script:

    camt-exceptions-mcp
    
  • In an MCP client config (e.g. Claude Desktop):

    {
      "mcpServers": {
        "camt-exceptions": {
          "command": "camt-exceptions-mcp"
        }
      }
    }
    

stdio by default; --transport streamable-http or --transport sse listens on --host/--port instead. See camt_exceptions._cli.

camt_exceptions.server.build_investigation_message(message_type='camt.056.001.12')[source]

Guide the caller through building a validated E&I camt message.

Return type:

str

Parameters:

message_type (Annotated[str, FieldInfo(annotation=NoneType, required=True, description="An E&I message type, e.g. 'camt.056.001.12' (see list_message_types).")])

camt_exceptions.server.generate_message(message_type, record)[source]

Generate a validated E&I XML message.

Return type:

dict[str, Any]

Parameters:
  • message_type (Annotated[str, FieldInfo(annotation=NoneType, required=True, description="An E&I message type, e.g. 'camt.056.001.12' (see list_message_types).")])

  • record (Annotated[dict[str, Any], FieldInfo(annotation=NoneType, required=True, description='Message fields; see get_required_fields.')])

camt_exceptions.server.get_required_fields(message_type)[source]

Return the required fields for a message type.

Return type:

dict[str, Any]

Parameters:

message_type (Annotated[str, FieldInfo(annotation=NoneType, required=True, description="An E&I message type, e.g. 'camt.056.001.12' (see list_message_types).")])

camt_exceptions.server.list_message_types()[source]

List supported E&I message types.

Return type:

dict[str, Any]

camt_exceptions.server.main(argv=None)[source]

Run the E&I MCP server (the camt-exceptions-mcp entry point).

stdio by default; --transport streamable-http or --transport sse listens on --host/--port instead. See camt_exceptions._cli.

Parameters:

argv (list[str] | None) – Command-line arguments; None reads sys.argv[1:].

Return type:

None

camt_exceptions.server.message_types_resource()[source]

Expose the supported E&I message types as a JSON resource.

Return type:

str

camt_exceptions.server.required_fields_resource(message_type)[source]

Expose a message type’s required fields as a JSON resource.

Return type:

str

Parameters:

message_type (str)

camt_exceptions.server.validate_xml(message_type, xml)[source]

Validate XML against a message type’s XSD.

Return type:

dict[str, Any]

Parameters:
  • message_type (Annotated[str, FieldInfo(annotation=NoneType, required=True, description="An E&I message type, e.g. 'camt.056.001.12' (see list_message_types).")])

  • xml (Annotated[str, FieldInfo(annotation=NoneType, required=True, description='Raw ISO 20022 XML to validate.')])

Transports and command line

One command line for the three MCP transports.

Every server in the suite is started the same way:

<server>                                   # stdio, for a client that spawns it
<server> --transport streamable-http       # HTTP on 127.0.0.1:8000, path /mcp
<server> --transport sse --port 8001       # the older HTTP+SSE transport

Over streamable HTTP the SDK speaks both current protocol revisions on one endpoint: 2026-07-28 (stateless, server/discover, per-request _meta) and 2025-11-25 (initialize handshake, Mcp-Session-Id). Responses stream as server-sent events; a GET on the same path opens the server-to-client event stream. --transport sse serves the 2024-11-05 HTTP+SSE transport for clients that still expect it.

The listener binds the loopback interface unless told otherwise. There is no authentication here: put the server behind a gateway you trust before binding a routable address.

This module holds the transport dispatch; the flags that drive it live in _cli. Both files are copied verbatim into every server of the suite and work on mcp 1.x and 2.x.

camt_exceptions._transports.run(server, transport='stdio', host='127.0.0.1', port=8000)[source]

Serve server over transport; returns when the server stops.

Raises:

ValueError – If transport is not one of TRANSPORTS, or port is outside 1-65535.

Return type:

None

Parameters:

The command line every server in the suite shares.

serve is the body of each main(): it parses --transport, --host, --port and --version and hands the result to _transports.run(). Flag names, defaults and help text live here and nowhere else, so the suite is started and documented the same way.

Copied verbatim into every server of the suite.

camt_exceptions._cli.add_arguments(parser)[source]

Add --transport, --host and --port to parser.

Return type:

None

Parameters:

parser (ArgumentParser)

camt_exceptions._cli.serve(server, argv, prog, version)[source]

Parse argv and run server: the body of every main().

Return type:

None

Parameters: