Behaviour for implementing MCP server feature handlers.
Implement this behaviour to define how your server responds to client requests for tools, resources, prompts, completions, and logging.
All callbacks are optional — the server only advertises capabilities for callbacks that your module actually implements.
Example
defmodule MyHandler do
@behaviour MCP.Server.Handler
@impl true
def init(opts) do
{:ok, %{tools: Keyword.get(opts, :tools, [])}}
end
@impl true
def handle_list_tools(_cursor, state) do
{:ok, state.tools, nil, state}
end
@impl true
def handle_call_tool("echo", %{"message" => msg}, state) do
{:ok, [%{"type" => "text", "text" => msg}], state}
end
end
Summary
Callbacks
Execute a tool. Called on tools/call.
Execute a tool with context. Called on tools/call when the handler
implements this 4-arity version.
Complete an argument value. Called on completion/complete.
Get a specific prompt. Called on prompts/get.
Return a list of prompts. Called on prompts/list.
Return a list of resource templates. Called on resources/templates/list.
Return a list of resources. Called on resources/list.
Return a list of tools. Called on tools/list.
Read a resource by URI. Called on resources/read.
Set the logging level. Called on logging/setLevel.
Subscribe to resource updates. Called on resources/subscribe.
Unsubscribe from resource updates. Called on resources/unsubscribe.
Initialize handler state. Called when the server starts.
Types
Callbacks
@callback handle_call_tool(name :: String.t(), arguments :: map(), state()) :: {:ok, content :: [map()], state()} | {:ok, content :: [map()], is_error :: boolean(), state()} | {:error, code :: integer(), message :: String.t(), state()}
Execute a tool. Called on tools/call.
@callback handle_call_tool( name :: String.t(), arguments :: map(), context :: MCP.Server.ToolContext.t(), state() ) :: {:ok, content :: [map()], state()} | {:ok, content :: [map()], is_error :: boolean(), state()} | {:error, code :: integer(), message :: String.t(), state()}
Execute a tool with context. Called on tools/call when the handler
implements this 4-arity version.
The context (MCP.Server.ToolContext) allows sending notifications
(logging, progress) and making server-to-client requests (sampling,
elicitation) during tool execution.
When this callback is implemented, tool execution runs asynchronously, enabling SSE streaming of intermediate messages.
@callback handle_complete(ref :: map(), argument :: map(), state()) :: {:ok, completion :: map(), state()}
Complete an argument value. Called on completion/complete.
@callback handle_get_prompt(name :: String.t(), arguments :: map() | nil, state()) :: {:ok, result :: map(), state()} | {:error, code :: integer(), message :: String.t(), state()}
Get a specific prompt. Called on prompts/get.
@callback handle_list_prompts(cursor(), state()) :: {:ok, prompts :: [map()], next_cursor :: cursor(), state()}
Return a list of prompts. Called on prompts/list.
@callback handle_list_resource_templates(cursor(), state()) :: {:ok, templates :: [map()], next_cursor :: cursor(), state()}
Return a list of resource templates. Called on resources/templates/list.
@callback handle_list_resources(cursor(), state()) :: {:ok, resources :: [map()], next_cursor :: cursor(), state()}
Return a list of resources. Called on resources/list.
@callback handle_list_tools(cursor(), state()) :: {:ok, tools :: [map()], next_cursor :: cursor(), state()}
Return a list of tools. Called on tools/list.
@callback handle_read_resource(uri :: String.t(), state()) :: {:ok, contents :: [map()], state()} | {:error, code :: integer(), message :: String.t(), state()}
Read a resource by URI. Called on resources/read.
Set the logging level. Called on logging/setLevel.
@callback handle_subscribe(uri :: String.t(), state()) :: {:ok, state()} | {:error, code :: integer(), message :: String.t(), state()}
Subscribe to resource updates. Called on resources/subscribe.
@callback handle_unsubscribe(uri :: String.t(), state()) :: {:ok, state()} | {:error, code :: integer(), message :: String.t(), state()}
Unsubscribe from resource updates. Called on resources/unsubscribe.
Initialize handler state. Called when the server starts.