ConduitMcp.MRTR (ConduitMCP v0.11.0)

Copy Markdown View Source

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.

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.

Summary

Functions

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

list_roots() deprecated

Builds a roots/list input request.

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

Builds a sampling/createMessage input request.

Functions

elicit(message, requested_schema)

@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.
@spec list_roots() :: map()

Builds a roots/list input request.

missing_capabilities(input_requests, client_capabilities)

@spec missing_capabilities(%{optional(String.t()) => 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(messages, opts)

This function is deprecated. Sampling is deprecated in MCP 2026-07-28.
@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.