ExMCP.Transport behaviour (ex_mcp v0.1.0)

View Source

Behaviour for MCP transport implementations.

A transport is responsible for sending and receiving MCP protocol messages over a specific communication channel (stdio, SSE, WebSocket, etc).

Implementing a Transport

To implement a custom transport, create a module that implements all the callbacks defined in this behaviour:

defmodule MyTransport do
  @behaviour ExMCP.Transport

  @impl true
  def connect(opts) do
    # Establish connection
    {:ok, state}
  end

  @impl true
  def send_message(message, state) do
    # Send the message
    {:ok, state}
  end

  @impl true
  def receive_message(state) do
    # Receive a message (blocking)
    {:ok, message, state}
  end

  @impl true
  def close(state) do
    # Clean up
    :ok
  end
end

Summary

Callbacks

Closes the transport connection.

Establishes a connection for the transport.

Optional callback to check if the transport is still connected.

Receives a message from the transport.

Sends a message through the transport.

Functions

Helper to get the appropriate transport module for an atom identifier.

Types

message()

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

opts()

@type opts() :: keyword()

state()

@type state() :: any()

Callbacks

close(state)

@callback close(state()) :: :ok

Closes the transport connection.

Should clean up any resources and return :ok.

connect(opts)

@callback connect(opts()) :: {:ok, state()} | {:error, any()}

Establishes a connection for the transport.

Options are transport-specific. Should return {:ok, state} where state contains any necessary connection information.

connected?(state)

(optional)
@callback connected?(state()) :: boolean()

Optional callback to check if the transport is still connected.

Default implementation always returns true.

receive_message(state)

@callback receive_message(state()) :: {:ok, message(), state()} | {:error, any()}

Receives a message from the transport.

This should block until a message is available. Returns {:ok, message, new_state} where message is a JSON string.

send_message(message, state)

@callback send_message(message(), state()) :: {:ok, state()} | {:error, any()}

Sends a message through the transport.

The message will be a JSON-encoded string. Should return {:ok, new_state} on success.

Functions

get_transport(module)

@spec get_transport(:stdio | :sse | :websocket | module()) :: module()

Helper to get the appropriate transport module for an atom identifier.