Hermolaos.Protocol.Capabilities (Hermolaos v0.3.0)

View Source

MCP capability negotiation and validation.

Capabilities define what features a client or server supports. During the initialization handshake, both parties exchange their capabilities to establish what operations are available.

Client Capabilities

Clients can advertise these capabilities:

  • roots - Filesystem root access
    • listChanged - Whether client sends notifications when roots change
  • sampling - LLM sampling support (allows server to request text generation)

Server Capabilities

Servers can advertise these capabilities:

  • tools - Tool invocation support
    • listChanged - Whether server sends notifications when tools change
  • resources - Resource access support
    • subscribe - Whether subscriptions are supported
    • listChanged - Whether server sends notifications when resources change
  • prompts - Prompt template support
    • listChanged - Whether server sends notifications when prompts change
  • logging - Structured logging support
  • completions - Argument completion support

Example

# Default client capabilities
caps = Hermolaos.Protocol.Capabilities.default_client_capabilities()

# Check if server supports tools
if Hermolaos.Protocol.Capabilities.supports?(server_caps, :tools) do
  # Can list and call tools
end

Summary

Functions

Builds custom client capabilities.

Returns client capabilities with sampling support enabled.

Returns default client capabilities.

Extracts capabilities from an initialize response.

Returns the latest (preferred) protocol version.

Extracts the protocol version from an initialize response.

Validates that required capabilities are present for an operation.

Extracts server info from an initialize response.

Returns the list of supported protocol versions.

Checks if capabilities include support for a specific feature.

Checks if a capability supports change notifications.

Checks if resource capabilities support subscriptions.

Checks if a protocol version is supported.

Types

capability()

@type capability() ::
  :roots | :sampling | :tools | :resources | :prompts | :logging | :completions

client_capabilities()

@type client_capabilities() :: %{
  optional(:roots) => %{optional(:listChanged) => boolean()},
  optional(:sampling) => %{}
}

server_capabilities()

@type server_capabilities() :: %{
  optional(:tools) => %{optional(:listChanged) => boolean()},
  optional(:resources) => %{
    optional(:subscribe) => boolean(),
    optional(:listChanged) => boolean()
  },
  optional(:prompts) => %{optional(:listChanged) => boolean()},
  optional(:logging) => %{},
  optional(:completions) => %{}
}

Functions

build_client_capabilities(opts \\ [])

@spec build_client_capabilities(keyword()) :: client_capabilities()

Builds custom client capabilities.

Options

  • :roots - Enable roots capability (default: true)
  • :roots_list_changed - Enable roots change notifications (default: true)
  • :sampling - Enable sampling capability (default: false)

Examples

caps = Hermolaos.Protocol.Capabilities.build_client_capabilities(
  roots: true,
  sampling: true
)

client_capabilities_with_sampling()

@spec client_capabilities_with_sampling() :: client_capabilities()

Returns client capabilities with sampling support enabled.

Examples

caps = Hermolaos.Protocol.Capabilities.client_capabilities_with_sampling()
# => %{"roots" => %{"listChanged" => true}, "sampling" => %{}}

default_client_capabilities()

@spec default_client_capabilities() :: client_capabilities()

Returns default client capabilities.

The default client advertises:

  • roots with listChanged: true

Sampling is not enabled by default as it requires special handling.

Examples

caps = Hermolaos.Protocol.Capabilities.default_client_capabilities()
# => %{"roots" => %{"listChanged" => true}}

from_init_response(arg1)

@spec from_init_response(map()) :: {:ok, map()} | {:error, :missing_capabilities}

Extracts capabilities from an initialize response.

Examples

response = %{"capabilities" => %{"tools" => %{}}, "serverInfo" => %{...}}
{:ok, caps} = Hermolaos.Protocol.Capabilities.from_init_response(response)

latest_version()

@spec latest_version() :: String.t()

Returns the latest (preferred) protocol version.

protocol_version_from_response(arg1)

@spec protocol_version_from_response(map()) ::
  {:ok, String.t()} | {:error, :missing_version}

Extracts the protocol version from an initialize response.

Examples

response = %{"protocolVersion" => "2025-03-26"}
{:ok, version} = Hermolaos.Protocol.Capabilities.protocol_version_from_response(response)

require(capabilities, required)

@spec require(map(), [capability()]) ::
  :ok | {:error, {:missing_capability, capability()}}

Validates that required capabilities are present for an operation.

Examples

# Check if we can list tools
:ok = Hermolaos.Protocol.Capabilities.require(server_caps, [:tools])

# Check if we can subscribe to resources
{:error, {:missing_capability, :resources}} =
  Hermolaos.Protocol.Capabilities.require(%{}, [:resources])

server_info_from_response(arg1)

@spec server_info_from_response(map()) ::
  {:ok, map()} | {:error, :missing_server_info}

Extracts server info from an initialize response.

Examples

response = %{"serverInfo" => %{"name" => "MyServer", "version" => "1.0.0"}}
{:ok, info} = Hermolaos.Protocol.Capabilities.server_info_from_response(response)

supported_versions()

@spec supported_versions() :: [String.t()]

Returns the list of supported protocol versions.

supports?(capabilities, feature)

@spec supports?(map(), capability()) :: boolean()

Checks if capabilities include support for a specific feature.

Examples

iex> caps = %{"tools" => %{"listChanged" => true}}
iex> Hermolaos.Protocol.Capabilities.supports?(caps, :tools)
true

iex> caps = %{}
iex> Hermolaos.Protocol.Capabilities.supports?(caps, :tools)
false

supports_list_changed?(capabilities, feature)

@spec supports_list_changed?(map(), capability()) :: boolean()

Checks if a capability supports change notifications.

Examples

iex> caps = %{"tools" => %{"listChanged" => true}}
iex> Hermolaos.Protocol.Capabilities.supports_list_changed?(caps, :tools)
true

iex> caps = %{"tools" => %{}}
iex> Hermolaos.Protocol.Capabilities.supports_list_changed?(caps, :tools)
false

supports_subscribe?(capabilities)

@spec supports_subscribe?(map()) :: boolean()

Checks if resource capabilities support subscriptions.

Examples

iex> caps = %{"resources" => %{"subscribe" => true}}
iex> Hermolaos.Protocol.Capabilities.supports_subscribe?(caps)
true

version_supported?(version)

@spec version_supported?(String.t()) :: boolean()

Checks if a protocol version is supported.

Examples

iex> Hermolaos.Protocol.Capabilities.version_supported?("2025-03-26")
true

iex> Hermolaos.Protocol.Capabilities.version_supported?("1.0.0")
false