Hermes.Server.Session (hermes_mcp v0.10.4)
Manages state for the Hermes MCP server base implementation.
This module provides a structured representation of server state during the MCP lifecycle, including initialization status, protocol negotiation, and server capabilities.
State Structure
Each server state includes:
protocol_version
: Negotiated MCP protocol versionframe
: Server frame (similar to LiveView socket)initialized
: Whether the server has completed initializationclient_info
: Client information received during initializationclient_capabilities
: Client capabilities received during initialization
Summary
Functions
Returns a specification to start this module under a supervisor.
Removes a completed request from tracking.
Retrieves the current state of a session.
Gets all pending requests for a session.
Checks if a request is currently pending.
Guard to check if a session has been initialized.
Marks the session as initialized.
Creates a new server state with the given options.
Updates the log level.
Starts a new session agent with initial state.
Tracks a new pending request in the session.
Updates state after successful initialization handshake.
Types
@type t() :: %Hermes.Server.Session{ client_capabilities: map() | nil, client_info: map() | nil, id: String.t() | nil, initialized: boolean(), log_level: String.t(), name: GenServer.name() | nil, pending_requests: %{ required(String.t()) => %{started_at: integer(), method: String.t()} }, protocol_version: String.t() | nil }
Functions
Returns a specification to start this module under a supervisor.
See Supervisor
.
@spec complete_request(GenServer.name(), String.t()) :: map() | nil
Removes a completed request from tracking.
Parameters
session
- The session agent name or PIDrequest_id
- The request ID to remove
Returns
The request info if found, nil otherwise.
Examples
iex> Session.complete_request(session, "req_123")
%{started_at: 1234567890, method: "tools/call"}
@spec get(GenServer.name()) :: t()
Retrieves the current state of a session.
Parameters
session
- The session agent name or PID
Returns
The current session state as a %Session{}
struct.
Examples
iex> session_state = Session.get(session_name)
%Session{initialized: true, protocol_version: "2025-03-26"}
@spec get_pending_requests(GenServer.name()) :: map()
Gets all pending requests for a session.
Parameters
session
- The session agent name or PID
Examples
iex> Session.get_pending_requests(session)
%{"req_123" => %{started_at: 1234567890, method: "tools/call"}}
@spec has_pending_request?(GenServer.name(), String.t()) :: boolean()
Checks if a request is currently pending.
Parameters
session
- The session agent name or PIDrequest_id
- The request ID to check
Examples
iex> Session.has_pending_request?(session, "req_123")
true
Guard to check if a session has been initialized.
Examples
iex> session = %Session{initialized: true}
iex> is_initialized(session)
true
@spec mark_initialized(GenServer.name()) :: :ok
Marks the session as initialized.
@spec new(Enumerable.t()) :: t()
Creates a new server state with the given options.
Parameters
opts
- Map containing the initialization options
@spec set_log_level(GenServer.name(), String.t()) :: :ok
Updates the log level.
@spec start_link(keyword()) :: Agent.on_start()
Starts a new session agent with initial state.
@spec track_request(GenServer.name(), String.t(), String.t()) :: :ok
Tracks a new pending request in the session.
Parameters
session
- The session agent name or PIDrequest_id
- The unique request IDmethod
- The MCP method being called
Examples
iex> Session.track_request(session, "req_123", "tools/call")
:ok
@spec update_from_initialization(GenServer.name(), String.t(), map(), map()) :: :ok
Updates state after successful initialization handshake.
This function:
- Sets the negotiated protocol version
- Stores client information and capabilities
- Marks the server as initialized
Parameters
state
- The current server stateprotocol_version
- The negotiated protocol versionclient_info
- Client information from the initialize requestclient_capabilities
- Client capabilities from the initialize request
Examples
iex> client_info = %{"name" => "hello", "version" => "1.0.0"}
iex> capabilities = %{"sampling" => %{}}
iex> Hermes.Server.Session.update_from_initialization(session, "2025-03-26", client_info, capabilities)
:ok