McpServer behaviour (HTTP MCP Server v0.6.0)
View SourceDefines the behaviour for implementing Model Context Protocol (MCP) servers in Elixir.
McpServer is the core behaviour module that specifies the callback functions
required to implement a fully-functional MCP server. MCP (Model Context Protocol)
is a protocol that enables AI models to interact with external tools, prompts,
and resources.
Overview
This behaviour defines optional callbacks for three main MCP capabilities:
- Tools - Functions that can be called by MCP clients with input validation
- Prompts - Interactive message templates with argument completion
- Resources - Data sources that can be read and completed
Implementing modules can choose to implement any combination of these capabilities by defining the appropriate callback functions.
Callbacks
All callbacks are optional, allowing servers to implement only the features they need:
Tool Callbacks
list_tools/1- Returns the list of available tools with their schemascall_tool/3- Executes a tool with the given name and arguments
Prompt Callbacks
get_prompt/3- Returns a prompt's messages for the given argumentscomplete_prompt/3- Provides completion suggestions for prompt arguments
Resource Callbacks
list_resources/1- Returns the list of available resourcesread_resource/3- Reads and returns a resource's contentscomplete_resource/3- Provides completion suggestions for resource URIs
Connection Context
All callbacks receive a McpServer.Conn.t() as their first argument, which provides
request context and connection information for handling the MCP interaction.
Usage
Instead of implementing this behaviour directly, most applications should use
McpServer.Router, which provides a convenient DSL for defining tools, prompts,
and resources:
defmodule MyApp.Router do
use McpServer.Router
tool "greet", "Greets a person", MyController, :greet do
input_field("name", "The name to greet", :string, required: true)
output_field("greeting", "The greeting message", :string)
end
prompt "welcome", "A friendly welcome prompt" do
argument("user_name", "The user's name", required: true)
get MyController, :get_welcome_prompt
end
resource "user", "https://example.com/users/{id}" do
description "User resource"
read MyController, :read_user
end
endError Handling
Callbacks that can fail should return an {:error, code, message} tuple where:
codeis an integer error code (typically JSON-RPC error codes)messageis a human-readable error description
Example Implementation
defmodule MyMcpServer do
@behaviour McpServer
@impl true
def list_tools(_conn) do
{:ok, [
%{
"name" => "echo",
"description" => "Echoes back the input",
"inputSchema" => %{
"type" => "object",
"properties" => %{"message" => %{"type" => "string"}},
"required" => ["message"]
}
}
]}
end
@impl true
def call_tool(_conn, "echo", %{"message" => msg}) do
{:ok, %{"response" => msg}}
end
endSee McpServer.Router for a more convenient way to define MCP servers.
Summary
Types
@type error() :: {:error, message :: String.t()}
Callbacks
@callback call_tool(McpServer.Conn.t(), String.t(), map()) :: {:ok, map()} | error()
@callback get_prompt(McpServer.Conn.t(), String.t(), map()) :: {:ok, list()} | error()
@callback list_resources(McpServer.Conn.t()) :: {:ok, list()} | error()
@callback list_tools(McpServer.Conn.t()) :: {:ok, list()} | error()
@callback read_resource(McpServer.Conn.t(), String.t(), map()) :: {:ok, any()} | error()