Anubis.Server.Component (anubis_mcp v2.2.0)

Copy Markdown

The DSL behind use Anubis.Server.Component.

A component is one addressable piece of an MCP server: a tool, a prompt or a resource. use Anubis.Server.Component injects the callbacks for whichever type you pass, so you only write the part that is yours (the execute/2, get_messages/2 or read/2 implementation) plus the schema.

defmodule MyApp.Tools.Search do
  use Anubis.Server.Component, type: :tool, name: "search", title: "Search"

  schema do
    field(:query, :string, description: "What to look for")
  end

  @impl true
  def execute(%{"query" => query}, frame) do
    {:reply, Response.text(Response.tool(), MyApp.search(query)), frame}
  end
end

Options

:type is required and must be :tool, :prompt or :resource. The options below are accepted by all three types, plus the ones each behaviour documents.

  • :name - the wire name. Defaults to the module basename for resources, nil otherwise.
  • :title - a human-readable label.
  • :description - defaults to the module @moduledoc.
  • :annotations - behaviour-specific hints (readOnlyHint, destructiveHint, ...).
  • :meta - arbitrary _meta on the tool or resource descriptor.
  • :icons - icons rendered by supporting clients.
  • :scopes - authorization scopes required to see this component.

Resources additionally take :uri or :uri_template (mutually exclusive) and :mime_type. Tools additionally take :task_support (:forbidden, :optional or :required).

Schemas

schema/1 and output_schema/1 wrap a Peri schema and compile it at build time, so the JSON Schema handed to clients is derived from the same source that validates arguments:

schema do
  field(:query, :string, description: "What to look for")
  field(:limit, :integer, default: 10)
end

See Anubis.Server.Component.Tool, .Prompt and .Resource for the callbacks each type must implement, and the Building a Server guide for end-to-end examples.

Summary

Functions

Checks if a module is a valid component.

Defines a field that embeds many objects (array of objects).

Defines a field that embeds one object.

Defines a field with metadata for JSON Schema generation.

Extracts the description from a component module.

Gets the component type (:tool, :prompt, or :resource).

Defines the output schema for a tool component.

Defines the parameter schema for the component.

Functions

component?(module)

Checks if a module is a valid component.

Parameters

  • module - The module atom to check

Returns

Examples

iex> defmodule MyTool do
...>   use Anubis.Server.Component, type: :tool
...> end
iex> Anubis.Server.Component.component?(MyTool)
true

iex> defmodule NotAComponent do
...>   def hello, do: :world
...> end
iex> Anubis.Server.Component.component?(NotAComponent)
false

embeds_many(name, opts \\ [], list)

(macro)

Defines a field that embeds many objects (array of objects).

Examples

embeds_many :users, description: "List of users" do
  field :id, :string, required: true, description: "User ID"
  field :name, :string, description: "User name"
end

embeds_many :tags, required: true do
  field :name, :string, required: true
  field :value, :string
end

embeds_one(name, opts \\ [], list)

(macro)

Defines a field that embeds one object.

Examples

embeds_one :user, description: "User object" do
  field :id, :string, required: true, description: "User ID"
  field :name, :string, description: "User name"
end

embeds_one :address, required: true do
  field :street, :string, required: true
  field :city, :string, required: true
  field :zip, :string
end

field(name, type, opts \\ [])

(macro)

Defines a field with metadata for JSON Schema generation.

Supports both simple fields and nested objects with their own fields.

Examples

# Simple field
field :email, {:required, :string}, format: "email", description: "User's email address"
field :age, :integer, description: "Age in years"

# Nested field
field :user do
  field :name, {:required, :string}
  field :email, :string, format: "email"
end

# Nested field with metadata
field :profile, description: "User profile information" do
  field :bio, :string, description: "Short biography"
  field :avatar_url, :string, format: "uri"
end

# Mirrored into the Mcp-Param-Region header by 2026-07-28 clients
field :region, :string, required: true, mcp_header: "Region"

mcp_header: puts x-mcp-header on the parameter; see Anubis.Server.McpParam for the rules it must follow and how the header is checked.

get_description(module)

Extracts the description from a component module.

Parameters

  • module - The component module atom

Returns

  • The description from description/0 callback if defined
  • Falls back to the module's @moduledoc if no callback is defined
  • Empty string if neither is defined

Examples

iex> defmodule MyTool do
...>   @moduledoc "A helpful tool"
...>   use Anubis.Server.Component, type: :tool
...> end
iex> Anubis.Server.Component.get_description(MyTool)
"A helpful tool"

iex> defmodule MyToolWithCallback do
...>   @moduledoc "Default description"
...>   use Anubis.Server.Component, type: :tool
...>   def description, do: "Custom description from callback"
...> end
iex> Anubis.Server.Component.get_description(MyToolWithCallback)
"Custom description from callback"

get_type(module)

Gets the component type (:tool, :prompt, or :resource).

Parameters

  • module - The component module atom

Returns

  • :tool - If the module is a tool component
  • :prompt - If the module is a prompt component
  • :resource - If the module is a resource component

Examples

iex> defmodule MyTool do
...>   use Anubis.Server.Component, type: :tool
...> end
iex> Anubis.Server.Component.get_type(MyTool)
:tool

output_schema(list)

(macro)

Defines the output schema for a tool component.

This schema describes the expected structure of the tool's output in the structuredContent field. Only available for tool components.

schema(list)

(macro)

Defines the parameter schema for the component.

The schema uses Peri's validation DSL and is automatically validated before the component's callback is executed.