Helpers for building MCP payload structs from Servers, Tools or repositories.
Each constructor normalizes various type of inputs into the MCP structs expected by the wire protocol.
Summary
Functions
Builds %GenMCP.MCP.CallToolResult{} for results returned by tool
implementations.
Normalizes capability flags/maps into %GenMCP.MCP.ServerCapabilities{}.
Normalizes content shortcuts into the MCP structs that tools and prompts expect.
Builds %GenMCP.MCP.GetPromptResult{} from keyword helpers or explicit prompt entries.
Builds a %GenMCP.MCP.InitializeResult{} for the initialize handshake.
Wraps prompt entries into %GenMCP.MCP.ListPromptsResult{} for prompt listing responses.
Wraps template entries into %GenMCP.MCP.ListResourceTemplatesResult{}
for resource template listings.
Wraps the provided resources list into
%GenMCP.MCP.ListResourcesResult{} for ListResources responses.
Builds %GenMCP.MCP.ListToolsResult{} for the tools advertised by a
server.
Wraps resource content helpers into %GenMCP.MCP.ReadResourceResult{}.
Builds either %GenMCP.MCP.TextResourceContents{} or %GenMCP.MCP.BlobResourceContents{} from keyword options.
Builds %GenMCP.MCP.Implementation{} entries used in initialize replies.
Types
@type content_block() :: content_block_option() | GenMCP.MCP.TextContent.t() | GenMCP.MCP.AudioContent.t() | GenMCP.MCP.ImageContent.t() | GenMCP.MCP.EmbeddedResource.t() | GenMCP.MCP.ResourceLink.t()
Functions
@spec call_tool_result([ content_block() | {:error, boolean() | binary() | nil} | {:data, map()} | {:_data, map()} | map() ]) :: GenMCP.MCP.CallToolResult.t()
Builds %GenMCP.MCP.CallToolResult{} for results returned by tool
implementations.
The list may contain shortcuts such as text: "foo", image: {"mime", data}
or literal %GenMCP.MCP.* structs.
Structured content
Structured payloads can be provided as a naked map in the list, with the
data: keyword shortcut, or with the _data: shortcut. Only one structured
payload is allowed per result.
data: mapand a naked map both setstructuredContentand also append a JSON-encoded text content block mirroring the payload. This is convenient for clients that do not consume structured content directly._data: mapsetsstructuredContentwithout adding the JSON text mirror, when the caller wants the structured payload to remain the only carrier of that data.
Errors
Errors can be reported by including error: true (sets isError to true) or
error: "message" (adds a text content block with the message and sets
isError to true).
Example
MCP.call_tool_result(text: "Hello, world!", error: true)
MCP.call_tool_result(text: "Summary", data: %{rows: 3})
MCP.call_tool_result(text: "Summary", _data: %{rows: 3})
@spec capabilities(keyword()) :: GenMCP.MCP.ServerCapabilities.t()
Normalizes capability flags/maps into %GenMCP.MCP.ServerCapabilities{}.
Passing true for a key yields an empty map, while maps are returned
unchanged and other values keep the field nil. This allows flexible
declaration of server capabilities during initialization.
@spec content_block(content_block_option()) :: GenMCP.MCP.TextContent.t() | GenMCP.MCP.EmbeddedResource.t() | GenMCP.MCP.ResourceLink.t() | GenMCP.MCP.ImageContent.t() | GenMCP.MCP.AudioContent.t()
Normalizes content shortcuts into the MCP structs that tools and prompts expect.
This helper is generally not used directly, but delegated to from
call_tool_result/1 or get_prompt_result/1.
Supported shortcuts are
{:text, binary()}{:resource, %{uri: binary(), text: binary()}}{:resource, %{uri: binary(), blob: binary()}}{:link, %{name: binary(), uri: binary()}}{:image, {mime, data}}{:audio, {mime, data}}
Example
MCP.content_block({:audio, {"audio/mp3", "base64data"}})
@spec get_prompt_result(keyword() | [term()]) :: GenMCP.MCP.GetPromptResult.t()
Builds %GenMCP.MCP.GetPromptResult{} from keyword helpers or explicit prompt entries.
The helpers treat text: and assistant: keywords as alternating user/assistant messages, honor an optional description: and convert tuples or %GenMCP.MCP.PromptMessage structs via content_block/1. Unsupported shapes such as :link or error: raise ArgumentError so the caller can fix the prompt payload.
Example
MCP.get_prompt_result(
description: "A helpful prompt",
assistant: "You are a an expert for some reason…",
text: user_input
)
@spec intialize_result(keyword()) :: GenMCP.MCP.InitializeResult.t()
Builds a %GenMCP.MCP.InitializeResult{} for the initialize handshake.
Requires :server_info (usually a %GenMCP.MCP.Implementation{}) and
uses :capabilities if provided. The protocolVersion field is fixed to
"2025-11-25" to match the latest MCP spec supported here.
Example
MCP.intialize_result(
server_info: %GenMCP.MCP.Implementation{
name: "TestServer",
version: "1.0.0"
}
)
@spec list_prompts_result([term()], term() | nil) :: GenMCP.MCP.ListPromptsResult.t()
Wraps prompt entries into %GenMCP.MCP.ListPromptsResult{} for prompt listing responses.
The provided prompts list is returned as-is and nextCursor mirrors the optional cursor token passed by the caller.
@spec list_resource_templates_result([term()]) :: GenMCP.MCP.ListResourceTemplatesResult.t()
Wraps template entries into %GenMCP.MCP.ListResourceTemplatesResult{}
for resource template listings.
Templates are returned as-is so callers may pass either structs or raw maps.
Pagination is not supported for resource templates.
@spec list_resources_result([term()], term() | nil) :: GenMCP.MCP.ListResourcesResult.t()
Wraps the provided resources list into
%GenMCP.MCP.ListResourcesResult{} for ListResources responses.
next_cursor arguments such as "cursor-123" are assigned to nextCursor,
while the caller keeps ownership of the resource entries.
@spec list_tools_result([GenMCP.Suite.Tool.tool() | GenMCP.MCP.Tool.t()]) :: GenMCP.MCP.ListToolsResult.t()
Builds %GenMCP.MCP.ListToolsResult{} for the tools advertised by a
server.
Structs already shaped as %GenMCP.MCP.Tool{} are left untouched and
other entries go through GenMCP.Suite.Tool.describe/1.
Pagination for tools is not supported yet.
Example
MCP.list_tools_result([
%GenMCP.MCP.Tool{name: "tool1", inputSchema: %{type: "object"}},
%{name: "tool2", inputSchema: %{type: "object"}}
])
@spec read_resource_result(keyword() | [map()]) :: GenMCP.MCP.ReadResourceResult.t()
Wraps resource content helpers into %GenMCP.MCP.ReadResourceResult{}.
When given a keyword list (typically :uri with :text or :blob) it
delegates to resource_contents/1 and includes a single-element content list.
Passing a list of maps returns those entries as the content list.
It is not possible to mix keyword style items and maps in the list, as all keyword keys define the same resource content.
Example
MCP.read_resource_result(uri: "file:///doc.pdf", blob: "bytes")
@spec resource_contents(keyword()) :: GenMCP.MCP.TextResourceContents.t() | GenMCP.MCP.BlobResourceContents.t()
Builds either %GenMCP.MCP.TextResourceContents{} or %GenMCP.MCP.BlobResourceContents{} from keyword options.
Requires :uri and either :text or :blob. Optional :mime_type and :_meta fields are forwarded to the resulting struct. Missing both :text and :blob raises ArgumentError, while omitting :uri raises KeyError.
Example
MCP.resource_contents(
uri: "file:///doc.pdf",
mime_type: "application/pdf",
blob: "some-base-64"
)
@spec server_info(keyword()) :: GenMCP.MCP.Implementation.t()
Builds %GenMCP.MCP.Implementation{} entries used in initialize replies.
:name and :version trigger KeyError when missing, while :title is
optional.