mcp.server.request_state

An opt-in codec that secures the MRTR (SEP-2322) opaque requestState the server hands a client in an InputRequiredResult and the (untrusted) client echoes back verbatim on retry.

Per SEP-2322 a server MUST treat the echoed requestState as untrusted input, SHOULD encrypt/sign it for integrity + confidentiality, and — when the state carries data specific to the original user — MUST cryptographically bind it to that user and verify the echoed state belongs to the currently authenticated user (replay/hijack defense). This codec makes those a one-liner: the server wraps outgoing state and verifies incoming state transparently, so tool/prompt/task handlers keep calling inputRequired!T / requestStateAs!T against plaintext.

Two wire modes share one envelope: payload = {"s":<stateJson>,"exp":<unixSeconds>,"b":<bindTagHex>} - signed (HMAC-SHA256): "v1." ~ b64url(payload) ~ "." ~ b64url(mac) - encrypted (AES-256-GCM): "v1e." ~ b64url(nonce ~ ciphertext ~ tag) The bind tag is HMAC-SHA256(key, subject [~ "\0" ~ tool]) hex; in the encrypted mode it is also fed as GCM AAD. Verification is fail-closed: a bad MAC, a GCM auth failure, an expired blob, a wrong-subject bind, or an unparseable envelope all yield Nullable!string.init (the dispatch path then re-elicits).

Members

Classes

RequestStateCodec
class RequestStateCodec

The codec the dispatch path installs when an operator enables secureRequestState. encode wraps a handler's plaintext state for the wire; decode verifies an echoed blob and returns the inner state, or null when verification fails (the caller then treats it as no state and re-elicits). All crypto is fail-closed.

Enums

RequestStateBinding
enum RequestStateBinding

What the codec binds the state to, so an echoed blob can only be redeemed by the identity it was issued for (SEP-2322 user-binding MUST).

RequestStateMode
enum RequestStateMode

How the codec protects the envelope. signed (HMAC-SHA256) gives integrity and authenticity but leaves the inner state readable on the wire; encrypted (AES-256-GCM) additionally gives confidentiality.

Functions

generateEphemeralKey
ubyte[] generateEphemeralKey()

Generate a 32-byte ephemeral key (used when the operator supplies none).

Structs

RequestStateSecurity
struct RequestStateSecurity

Configuration handed to McpServer.secureRequestState. The key is the operator-supplied secret (>= 32 bytes); an empty key makes the server generate a single-process ephemeral key (verification fails across instances or restarts — see secureRequestState).