AttestoMCP.Server.RequestMeta (attesto_mcp_server v2.8.0)

Copy Markdown View Source

Untrusted request metadata exposed to handlers as context.request_meta.

Every handler and per-request callback receives an immutable snapshot of the incoming request's params["_meta"] object with its JSON string keys and values unchanged. An absent object, which only legacy revisions permit, produces %{}. The snapshot is the same for HTTP, stdio, and direct dispatch through AttestoMCP.Server.Test.

The snapshot is client input. It is never merged into principal, principal_binding, tenant, scopes, claims, sender constraints, or host_context, and the server never derives an issuer, audience, authorization decision, or outbound destination from it. Protocol-owned keys such as io.modelcontextprotocol/protocolVersion appear exactly as the client sent them; the server's validated interpretation remains in the normalized context fields (:protocol_version, :trace_context, :logging_level) and is not changed by the snapshot. Use application/1 to read only keys outside the reserved MCP namespaces.

The complete _meta object must encode within :max_request_meta_bytes (65,536 bytes by default, configurable up to :max_json_bytes) and within the server's existing JSON depth and node bounds. Larger metadata is rejected with an invalid-params error whose reason is "request_meta_too_large"; it is never truncated. String keys and values are copied out of the request body so a retained snapshot does not keep the body alive.

Metadata values are not added to logs, telemetry, error payloads, or response metadata. The existing trace-context extraction remains separate.

A multi-round retry exposes its own metadata. The signed retry state binds operation parameters and all metadata except traceparent, tracestate, baggage, progressToken, and io.modelcontextprotocol/clientInfo. Application keys and protocol settings remain bound to the first round; tracing, progress, and display values may change. Operation targets and confirmation-bound values belong in operation parameters, not those volatile fields. No identity or authority is recovered from earlier metadata.

Summary

Functions

Returns the entries whose keys are outside MCP-reserved metadata names.

Returns the default metadata byte budget.

Returns true for keys reserved by MCP: progressToken, the trace-context keys, and any prefix whose second label is modelcontextprotocol or mcp.

Returns true when a key follows the MCP _meta key grammar.

Functions

application(meta)

@spec application(map()) :: map()

Returns the entries whose keys are outside MCP-reserved metadata names.

iex> AttestoMCP.Server.RequestMeta.application(%{
...>   "com.example/request-purpose" => "audit",
...>   "io.modelcontextprotocol/protocolVersion" => "2026-07-28",
...>   "progressToken" => 7
...> })
%{"com.example/request-purpose" => "audit"}

default_max_bytes()

@spec default_max_bytes() :: pos_integer()

Returns the default metadata byte budget.

reserved_key?(key)

@spec reserved_key?(term()) :: boolean()

Returns true for keys reserved by MCP: progressToken, the trace-context keys, and any prefix whose second label is modelcontextprotocol or mcp.

valid_key?(key)

@spec valid_key?(term()) :: boolean()

Returns true when a key follows the MCP _meta key grammar.