Current section
Files
Jump to
Current section
Files
lib/gen_mcp.ex
defmodule GenMCP do
@moduledoc """
The main behaviour for MCP servers.
Implement this behaviour to create a custom MCP server. If you are looking for a high-level framework to build tools and resources, see `GenMCP.Suite`.
## Example
defmodule MyServer do
@behaviour GenMCP
alias GenMCP.MCP
@impl true
def init(_session_id, _opts) do
{:ok, %{}}
end
@impl true
def handle_request(%MCP.InitializeRequest{} = req, _chan_info, state) do
# Protocol version check omitted for brevity
result = MCP.intialize_result(
capabilities: MCP.capabilities(tools: true),
server_info: MCP.server_info(name: "My Server", version: "1.0.0")
)
{:reply, {:result, result}, state}
end
def handle_request(%MCP.ListToolsRequest{}, _chan_info, state) do
result = MCP.list_tools_result([
%MCP.Tool{
name: "hello",
description: "Say hello",
inputSchema: %{
type: "object",
properties: %{
name: %{type: "string"}
}
}
}
])
{:reply, {:result, result}, state}
end
@impl true
def handle_notification(%MCP.InitializedNotification{}, state) do
{:noreply, state}
end
def handle_notification(_notif, state) do
{:noreply, state}
end
@impl true
def handle_info(_msg, state) do
{:noreply, state}
end
end
"""
alias GenMCP.MCP
alias GenMCP.Mux.Channel
require(Elixir.GenMCP.MCP.ModMap).require_all()
@doc """
Returns the supported protocol versions.
"""
def supported_protocol_versions do
["2025-06-18"]
end
@type state :: term
@doc """
Initializes the server state.
Called when a new MCP session is established.
"""
@callback init(session_id :: String.t(), init_arg :: term) :: {:ok, state} | {:stop, term}
@type request ::
MCP.InitializeRequest.t()
| MCP.ListToolsRequest.t()
| MCP.CallToolRequest.t()
| MCP.ListResourcesRequest.t()
| MCP.ReadResourceRequest.t()
| MCP.ListResourceTemplatesRequest.t()
| MCP.ListPromptsRequest.t()
| MCP.GetPromptRequest.t()
| MCP.PingRequest.t()
@type result ::
MCP.InitializeResult.t()
| MCP.ListToolsResult.t()
| MCP.CallToolResult.t()
| MCP.ListResourcesResult.t()
| MCP.ReadResourceResult.t()
| MCP.ListResourceTemplatesResult.t()
| MCP.ListPromptsResult.t()
| MCP.GetPromptResult.t()
@type notification ::
MCP.InitializedNotification.t()
| MCP.CancelledNotification.t()
| MCP.RootsListChangedNotification.t()
| MCP.ProgressNotification.t()
@type server_reply :: {:result, result} | :stream | {:error, term}
@doc """
Handles an incoming MCP request and returns a result or stop the server.
"""
@callback handle_request(request, Channel.chan_info(), state) ::
{:reply, server_reply, state} | {:stop, reason :: term, server_reply, state}
@doc """
Handles an incoming MCP notification.
Notifications are one-way messages that do not expect a response.
"""
@callback handle_notification(notification, state) :: {:noreply, state}
@doc """
Handles process messages.
Invoked when the server process receives a message that is not an MCP request
or notification.
"""
@callback handle_info(term, state) :: {:noreply, state}
end