Anubis.Server.Session (anubis_mcp v1.14.0)

Copy Markdown

Per-client MCP session process.

Each Session is a GenServer that manages the lifecycle of a single MCP client connection. It handles protocol initialization, request/notification dispatch, server-initiated requests (sampling, roots), and session persistence.

Sessions are created by the transport layer (STDIO creates one at startup, HTTP transports create them dynamically via Anubis.Server.Supervisor). Transports deliver client messages through the dispatcher contract defined in Anubis.Server.Transport.Session.

Summary

Functions

Auto-initializes a session without a client initialize handshake.

Starts a Session process linked to the current process.

Types

t()

@type t() :: %{
  session_id: String.t(),
  server_module: module(),
  protocol_version: String.t() | nil,
  protocol_module: module() | nil,
  initialized: boolean(),
  client_info: map() | nil,
  client_capabilities: map() | nil,
  init_meta: map(),
  log_level: String.t() | nil,
  frame: Anubis.Server.Frame.t(),
  server_info: map(),
  capabilities: map(),
  instructions: String.t() | nil,
  supported_versions: [String.t()],
  transport: %{layer: module(), name: GenServer.name()},
  registry: module(),
  session_idle_timeout: pos_integer(),
  expiry_timer: reference() | nil,
  pending_requests: %{
    required(String.t()) => %{started_at: integer(), method: String.t()}
  },
  server_requests: %{
    required(String.t()) => %{method: String.t(), timer_ref: reference()}
  },
  timeout: pos_integer(),
  task_supervisor: GenServer.name(),
  task_store: Anubis.Server.Session.Tasks.store() | nil,
  tasks: %{required(String.t()) => Anubis.Server.Session.Tasks.task_runtime()},
  task_refs: %{required(reference()) => String.t()},
  in_flight: Anubis.Server.Session.Scheduler.in_flight() | nil,
  request_queue: :queue.queue(Anubis.Server.Session.Scheduler.queued_request()),
  deferred_callbacks:
    :queue.queue(Anubis.Server.Session.Scheduler.deferred_callback())
}

Functions

auto_initialize(session)

@spec auto_initialize(GenServer.server()) :: :ok | {:error, term()}

Auto-initializes a session without a client initialize handshake.

This is used when a client sends a non-initialize request to an expired or unknown session. Instead of returning 404, the server can create a new session and auto-initialize it so the request can be processed transparently.

Uses the server's latest supported protocol version and synthetic client info (%{"name" => "auto-recovered", "version" => "unknown"}). Server implementations should not rely on this identity for client-specific decisions.

auto_initialize(session, transport_context)

@spec auto_initialize(GenServer.server(), map() | nil) :: :ok | {:error, term()}

get_schema(atom)

parse_options(data)

parse_options!(data)

start_link(opts)

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

Starts a Session process linked to the current process.

Options

  • :session_id — unique session identifier (required)
  • :server_module — the MCP server module implementing Anubis.Server (required)
  • :name — GenServer registration name (required)
  • :transport — transport configuration [layer: module, name: name] (required)
  • :task_supervisor — name of the Task.Supervisor for async work (required)
  • :registry — session registry module (default: Anubis.Server.Registry)
  • :session_idle_timeout — idle timeout in ms before session expires (default: 30 min)
  • :timeout — request timeout in ms (default: 30s)