Anubis.Transport.Behaviour behaviour (anubis_mcp v2.2.0)

Copy Markdown

Defines the behaviour that all transport implementations must follow.

Two kinds of callbacks:

  • Process callbacks (start_link/1, send_message/3, shutdown/1) — the GenServer-oriented I/O contract, required.
  • Functional callbacks (transport_init/1, parse/2, encode/2, extract_metadata/2) — pure message framing used when the transport owns a parse state (newline-delimited JSON, SSE chunks, HTTP bodies). Optional; the client checks function_exported?/3 before using them.

Summary

Callbacks

Encode an MCP message map for this transport's wire format.

Extract transport-specific metadata from raw input.

Parse raw input into decoded MCP message(s).

Returns the list of MCP protocol versions supported by this transport.

Initialize transport-specific state (parse options, configure connection).

Types

message()

@type message() :: String.t()

The JSON-RPC message encoded

raw_message()

@type raw_message() :: binary()

reason()

@type reason() :: term() | Anubis.MCP.Error.t()

t()

@type t() :: GenServer.server()

transport_state()

@type transport_state() :: term()

Callbacks

encode(message, transport_state)

(optional)
@callback encode(message :: map(), transport_state()) ::
  {:ok, raw_message(), transport_state()} | {:error, term()}

Encode an MCP message map for this transport's wire format.

Returns the encoded binary ready to be sent.

extract_metadata(raw_input, transport_state)

(optional)
@callback extract_metadata(raw_input :: term(), transport_state()) :: map()

Extract transport-specific metadata from raw input.

For HTTP, this extracts session_id from headers, request context, etc. For STDIO, this returns basic process metadata.

parse(arg1, transport_state)

(optional)
@callback parse(raw_message() | map(), transport_state()) ::
  {:ok, [map()], transport_state()} | {:error, term()}

Parse raw input into decoded MCP message(s).

For STDIO, raw input is newline-delimited JSON. For HTTP, raw input is a JSON body string or already-parsed map. For SSE, raw input is SSE event data.

send_message(t, message, list)

@callback send_message(t(), message(), [opt]) :: :ok | {:error, reason()}
when opt: {:timeout, pos_integer()} | {:session_id, String.t()}

shutdown(t)

@callback shutdown(t()) :: :ok | {:error, reason()}

start_link(keyword)

@callback start_link(keyword()) :: GenServer.on_start()

supported_protocol_versions()

@callback supported_protocol_versions() :: [String.t()] | :all

Returns the list of MCP protocol versions supported by this transport.

Examples

iex> MyTransport.supported_protocol_versions()
["2025-03-26", "2025-06-18"]

transport_init(keyword)

(optional)
@callback transport_init(keyword()) :: {:ok, transport_state()} | {:error, term()}

Initialize transport-specific state (parse options, configure connection).