GenMCP.MCP (gen_mcp v0.10.0)

Copy Markdown View Source

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

content_block()

content_block_option()

@type content_block_option() ::
  {:text, binary()}
  | {:resource, %{uri: binary(), text: binary()}}
  | {:resource, %{uri: binary(), blob: binary()}}
  | {:link, %{name: binary(), uri: binary()}}
  | {:image, {binary(), binary()}}
  | {:audio, {binary(), binary()}}

Functions

call_tool_result(all_content)

@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: map and a naked map both set structuredContent and also append a JSON-encoded text content block mirroring the payload. This is convenient for clients that do not consume structured content directly.
  • _data: map sets structuredContent without 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})

capabilities(opts)

@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.

content_block(content_opts)

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"}})

get_prompt_result(opts)

@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
)

intialize_result(opts)

@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"
  }
)

list_prompts_result(prompts, next_cursor)

@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.

list_resource_templates_result(templates)

@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.

list_resources_result(resources, next_cursor)

@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.

list_tools_result(tools)

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"}}
])

read_resource_result(opts)

@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")

resource_contents(opts)

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"
)

server_info(opts)

@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.