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

Single MCP method table for handler modules invoked with their own state.

`ExMCP.Server.HandlerServer` (test/BEAM transports) and
`ExMCP.Server.StdioServer` both drive an `ExMCP.Server.Handler` module by
calling its callbacks with the handler state and turning the return value
into a JSON-RPC response. They used to carry two independently maintained
copies of that table, which drifted: stdio never implemented
`completion/complete`, `resources/subscribe`, `roots/list`,
`logging/setLevel` or the task methods, and the two copies normalized tool
results differently.

This module owns the table. Transports keep their own framing (stdout lines
vs. transport `send_message/2`), batching, and cancellation bookkeeping, and
delegate callback invocation plus result shaping here. Shaping itself lives
in `ExMCP.Server.ResultNormalizer`, which the HTTP message processor also
shares, so every transport agrees
on tool-result shape and on which error detail is safe to return.

## Return value

* `{:response, response_map, new_handler_state}` for requests
* `{:notification, new_handler_state}` for notifications (no response)

Callbacks that `ExMCP.Server.Handler` marks optional are probed with
`function_exported?/3`; a handler that does not implement one answers
`-32601 Method not found`.

# `handler_state`

```elixir
@type handler_state() :: term()
```

# `result`

```elixir
@type result() ::
  {:response, map(), handler_state()} | {:notification, handler_state()}
```

# `dispatch`

```elixir
@spec dispatch(map(), module(), handler_state()) :: result()
```

Dispatches a decoded JSON-RPC request or notification to `handler_module`.

# `known_method?`

```elixir
@spec known_method?(String.t()) :: boolean()
```

Whether `method` is part of the shared MCP method table.

# `methods`

```elixir
@spec methods() :: [String.t()]
```

Returns the list of MCP methods handled by this dispatcher.

# `tool_arguments`

```elixir
@spec tool_arguments(map()) :: map()
```

Builds the argument map handed to `c:ExMCP.Server.Handler.handle_call_tool/3`.

Request-level `_meta` (which carries `progressToken`) lives beside
`arguments` in the JSON-RPC params, but `ExMCP.Server.Handler` documents it
as reachable from the arguments map, so it is merged in here. Arguments that
already carry their own `_meta` win.

---

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