Behaviour for session controllers.
Summary
Callbacks
Called by GenMCP.Suite or custom implementations when a new session is
created during initialization.
Called by GenMCP.Suite or custom implementations when a session is being
deleted.
Retrieves an existing stored session.
Called by GenMCP.Suite or custom implementations when the session process
receives an info message.
Called by GenMCP.Suite or custom implementations when the client closes or
opens a listener channel.
Called by GenMCP.Suite or custom implementations when a session is restored
from stored data.
Called by GenMCP.Suite or custom implementations when a session is
initialized and before the session timeout time is reached.
Types
@type arg() :: term()
@type channel() :: GenMCP.Mux.Channel.t()
@type restore_data() :: term()
@type session_id() :: String.t()
@type session_state() :: term()
Callbacks
@callback create( session_id(), GenMCP.Suite.PersistedClientInfo.normalized(), channel(), arg() ) :: {:ok, channel(), session_state()} | {:stop, reason :: term()}
Called by GenMCP.Suite or custom implementations when a new session is
created during initialization.
Returns the updated channel new assigns and the session state.
@callback delete(session_id(), session_state()) :: term()
Called by GenMCP.Suite or custom implementations when a session is being
deleted.
The return value is not checked. If the callback exits or raises, the session process will be terminated immediately. Failure to delete persisted data will not be retried and the session may be restore-able again, depending on your implementation.
@callback fetch(session_id :: String.t(), channel(), arg()) :: {:ok, restore_data()} | {:error, :not_found}
Retrieves an existing stored session.
A channel is given to be able to compare authenticated channels with session ownership, but the channel cannot be altered at this step.
The resoted data will be passed to restore/3 in the execution context of
the session process.
@callback handle_info(info :: term(), channel(), session_state()) :: {:noreply, channel(), session_state()} | {:noreply, session_state()} | {:stop, reason :: term()}
Called by GenMCP.Suite or custom implementations when the session process
receives an info message.
Once created or restored, the original arg from the :session_controller
option given to server implementation is not carried anymore. Data that must
be available at all time should be added into the session_state.
Returns the updated session state and optionally the channel updated with assigns.
To not be fighting about muscle memory, callback implementations must return
:noreply tuples instead of :ok tuples!
@callback listener_change(channel(), session_state()) :: {:ok, channel(), session_state()} | {:ok, session_state()}
Called by GenMCP.Suite or custom implementations when the client closes or
opens a listener channel.
In the case of a new open channel, all previous assigns are lost.
A listener channel is typically representing the HTTP request streaming from GET request to the MCP endpoint, used to send notifications and requests to the client that are not related to any client request.
Channels can be open and closed at any time by the client. GenMCP will only
allow one listener channel to be open at the same time. When the channel is
closed by the client, this callback will be called with a channel whose
status property is :closed and :client property is nil (instead of the
HTTP request controller pid).
This callback is the right place to setup/teardown subscriptions to pubsub, GenStage, etc.
Returns the updated session state and optionally the channel updated with assigns.
Sequence diagram
To initialize the session controller with a closed channel after session
initialization, this callback is also called immediately after the
InitializeRequest is handled by the MCP server. In general this will happen
before the InitializedNotification is received, so before the update/4
callback is called, but it may depend on the client implementation.
@callback restore(restore_data(), channel(), arg()) :: {:ok, GenMCP.Suite.PersistedClientInfo.normalized(), channel(), session_state()} | {:stop, reason :: term()}
Called by GenMCP.Suite or custom implementations when a session is restored
from stored data.
Receives the return value of fetch/3 as session_state.
Returns the persisted client information, the updated channel with any restored assigns, and the session state.
@callback update( session_id(), GenMCP.Suite.PersistedClientInfo.normalized(), channel(), arg() ) :: {:ok, channel(), session_state()} | {:stop, reason :: term()}
Called by GenMCP.Suite or custom implementations when a session is
initialized and before the session timeout time is reached.
Returns the updated channel new assigns and the session state.