Phantom.Router behaviour (phantom v0.1.0)
View SourceA DSL for defining MCP servers. This module provides functions that define tools, resources, and prompts.
Usage
defmodule MyApp.MCP.Router do
use Phantom.Router,
name: "MyApp",
vsn: "1.0"
# Call MyApp.MCP.hello/3
tool :hello, MyApp.MCP
# Call MyApp.MCP.Router.hello/3
tool :hello
# Call MyApp.MCP.code_review/3
prompt :code_review, MyApp.MCP
# Call MyApp.MCP.studies/3
resource "my_app:///studies/:id", MyApp.MCP, :studies,
name: "Studies",
mime_type: "application/json"
# Call MyApp.MCP.questions/3
resource "my_app:///questions/:id", MyApp.MCP, :questions,
name: "Questions",
mime_type: "application/html"
end
Telemetry
Telemetry is provided with these events:
[:phantom, :dispatch, :start]
with meta:~w[method params request session]a
[:phantom, :dispatch, :stop]
with meta:~w[method params request result session]a
[:phantom, :dispatch, :exception]
with meta:~w[method kind reason stacktrace params request session]a
Summary
Functions
Define a prompt that can be retrieved by the MCP client.
Define a resource that can be read by the MCP client.
Constructs a response map for the given resource with the provided parameters. This function is provided to your MCP Router that accepts the session instead.
Define a tool that can be called by the MCP client.
Callbacks
@callback connect(Phantom.Session.t(), String.t() | nil) :: {:ok, Phantom.Session.t()} | {:error, any()}
@callback disconnect(Phantom.Session.t()) :: any()
@callback dispatch_method(String.t(), module(), map(), Phantom.Session.t()) :: {:reply, any(), Phantom.Session.t()} | {:noreply, Phantom.Session.t()} | {:error, %{code: neg_integer(), message: binary()}, Phantom.Session.t()}
@callback instructions(Phantom.Session.t()) :: {:ok, String.t()}
@callback list_resources(String.t() | nil, map(), Phantom.Session.t()) :: {:reply, any(), Phantom.Session.t()} | {:noreply, Phantom.Session.t()} | {:error, any(), Phantom.Session.t()}
@callback server_info(Phantom.Session.t()) :: {:ok, %{name: String.t(), version: String.t()}} | {:error, any()}
@callback terminate(Phantom.Session.t()) :: any()
Functions
Define a prompt that can be retrieved by the MCP client.
Examples
prompt :summarize,
description: "A text prompt",
completion_function: :summarize_complete,
arguments: [
%{
name: "text",
description: "The text to summarize",
},
%{
name: "resource",
description: "The resource to summarize",
}
]
)
# ...
def summarize(args, _request, session) do
{:reply, %{}, session}
end
def summarize_complete("text", _, session) do
{:reply, [], session}
end
def summarize_complete("resource", _, session) do
# list of IDs
{:reply, ["123"], session}
end
Define a resource that can be read by the MCP client.
Examples
resource "app:///studies/:id", MyApp.MCP, :read_study,
description: "A study",
mime_type: "application/json"
# ...
def read_study(%{"id" => id}, _request, session) do
{:reply, %{
uri: "file:///project/lib/application.ex",
mime_type: "text/x-elixir",
text: "IO.puts "Hi""
}, session}
end
Constructs a response map for the given resource with the provided parameters. This function is provided to your MCP Router that accepts the session instead.
For example
iex> MyMCPRouter.resource_for(session, :name_of_resource, id: 123)
%{
uri: "myapp:///my-resource/123",
mimeType: "application/json"
text: "name of my resource"
}
Define a tool that can be called by the MCP client.
Examples
tool :local_echo,
description: "A test that echos your message",
input_schema: %{
required: [:message],
properties: %{
message: %{
type: "string",
description: "message to echo"
}
}
}
###
def local_echo(params, _request, session) do
{:reply, %{type: "text", text: params["message"]}, session}
end