# `ExMCP.Server.HandlerServer`
[🔗](https://github.com/azmaveth/ex_mcp/blob/v1.0.0/lib/ex_mcp/server/handler_server.ex#L1)

Transport-aware process for `ExMCP.Server.Handler` modules.

This module runs a handler module behind the MCP transports that need a
server process, including the in-memory test transport.

## Usage

    # Handler module implementing ExMCP.Server.Handler
    defmodule MyHandler do
      use ExMCP.Server.Handler

      @impl true
      def handle_initialize(params, state) do
        {:ok, %{
          protocolVersion: "2025-03-26",
          serverInfo: %{name: "test-server", version: "1.0.0"},
          capabilities: %{tools: %{}}
        }, state}
      end

      @impl true
      def handle_list_tools(_cursor, state) do
        tools = [
          %{
            name: "ping",
            description: "Simple ping tool",
            inputSchema: %{type: "object", properties: %{}}
          }
        ]
        {:ok, tools, nil, state}
      end
    end

    # Start the server
    {:ok, server} = ExMCP.Server.HandlerServer.start_link(transport: :test, handler: MyHandler)

# `handler_module`

```elixir
@type handler_module() :: module()
```

# `state`

```elixir
@type state() :: %{
  handler_module: handler_module(),
  handler_state: any(),
  transport: any(),
  transport_state: any(),
  protocol_version: String.t() | nil,
  validation_state: %{
    seen_request_ids: MapSet.t(String.t() | integer()),
    max_request_ids: pos_integer(),
    protocol_version: String.t() | nil
  },
  protocol_mode: ExMCP.Types.protocol_mode() | nil,
  connection_era: :legacy | :modern | nil,
  instructions: String.t() | nil,
  request_state: keyword() | nil,
  endpoint: String.t() | nil,
  principal_id: String.t() | nil,
  tenant_id: String.t() | nil,
  replay_cache: module() | {module(), keyword()} | nil,
  require_replay_protection: boolean(),
  pending_requests: map(),
  cancelled_requests: MapSet.t(),
  cancellation_tracker: module(),
  subscriptions: map(),
  subscription_options: keyword()
}
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `start_link`

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

Starts a handler-based server.

## Options

* `:handler` - Module implementing `ExMCP.Server.Handler` behaviour (required)
* `:transport` - Transport type (`:test`, `:stdio`, `:http`, etc.)
* `:handler_args` - Optional term passed to `handler.init/1` (default: `[]`)
* `:cancellation_tracker` - Module implementing
  `ExMCP.Server.CancellationTracker` used to propagate
  `notifications/cancelled` into handler state
  (default: `ExMCP.Server.CancellationTracker.Default`)
* `:max_request_ids` - Maximum number of distinct client request IDs retained
  for this server process (default: `10_000`). Once reached, new request IDs
  fail closed while already-seen IDs continue to be rejected as duplicates.
* Other options are passed to the transport

---

*Consult [api-reference.md](api-reference.md) for complete listing*
