Anubis. Server. RequestState
(anubis_mcp v2.2.0)
Copy Markdown
The integrity-protected requestState of multi round-trip requests.
A handler that returns an Anubis.Server.InputRequired may attach any Erlang
term as state. The client echoes the resulting string on its retry, so the
specification treats it as attacker-controlled input: a server whose state
influences what it does must protect its integrity and reject state that
fails verification.
This module signs the term with HMAC-SHA256 and binds it to:
- the authenticated principal (
Anubis.Server.Frame.subject/1), so state issued to one user is refused for another; - the server module that issued it, so state cannot cross to another server sharing the application's secret;
- the originating request, its method plus the tool or prompt name or the resource URI, so state cannot move to a different request;
- a digest of that request's parameters (
request_digeston the frame's context), so a retry cannot keep the state and change the arguments; - an expiry,
:request_state_ttlmilliseconds after it was issued (default: ten minutes).
A server that authenticates outside Anubis.Server.Authorization has no
subject on the frame, and should carry its own principal inside the term and
check it on retry.
These measures bound replay; they do not make a state single-use. A server that must consume a state at most once enforces that itself.
Configuration
config :anubis_mcp, request_state_secret: System.fetch_env!("MCP_REQUEST_STATE_SECRET")The secret must be a binary of at least 32 bytes. Signing without one raises;
verifying without one refuses the state as :invalid.
Summary
Functions
Signs term for the request binding identifies, as the principal on frame.
Verifies a state the client echoed and returns the term it carries.
Types
Functions
@spec sign(term(), Anubis.Server.Frame.t(), binding()) :: String.t()
Signs term for the request binding identifies, as the principal on frame.
@spec verify(String.t(), Anubis.Server.Frame.t(), binding()) :: {:ok, term()} | {:error, :invalid | :mismatch | :expired}
Verifies a state the client echoed and returns the term it carries.
Fails with :invalid when the string is malformed or its signature does not
match, :mismatch when it was issued to another principal or request, and
:expired once its TTL has lapsed.