# `Hermolaos.Protocol.Capabilities`
[🔗](https://github.com/nyo16/hermolaos/blob/v0.5.0/lib/hermolaos/protocol/capabilities.ex#L1)

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

# `capability`

```elixir
@type capability() ::
  :roots
  | :sampling
  | :elicitation
  | :tasks
  | :tools
  | :resources
  | :prompts
  | :logging
  | :completions
```

# `client_capabilities`

```elixir
@type client_capabilities() :: %{optional(String.t()) =&gt; map()}
```

# `server_capabilities`

```elixir
@type server_capabilities() :: %{optional(String.t()) =&gt; map() | boolean()}
```

# `build_client_capabilities`

```elixir
@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)
- `:elicitation` - Enable elicitation capability (default: false)
- `:tasks` - Enable tasks capability (default: false)

## Examples

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

# `client_capabilities_with_sampling`

```elixir
@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`

```elixir
@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`

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

# `instructions_from_response`

```elixir
@spec instructions_from_response(map()) ::
  {:ok, String.t()} | {:error, :no_instructions}
```

Extracts server instructions from an initialize response.

The `instructions` field is an optional string that describes how to use the server.

## Examples

    response = %{"instructions" => "Use the search tool to find files."}
    {:ok, instructions} = Hermolaos.Protocol.Capabilities.instructions_from_response(response)

# `latest_version`

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

Returns the latest (preferred) protocol version.

# `protocol_version_from_response`

```elixir
@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`

```elixir
@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`

```elixir
@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`

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

Returns the list of supported protocol versions.

# `supports?`

```elixir
@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?`

```elixir
@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?`

```elixir
@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?`

```elixir
@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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
