# `Anubis.Server.InputRequired`

A result asking the client for input before a request can complete: the
`InputRequiredResult` of the multi round-trip requests pattern (MCP
2026-07-28).

A `tools/call`, `prompts/get` or `resources/read` handler returns one in place
of an `Anubis.Server.Response`. The client answers each input request under
its key and retries the original request; the handler then reads the answers
with `Anubis.Server.Frame.input_response/2` and, if it attached one, its state
with `Anubis.Server.Frame.request_state/1`.

    alias Anubis.Server.{Frame, InputRequired, Response}

    @impl true
    def execute(_params, frame) do
      case Frame.input_response(frame, "confirm") do
        %{"action" => "accept"} ->
          {:reply, Response.text(Response.tool(), "Sent."), frame}

        _not_yet ->
          input =
            InputRequired.new()
            |> InputRequired.elicit("confirm", "Send the message?", %{
              "type" => "object",
              "properties" => %{"ok" => %{"type" => "boolean"}}
            })

          {:reply, input, frame}
      end
    end

A client may answer only some requests, or none, and may never retry; a
handler asks again for what is missing rather than failing.

An input request needs the matching client capability (`elicitation`,
`sampling` or `roots`), including its elicitation mode or sampling tool
support. An unsupported request is refused with `-32021` instead of being
sent. `Anubis.Server.Frame.client_supports?/2` checks top-level presence;
handlers offering alternatives also check the required subfeatures in
`frame.context.client_capabilities`. The result exists only in the stateless era;
a handshake-era request that gets one fails with an internal error.

State is signed by `Anubis.Server.RequestState`, which needs
`config :anubis_mcp, :request_state_secret`.

# `t`

```elixir
@type t() :: %Anubis.Server.InputRequired{
  input_requests: %{required(String.t()) =&gt; %{required(String.t()) =&gt; term()}},
  request_state: {:set, term()} | nil
}
```

# `elicit`

```elixir
@spec elicit(t(), String.t(), String.t(), map()) :: t()
```

Asks the user, through a form, for content matching `requested_schema`.

The answer is an `ElicitResult`: `%{"action" => "accept", "content" => ...}`,
or `"decline"` / `"cancel"` without content.

# `list_roots`

```elixir
@spec list_roots(t(), String.t()) :: t()
```

Asks the client for its roots. The answer is a `ListRootsResult`.

# `new`

```elixir
@spec new() :: t()
```

Starts an empty result. It needs at least one input request or a state.

# `required_capabilities`

```elixir
@spec required_capabilities(t()) :: %{required(String.t()) =&gt; map()}
```

The client capabilities the input requests need, as a
`requiredCapabilities` map, including elicitation modes and sampling tool
support (for example, `%{"elicitation" => %{"form" => %{}}}`).
Requirements from all requests are combined.

# `sample`

```elixir
@spec sample(t(), String.t(), map()) :: t()
```

Asks the client's model for a completion. `params` are the
`sampling/createMessage` parameters (`"messages"`, `"maxTokens"`, ...).
Including `"tools"` or `"toolChoice"` requires `sampling.tools` support.

# `state`

```elixir
@spec state(t(), term()) :: t()
```

Attaches a state the client echoes on its retry, where
`Anubis.Server.Frame.request_state/1` returns it. Any term; it travels signed.

---

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