# `ConduitMcp.MRTR`
[🔗](https://github.com/nyo16/conduit_mcp/blob/v0.11.0/lib/conduit_mcp/mrtr.ex#L1)

Builders for Multi Round-Trip Request (MRTR) input requests.

In MCP `2026-07-28` a server no longer sends requests to the client.
Instead a tool call, resource read, or prompt get answers with an
`input_required` result carrying an `inputRequests` map — keys are
server-chosen identifiers, values are the maps these functions build — and
the client retries the original request with the matching
`inputResponses`. See
[MRTR](https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr).

Each builder returns one `InputRequest` (`"method"` plus `"params"`, no
`"jsonrpc"` or `"id"`):

    %{
      "approval" => ConduitMcp.MRTR.elicit("Approve deploy?", schema)
    }

Sampling and roots are deprecated in `2026-07-28`; `sample/2` and
`list_roots/0` remain available but carry `@deprecated` markers.
Elicitation is not deprecated.

## Returning input requests

`handle_call_tool/3`, `handle_read_resource/2` and `handle_get_prompt/3`
(and the DSL and `ConduitMcp.Component` handlers behind them) return
`{:input_required, input_requests, state}` to ask for input. The library
checks every request against the client's declared capabilities
(`missing_capabilities/2`; a gap is answered with `-32021` and
`data.requiredCapabilities`), seals `state` into `requestState` with
`ConduitMcp.MRTR.State`, and answers with an `InputRequiredResult`. On
the retry the callback finds the restored state and the client's
`inputResponses` in `conn.assigns[:mcp_input]`; see `ConduitMcp.Server`.

The state carried between rounds is sealed by `ConduitMcp.MRTR.State`,
which requires `config :conduit_mcp, :mrtr_keys`. MRTR exists only in the
modern era: a legacy-era request whose callback returns
`{:input_required, ...}` gets `-32603`.

# `elicit`

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

Builds an `elicitation/create` input request (form mode).

`requested_schema` is the restricted JSON Schema the client renders as a
form: a flat `"type" => "object"` with primitive `"properties"`.

## Example

    ConduitMcp.MRTR.elicit("Please provide your API key", %{
      "type" => "object",
      "properties" => %{"api_key" => %{"type" => "string"}},
      "required" => ["api_key"]
    })

# `list_roots`

> This function is deprecated. Roots are deprecated in MCP 2026-07-28.

```elixir
@spec list_roots() :: map()
```

Builds a `roots/list` input request.

# `missing_capabilities`

```elixir
@spec missing_capabilities(%{optional(String.t()) =&gt; map()}, map()) :: map()
```

Returns the client capabilities `input_requests` need that
`client_capabilities` does not declare, as a `ClientCapabilities`-shaped
map (`%{}` when every request can be sent).

  * `elicitation/create` needs `elicitation.url` for `"mode" => "url"`,
    otherwise form mode: `elicitation.form`, or an `elicitation` that
    declares neither mode (the spec's backwards-compatible form-only
    declaration).
  * `sampling/createMessage` needs `sampling`; `sampling.tools` when it
    carries `tools` or `toolChoice`; `sampling.context` when its
    `includeContext` is anything but `"none"`.
  * `roots/list` needs `roots`.

Other methods impose no requirement.

## Example

    iex> ConduitMcp.MRTR.missing_capabilities(
    ...>   %{"approval" => ConduitMcp.MRTR.elicit("Approve?", %{"type" => "object"})},
    ...>   %{"roots" => %{}}
    ...> )
    %{"elicitation" => %{"form" => %{}}}

# `sample`

> This function is deprecated. Sampling is deprecated in MCP 2026-07-28.

```elixir
@spec sample([map()], keyword()) :: map()
```

Builds a `sampling/createMessage` input request.

`messages` is a list of `SamplingMessage` maps.

## Options

  * `:max_tokens` - **required**; the maximum tokens to sample
  * `:system_prompt` - system prompt for the LLM
  * `:model_preferences` - model selection preferences
  * `:temperature` - sampling temperature
  * `:stop_sequences` - list of stop sequences
  * `:tools` - tools the LLM may call
  * `:tool_choice` - tool selection map, e.g. `%{"mode" => "auto"}`

Raises `KeyError` when `:max_tokens` is missing, since the spec requires it.

---

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