Packages
claude_code
0.35.0
0.36.5
0.36.4
0.36.3
0.36.2
0.36.1
0.36.0
0.35.0
0.34.0
0.33.1
0.32.2
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.1
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Claude Agent SDK for Elixir – Build AI agents with Claude Code
Current section
Files
Jump to
Current section
Files
lib/claude_code/mcp/router.ex
defmodule ClaudeCode.MCP.Router do
@moduledoc """
Dispatches JSONRPC requests to in-process MCP tool server modules.
Handles the MCP protocol methods (`initialize`, `tools/list`, `tools/call`)
by routing to the appropriate tool module via the MCP backend.
This module is called by the adapter when it receives an `mcp_message`
control request from the CLI for a `type: "sdk"` server.
"""
alias Anubis.MCP.Error
alias ClaudeCode.MCP.Backend.Anubis, as: Backend
@doc """
Handles a JSONRPC request for the given tool server module.
Returns a JSONRPC response map ready for JSON encoding.
## Parameters
* `server_module` - A module that uses `ClaudeCode.MCP.Server` and
exports `__tool_server__/0`
* `message` - A decoded JSONRPC request map with `"method"` key
* `assigns` - Optional map of assigns passed to tools
(available to tools that define `execute/2` via `frame.assigns`)
## Supported Methods
* `"initialize"` - Returns protocol version, capabilities, and server info
* `"notifications/initialized"` - Acknowledges initialization (returns empty result)
* `"tools/list"` - Returns all registered tools with their schemas
* `"tools/call"` - Dispatches to the named tool's `execute/2` callback
## Examples
iex> message = %{"jsonrpc" => "2.0", "id" => 1, "method" => "initialize", "params" => %{}}
iex> Router.handle_request(MyApp.Tools, message)
%{"jsonrpc" => "2.0", "id" => 1, "result" => %{"protocolVersion" => "2024-11-05", ...}}
"""
@spec handle_request(module(), map(), map()) :: map()
def handle_request(server_module, message, assigns \\ %{})
def handle_request(server_module, %{"method" => method} = message, assigns) do
case method do
"initialize" ->
jsonrpc_result(message, %{
"protocolVersion" => "2024-11-05",
"capabilities" => %{"tools" => %{}},
"serverInfo" => Backend.server_info(server_module)
})
"notifications/" <> _ ->
# Notifications have no "id" field in JSONRPC 2.0
%{"jsonrpc" => "2.0", "result" => %{}}
"tools/list" ->
tools = Backend.list_tools(server_module)
jsonrpc_result(message, %{"tools" => tools})
"tools/call" ->
%{"params" => %{"name" => name, "arguments" => args}} = message
case Backend.call_tool(server_module, name, args, assigns) do
{:ok, result} ->
jsonrpc_result(message, result)
{:error, %Error{} = error} ->
Error.build_json_rpc(error, message["id"])
end
_ ->
Error.build_json_rpc(
Error.protocol(:method_not_found, %{method: method}),
message["id"]
)
end
end
defp jsonrpc_result(%{"id" => id}, result) do
%{"jsonrpc" => "2.0", "id" => id, "result" => result}
end
end