Builds and validates embedded sampling/createMessage requests for MRTR.
SEP-2577 deprecates server-initiated sampling in MCP 2026-07-28. The method
is still defined by the protocol schema and scored by the official
conformance runner, so a 2026-07-28 handler may return one as an input
request through Snodo.Result.input_required/1, next to elicitation. Prefer
elicitation for new designs; sampling stays available for clients that
declare the sampling capability.
create_message/2 returns a bare input request, without a JSON-RPC
envelope. Messages are Snodo.Prompt.message/2 maps whose content is one
text, image, audio, tool-use, or tool-result block, or a list of those
blocks. Use response/3 on a retried request to read only the named
CreateMessageResult. It does not bind a response to a user or persist
state: applications must do that using authenticated context and verified,
request-specific state.
The dialect refuses the request with -32021 when the client has not
declared sampling, sampling.tools (needed by :tools and
:tool_choice), or sampling.context (needed by an :include_context
other than "none"). Sampled content is model output: treat it as
untrusted input, never as an instruction or a verified fact.
Summary
Functions
Builds a sampling input request, raising ArgumentError when invalid.
Reads and validates the named response, ignoring unrelated response IDs.
Checks the request against this request's client capabilities.
Checks that response is a CreateMessageResult.
Validates one bare sampling input request.
Types
@type response_result() :: :missing | {:ok, map()} | {:error, Snodo.Error.t()}
Functions
Builds a sampling input request, raising ArgumentError when invalid.
messages is a non-empty list of sampling messages. Options:
:max_tokens- required, a positive integer.:system_prompt- a string.:model_preferences- a map with optional"hints"(a list of%{"name" => string}maps) and"costPriority","speedPriority", and"intelligencePriority"numbers from 0 to 1.:temperature- a number.:stop_sequences- a list of strings.:include_context-"none","thisServer", or"allServers". The last two are deprecated by SEP-2596 and needsampling.context.:metadata- a JSON object passed through to the client's provider.:tools- a list of tool definitions in wire shape; needssampling.tools.:tool_choice-%{"mode" => "auto" | "none" | "required"}; needssampling.tools.
@spec response(Snodo.Context.t() | map(), String.t(), request()) :: response_result()
Reads and validates the named response, ignoring unrelated response IDs.
A valid response is a CreateMessageResult: a "role", one sampling
content block or a list of them as "content", a "model" string, and an
optional "stopReason". Invalid responses return a generic invalid-params
error without the submitted data. Additional JSON fields are preserved and
ignored. This helper does not authenticate content or trust client-echoed
request state.
Checks the request against this request's client capabilities.
Requires a sampling object, plus sampling.tools when the request carries
tools or toolChoice and sampling.context when includeContext is not
"none".
Checks that response is a CreateMessageResult.
That is a "role" of "user" or "assistant", one sampling content block
or a non-empty list of them as "content", a "model" string, and an
optional "stopReason" string. Additional JSON fields are allowed.
Snodo.Client applies it to what a sampling handler returns.
Validates one bare sampling input request.