Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Requirements — 2025-11-25

Every normative clause of the 2025-11-25 specification that the validator’s registry carries — 348 in all, 102 judged from a recorded trace and 246 excluded with the reason below. A report names a clause by the ID used as each heading here; each entry quotes the specification verbatim and links to the published text. mcp-trace-validator requirements --revision 2025-11-25 --format json prints the same data as JSON.

BASE

BASE-001

MUST · binds the client and server

Requests MUST include a string or integer ID.

basic#requests

Judged by base.request-id-type.

BASE-002

MUST NOT · binds the client and server

Unlike base JSON-RPC, the ID MUST NOT be null.

basic#requests

Judged by base.request-id-not-null.

BASE-003

MUST NOT · binds the client and server

The request ID MUST NOT have been previously used by the requestor within the same session.

basic#requests

Judged by base.request-id-unique.

BASE-004

MUST · binds the client and server

Result responses MUST include the same ID as the request they correspond to.

basic#result-responses

Judged by base.result-id-matches.

BASE-005

MUST NOT · binds the client and server

Notifications MUST NOT include an ID.

basic#notifications

Judged by base.notification-no-id.

BASE-006

MUST · binds the client and server

Error responses MUST include an error field with a code and message.

basic#error-responses

Judged by base.error-shape.

BASE-007

MUST · binds the client and server

Error codes MUST be integers.

basic#error-responses

Judged by base.error-code-integer.

BASE-008

MUST · binds the client and server

All messages between MCP clients and servers MUST follow the JSON-RPC 2.0 specification.

basic#messages

Judged by base.jsonrpc-version.

BASE-009

MUST · binds the client and server

Error responses MUST include the same ID as the request they correspond to (except in error cases where the ID could not be read due a malformed request).

basic#error-responses

Judged by base.error-id-matches.

BASE-010

MUST · binds the client and server

Result responses MUST include a result field.

basic#result-responses

Judged by base.result-field.

BASE-011

MUST NOT · binds the client and server

The receiver MUST NOT send a response.

basic#notifications

Excluded. A response to a notification carries no correlating ID, so it is indistinguishable on the wire from any other unsolicited response; unsolicited responses are flagged by base.result-id-matches and base.error-id-matches under BASE-004/BASE-009.

BASE-012

MUST · binds the client and server

All implementations MUST support the base protocol and lifecycle management components.

basic

Excluded. The umbrella clause the BASE and LIFE areas mechanize requirement-by-requirement; it has no observable beyond its constituents.

BASE-013

MUST · binds the client and server

Clients and servers MUST support JSON Schema 2020-12 for schemas without an explicit $schema field

basic#implementation-requirements

Excluded. Dialect support is validation behavior inside each implementation; a trace shows schemas exchanged, not how the receiver processed them.

BASE-014

MUST · binds the client and server

Clients and servers MUST validate schemas according to their declared or default dialect.

basic#implementation-requirements

Excluded. Whether validation happened, and against which dialect, is implementation-internal; validation outcomes need ground truth about inputs that a trace does not carry.

BASE-015

MUST · binds the client and server

They MUST handle unsupported dialects gracefully by returning an appropriate error indicating the dialect is not supported.

basic#implementation-requirements

Excluded. Judging graceful handling requires knowing the receiver’s supported-dialect set, which is not in the trace.

BASE-016

SHOULD · binds the client and server

Clients and servers SHOULD document which schema dialects they support

basic#implementation-requirements

Excluded. Documentation lives outside the protocol session entirely.

BASE-017

MUST · binds the client and server

Schemas MUST be valid according to their declared or default dialect

basic#schema-validation

Judged by base.schemas-valid-for-dialect.

BASE-018

MUST NOT · binds the client and server

Certain key names are reserved by MCP for protocol-level metadata, as specified below; implementations MUST NOT make assumptions about values at these keys.

basic#_meta

Excluded. What an implementation assumes is internal; only conduct that follows from an assumption could surface, and attributing it requires the assumption.

BASE-019

MUST · binds the client and server

If specified, MUST be a series of labels separated by dots (.), followed by a slash (/); Labels MUST start with a letter and end with a letter or digit; interior characters can be letters, digits, or hyphens (-)

basic#_meta

Judged by base.meta-key-format.

BASE-020

MUST · binds the client and server

Unless empty, MUST begin and end with an alphanumeric character ([a-z0-9A-Z]); MAY contain hyphens (-), underscores (_), dots (.), and alphanumerics in between

basic#_meta

Judged by base.meta-key-format.

BASE-021

SHOULD · binds the client and server

Implementations SHOULD use reverse DNS notation (e.g., com.example/ rather than example.com/).

basic#_meta

Excluded. Whether a syntactically valid prefix is reverse-DNS for its author cannot be decided without knowing the author’s domain.

BASE-022

MUST · binds the client

Clients that support rendering icons MUST support at least the following MIME types:

basic#icons

Excluded. Icon rendering support is client-internal capability with no wire footprint; the conditional premise (that the client renders icons) is equally invisible.

BASE-023

MUST · binds the client

Consumers of icon metadata MUST take appropriate security precautions when handling icons to prevent compromise:

basic#icons

Excluded. The umbrella for consumer-side icon hygiene (fetch policy, size limits, origin checks) — all consumer-internal conduct after the recorded session ends.

BASE-024

MUST · binds the client

Clients MUST reject icon URIs that use unsafe schemes and redirects, such as javascript:, file:, ftp:, ws:, or local app URI schemes.

basic#icons

Excluded. Rejection is client-side handling after receipt; the trace records the icon metadata served, not what the client did with it.

BASE-082

MUST · binds the client and server

Supported dialects: Implementations MUST support at least 2020-12 and SHOULD document which additional dialects they support

basic#schema-dialect

Excluded. Restates BASE-013’s dialect floor and BASE-016’s documentation SHOULD as the section’s third numbered rule, unconditionally where BASE-013 scopes itself to schemas without an explicit $schema (the same restatement shape as TRAN-049 to TRAN-024). Excluded for BASE-013’s reason: dialect support is validation behavior inside each implementation, and a trace shows the schemas exchanged, not how the receiver processed them.

BASE-085

SHOULD NOT · binds the client and server

Implementations using an HTTP-based transport SHOULD conform to this specification, whereas implementations using STDIO transport SHOULD NOT follow this specification, and instead retrieve credentials from the environment.

basic#auth

Excluded. Credential retrieval from the environment is process-local conduct with no wire footprint, and the HTTP half defers to the authorization specification, whose clauses are entered on its own page: AUTH-001 and AUTH-002 restate this sentence there, and the challenge clauses a recording can judge carry checks. One entry for the sentence’s SHOULD and SHOULD NOT, as BASE-068 enters it at 2026-07-28.

BASE-086

SHOULD · binds the client and server

Implementors are RECOMMENDED to use JSON Schema 2020-12.

basic#schema-dialect

Judged by base.schemas-use-2020-12.

BASE-087

SHOULD · binds the client

image/png - PNG images (safe, universal compatibility) image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility) Clients that support rendering icons SHOULD also support:

basic#icons

Excluded. Extends BASE-022’s client-internal rendering-support premise: neither the support nor its absence reaches the wire, and the premise itself (that the client renders icons) is equally invisible.

LIFE

LIFE-001

MUST · binds the client

The initialization phase MUST be the first interaction between client and server.

basic/lifecycle#initialization

Judged by lifecycle.first-interaction-initialize.

LIFE-002

MUST · binds the client

The client MUST initiate this phase by sending an initialize request containing: Protocol version supported; Client capabilities; Client implementation information

basic/lifecycle#initialization

Judged by lifecycle.initialize-params.

LIFE-003

MUST · binds the client

After successful initialization, the client MUST send an initialized notification to indicate it is ready to begin normal operations

basic/lifecycle#initialization

Judged by lifecycle.initialized-notification.

LIFE-004

SHOULD NOT · binds the client

The client SHOULD NOT send requests other than pings before the server has responded to the initialize request.

basic/lifecycle#initialization

Judged by lifecycle.client-requests-before-init-response.

LIFE-005

SHOULD NOT · binds the server

The server SHOULD NOT send requests other than pings and logging before receiving the initialized notification.

basic/lifecycle#initialization

Judged by lifecycle.server-requests-before-initialized.

LIFE-006

MUST · binds the server

If the server supports the requested protocol version, it MUST respond with the same version. Otherwise, the server MUST respond with another protocol version it supports.

basic/lifecycle#version-negotiation

Judged by lifecycle.initialize-result-version.

LIFE-007

MUST · binds the client

In the initialize request, the client MUST send a protocol version it supports.

basic/lifecycle#version-negotiation

Judged by lifecycle.initialize-protocol-version.

LIFE-008

MUST · binds the client and server

Both parties MUST: Respect the negotiated protocol version

basic/lifecycle#operation

Excluded. After negotiation, neither stdio nor HTTP message payloads carry a per-message protocol version, so respect is not observable in message traffic. The one wire artifact — the HTTP MCP-Protocol-Version header — is judged under TRAN-017 and TRAN-018.

LIFE-009

MUST · binds the client and server

Both parties MUST: Only use capabilities that were successfully negotiated

basic/lifecycle#operation

Judged by lifecycle.negotiated-capabilities-only.

LIFE-010

MUST · binds the server

The server MUST respond with its own capabilities and information:

basic/lifecycle#initialization

Judged by lifecycle.initialize-result-shape.

LIFE-011

SHOULD · binds the client

This SHOULD be the latest version supported by the client.

basic/lifecycle#version-negotiation

Excluded. The client’s supported-version set is internal state with no wire footprint; the trace shows the version sent, not the versions available.

LIFE-012

SHOULD · binds the server

This SHOULD be the latest version supported by the server.

basic/lifecycle#version-negotiation

Excluded. The server’s supported-version set is internal state with no wire footprint; the trace shows the version answered, not the versions available.

LIFE-013

SHOULD · binds the client

If the client does not support the version in the server’s response, it SHOULD disconnect.

basic/lifecycle#version-negotiation

Excluded. Whether the client supports the answered version is client-internal; a continued session is only evidence of support if the premise is known. TRAN-018 warns on the adjacent observable (a mismatched MCP-Protocol-Version header).

LIFE-014

SHOULD · binds the client

For the stdio transport, the client SHOULD initiate shutdown by: First, closing the input stream to the child process (the server); Waiting for the server to exit, or sending SIGTERM if the server does not exit within a reasonable time; Sending SIGKILL if the server does not exit within a reasonable time after SIGTERM

basic/lifecycle#shutdown

Excluded. Stdin closure, signals, and process exit are host-OS actions outside the trace event vocabulary (transport-open/close/abort record that a transport ended, not who ended it or how).

LIFE-015

SHOULD · binds the client and server

Implementations SHOULD establish timeouts for all sent requests, to prevent hung connections and resource exhaustion.

basic/lifecycle#timeouts

Excluded. Checks may not consult time: trace timestamps are informational by design (determinism rule, 02-architecture.md), so timing conduct cannot be judged.

LIFE-016

SHOULD · binds the client and server

When the request has not received a success or error response within the timeout period, the sender SHOULD issue a cancellation notification for that request and stop waiting for a response.

basic/lifecycle#timeouts

Excluded. Checks may not consult time: trace timestamps are informational by design (determinism rule, 02-architecture.md), so timing conduct cannot be judged.

LIFE-017

SHOULD · binds the client and server

However, implementations SHOULD always enforce a maximum timeout, regardless of progress notifications, to limit the impact of a misbehaving client or server.

basic/lifecycle#timeouts

Excluded. Checks may not consult time: trace timestamps are informational by design (determinism rule, 02-architecture.md), so timing conduct cannot be judged.

LIFE-018

MUST · binds the client

If using HTTP, the client MUST include the MCP-Protocol-Version: <protocol-version> HTTP header on all subsequent requests to the MCP server.

basic/lifecycle#version-negotiation

Judged by transport.protocol-version-header.

LIFE-019

SHOULD · binds the client and server

SDKs and other middleware SHOULD allow these timeouts to be configured on a per-request basis.

basic/lifecycle#timeouts

Excluded. Binds an SDK’s programming interface — what its callers can configure — which has no protocol representation at all.

LIFE-020

SHOULD · binds the client and server

Implementations SHOULD be prepared to handle these error cases: Protocol version mismatch; Failure to negotiate required capabilities; Request timeouts

basic/lifecycle#error-handling

Excluded. Preparedness is a property of the implementation, not of any session it took part in: a trace that happens to contain a version mismatch shows one case handled, and a trace without one evidences nothing. Where the handling has a wire form it is judged under the clause that states it, such as the version negotiation rules.

TRAN

TRAN-001

MUST NOT · binds the client and server

Messages are delimited by newlines, and MUST NOT contain embedded newlines.

basic/transports#stdio

Excluded. Framing is enforced at capture time: the JSON Lines trace format cannot represent an embedded-newline violation, so a parseable trace is evidence the rule held. Violations surface as capture-time parse failures, not as trace findings.

TRAN-002

MUST · binds the server

Servers MUST validate the Origin header on all incoming connections to prevent DNS rebinding attacks

basic/transports#security-warning

Excluded. Judging Origin validation requires the server’s configured allowlist, which recorded traces do not carry. Enforced instead as default-on policy in mcp-everything-server and exercised by its transport integration tests (roadmap M2).

TRAN-003

MUST · binds the client and server

JSON-RPC messages MUST be UTF-8 encoded.

basic/transports

Excluded. A violation cannot be judged from a trace: trace documents are UTF-8 by construction, so recorded messages prove nothing was mis-encoded among what was recorded — and absence is not evidence, because capture tooling may drop undecodable bytes (mcp-everything-server’s tap skips non-UTF-8 SSE chunks and unparseable POST bodies). No offline check is sound.

TRAN-004

MUST NOT · binds the server

The server MUST NOT write anything to its stdout that is not a valid MCP message.

basic/transports#stdio

Judged by transport.stdio-server-output-valid.

TRAN-005

MUST NOT · binds the client

The client MUST NOT write anything to the server’s stdin that is not a valid MCP message.

basic/transports#stdio

Judged by transport.stdio-client-input-valid.

TRAN-006

MUST · binds the server

The server MUST provide a single HTTP endpoint path (hereafter referred to as the MCP endpoint) that supports both POST and GET methods.

basic/transports#streamable-http

Excluded. Recorded HTTP events carry status and conformance-relevant headers, not request lines, so endpoint topology is invisible in a trace. Enforced by mcp-everything-server’s transport integration tests (roadmap M2).

TRAN-007

MUST · binds the server

If the Origin header is present and invalid, servers MUST respond with HTTP 403 Forbidden.

basic/transports#security-warning

Excluded. Judging whether an Origin value is invalid requires the server’s configured allowlist, which recorded traces do not carry (the TRAN-002 rationale). Enforced as default-on policy in mcp-everything-server with 403 tests (roadmap M2).

TRAN-008

SHOULD · binds the server

When running locally, servers SHOULD bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)

basic/transports#security-warning

Excluded. Socket binding is deployment state with no trace footprint. mcp-everything-server defaults to a loopback bind (the –bind clap default in src/main.rs), asserted by default_bind_is_loopback in tests/cli.rs.

TRAN-009

SHOULD · binds the server

Servers SHOULD implement proper authentication for all connections

basic/transports#security-warning

Excluded. Whether authentication is properly implemented is not decidable from one session’s headers: the client’s credential is never recorded, and the server’s validation of it is internal. What a recording does show — the challenge a protected server answers with — is judged under the authorization page’s own clauses (AUTH-014, AUTH-045, AUTH-049–AUTH-051).

TRAN-010

SHOULD · binds the server

The session ID SHOULD be globally unique and cryptographically secure (e.g., a securely generated UUID, a JWT, or a cryptographic hash).

basic/transports#session-management

Excluded. Global uniqueness and entropy of an identifier cannot be established from the single sample a trace contains. mcp-everything-server’s ids are pinned to the v4-UUID shape (OS RNG) and distinctness by session_ids_are_version_4_uuids_and_distinct in tests/http_policy.rs.

TRAN-011

MUST · binds the server

The session ID MUST only contain visible ASCII characters (ranging from 0x21 to 0x7E).

basic/transports#session-management

Judged by transport.session-id-visible-ascii.

TRAN-012

MUST · binds the client

The client MUST handle the session ID in a secure manner, see Session Hijacking mitigations for more details.

basic/transports#session-management

Excluded. Secure handling (storage, exposure, logging discipline) is client-internal behavior with no wire footprint beyond the echo requirement judged under TRAN-013.

TRAN-013

MUST · binds the client

If an MCP-Session-Id is returned by the server during initialization, clients using the Streamable HTTP transport MUST include it in the MCP-Session-Id header on all of their subsequent HTTP requests.

basic/transports#session-management

Judged by transport.session-id-echoed.

TRAN-014

SHOULD · binds the server

Servers that require a session ID SHOULD respond to requests without an MCP-Session-Id header (other than initialization) with HTTP 400 Bad Request.

basic/transports#session-management

Excluded. Whether a server requires a session ID is server configuration a trace does not carry; without it, a non-400 answer to a session-less request is not evidence either way.

TRAN-015

MUST · binds the server

The server MAY terminate the session at any time, after which it MUST respond to requests containing that session ID with HTTP 404 Not Found.

basic/transports#session-management

Excluded. Session termination is server-internal state; a trace cannot distinguish a terminated session (404 required) from a live one (404 forbidden).

TRAN-016

MUST · binds the client

When a client receives HTTP 404 in response to a request containing an MCP-Session-Id, it MUST start a new session by sending a new InitializeRequest without a session ID attached.

basic/transports#session-management

Excluded. A 404 is attributed to the request it answered when the recording’s order is unambiguous, but not to the moment the client read it: a recorder logs the status as it passes, and the client may already have sent further requests on the old session. Requests after the 404 therefore do not show the client ignored it, and a client that stops instead of reconnecting sends nothing to judge.

TRAN-017

MUST · binds the client

If using HTTP, the client MUST include the MCP-Protocol-Version: <protocol-version> HTTP header on all subsequent requests to the MCP server, allowing the MCP server to respond based on the MCP protocol version.

basic/transports#protocol-version-header

Judged by transport.protocol-version-header.

TRAN-018

SHOULD · binds the client

The protocol version sent by the client SHOULD be the one negotiated during initialization.

basic/transports#protocol-version-header

Judged by transport.protocol-version-negotiated.

TRAN-019

SHOULD · binds the server

For backwards compatibility, if the server does not receive an MCP-Protocol-Version header, and has no other way to identify the version - for example, by relying on the protocol version negotiated during initialization - the server SHOULD assume protocol version 2025-03-26.

basic/transports#protocol-version-header

Excluded. Which version a server assumed is internal state; subsequent traffic does not reveal it.

TRAN-020

MUST · binds the server

If the server receives a request with an invalid or unsupported MCP-Protocol-Version, it MUST respond with 400 Bad Request.

basic/transports#protocol-version-header

Judged by transport.unsupported-version-header-rejected.

TRAN-021

SHOULD NOT · binds the client

The client MAY capture, forward, or ignore the server’s stderr output and SHOULD NOT assume stderr output indicates error conditions.

basic/transports#stdio

Excluded. How a client interprets stderr is internal, and stderr bytes are not part of the protocol trace (the trace records MCP messages and transport lifecycle, not diagnostics channels).

TRAN-022

SHOULD · binds the client

Clients SHOULD support stdio whenever possible.

basic/transports

Excluded. A client’s supported-transport surface is a property of the implementation, not of any one session; a streamable-HTTP trace says nothing about whether stdio was available.

TRAN-023

MUST · binds the client and server

Implementers who choose to support custom transports MUST ensure they preserve the JSON-RPC message format and lifecycle requirements defined by MCP.

basic/transports#custom-transports

Excluded. The trace vocabulary covers stdio and streamable HTTP; custom transports are outside the capture universe by construction (TransportKind is closed per revision).

TRAN-024

MUST · binds the client

Every JSON-RPC message sent from the client MUST be a new HTTP POST request to the MCP endpoint.

basic/transports#sending-messages-to-the-server

Excluded. Adds to TRAN-049’s verb obligation that each message ride a new POST to the MCP endpoint. A POST body is one JSON value, which a recorder writes as one payload, so more than one message in a POST is a batch array — TRAN-026 judges that. What remains — that the request was new rather than reused, and was addressed to the MCP endpoint — leaves no trace: the endpoint is not recorded.

TRAN-025

MUST · binds the client

The client MUST include an Accept header, listing both application/json and text/event-stream as supported content types.

basic/transports#sending-messages-to-the-server

Judged by transport.client-post-accept-header.

TRAN-026

MUST · binds the client

The body of the POST request MUST be a single JSON-RPC request, notification, or response.

basic/transports#sending-messages-to-the-server

Judged by transport.http-post-single-message.

TRAN-027

MUST · binds the server

If the server accepts the input, the server MUST return HTTP status code 202 Accepted with no body.

basic/transports#sending-messages-to-the-server

Judged by transport.accepted-input-status.

TRAN-028

MUST · binds the server

If the server cannot accept the input, it MUST return an HTTP error status code (e.g., 400 Bad Request).

basic/transports#sending-messages-to-the-server

Excluded. Whether input was acceptable is server-internal judgment, and the trace schema records HTTP request and response observations as independent events without request/response correlation, so which response answered which POST is not decidable offline; the official suite exercises this live and the conformance gate runs it.

TRAN-029

MUST · binds the server

If the input is a JSON-RPC request, the server MUST either return Content-Type: text/event-stream, to initiate an SSE stream, or Content-Type: application/json, to return one JSON object.

basic/transports#sending-messages-to-the-server

Judged by transport.success-content-type.

TRAN-030

MUST · binds the client

The client MUST support both these cases.

basic/transports#sending-messages-to-the-server

Excluded. What a client could have handled is client-internal capability; a trace shows the case that occurred, not the cases supported.

TRAN-031

SHOULD · binds the server

The server SHOULD immediately send an SSE event consisting of an event ID and an empty data field in order to prime the client to reconnect (using that event ID as Last-Event-ID).

basic/transports#sending-messages-to-the-server

Excluded. SSE framing is consumed at capture: the tap reassembles data: lines into messages and drops event IDs and retry fields, so SSE-frame-level conduct is invisible in a trace.

TRAN-032

SHOULD · binds the server

If the server does close the connection prior to terminating the SSE stream, it SHOULD send an SSE event with a standard retry field before closing the connection.

basic/transports#sending-messages-to-the-server

Excluded. SSE framing is consumed at capture: the tap reassembles data: lines into messages and drops event IDs and retry fields, so SSE-frame-level conduct is invisible in a trace.

TRAN-033

MUST · binds the client

The client MUST respect the retry field, waiting the given number of milliseconds before attempting to reconnect.

basic/transports#sending-messages-to-the-server

Excluded. Checks may not consult time: trace timestamps are informational by design (determinism rule, 02-architecture.md), so timing conduct cannot be judged.

TRAN-034

SHOULD · binds the server

The SSE stream SHOULD eventually include a JSON-RPC response for the JSON-RPC request sent in the POST body.

basic/transports#sending-messages-to-the-server

Excluded. Which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace.

TRAN-035

SHOULD · binds the server

These messages SHOULD relate to the originating client request.

basic/transports#sending-messages-to-the-server

Excluded. Relatedness is a semantic judgment over message content, and which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace.

TRAN-036

SHOULD · binds the server

After the JSON-RPC response has been sent, the server SHOULD terminate the SSE stream.

basic/transports#sending-messages-to-the-server

Excluded. Which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace.

TRAN-037

SHOULD NOT · binds the server

Disconnection SHOULD NOT be interpreted as the client cancelling its request.

basic/transports#sending-messages-to-the-server

Excluded. How the server interpreted a disconnect is internal state; only conduct that follows from a misinterpretation could surface, and attributing it requires the interpretation.

TRAN-038

SHOULD · binds the client

To cancel, the client SHOULD explicitly send an MCP CancelledNotification.

basic/transports#sending-messages-to-the-server

Excluded. A wish to cancel is client intent with no observable of its own; a session without a cancellation is not evidence one was wanted.

TRAN-039

MUST · binds the client

The client MUST include an Accept header, listing text/event-stream as a supported content type.

basic/transports#listening-for-messages-from-the-server

Judged by transport.client-get-accept-header.

TRAN-040

MUST · binds the server

The server MUST either return Content-Type: text/event-stream in response to this HTTP GET, or else return HTTP 405 Method Not Allowed, indicating that the server does not offer an SSE stream at this endpoint.

basic/transports#listening-for-messages-from-the-server

Judged by transport.get-content-type.

TRAN-041

SHOULD · binds the server

These messages SHOULD be unrelated to any concurrently-running JSON-RPC request from the client.

basic/transports#listening-for-messages-from-the-server

Excluded. Unrelatedness is a semantic judgment over message content, and which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace.

TRAN-042

MUST NOT · binds the server

The server MUST NOT send a JSON-RPC response on the stream unless resuming a stream associated with a previous client request.

basic/transports#listening-for-messages-from-the-server

Excluded. Which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace.

TRAN-043

MUST · binds the server

The server MUST send each of its JSON-RPC messages on only one of the connected streams; that is, it MUST NOT broadcast the same message across multiple streams.

basic/transports#multiple-connections

Excluded. Which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace. A duplicated message in the capture order is also indistinguishable from a legitimately repeated notification.

TRAN-044

MUST · binds the server

If present, the ID MUST be globally unique across all streams within that session—or all streams with that specific client, if session management is not in use.

basic/transports#resumability-and-redelivery

Excluded. SSE framing is consumed at capture: the tap reassembles data: lines into messages and drops event IDs and retry fields, so SSE-frame-level conduct is invisible in a trace.

TRAN-045

SHOULD · binds the server

Event IDs SHOULD encode sufficient information to identify the originating stream, enabling the server to correlate a Last-Event-ID to the correct stream.

basic/transports#resumability-and-redelivery

Excluded. SSE framing is consumed at capture: the tap reassembles data: lines into messages and drops event IDs and retry fields, so SSE-frame-level conduct is invisible in a trace.

TRAN-046

SHOULD · binds the client

If the client wishes to resume after a disconnection (whether due to network failure or server-initiated closure), it SHOULD issue an HTTP GET to the MCP endpoint, and include the Last-Event-ID header to indicate the last event ID it received.

basic/transports#resumability-and-redelivery

Excluded. Conditional on client intent (the wish to resume): a session that never disconnects owes nothing, and a recording cannot show a client wishing. When a resumption does occur its method and last-event-id header are both recorded, but absence proves nothing.

TRAN-047

MUST NOT · binds the server

The server MUST NOT replay messages that would have been delivered on a different stream.

basic/transports#resumability-and-redelivery

Excluded. Which HTTP stream delivered a message is not part of the trace vocabulary — events form a single capture-ordered sequence — so per-stream conduct cannot be judged from a recorded trace.

TRAN-048

SHOULD · binds the client

Clients that no longer need a particular session (e.g., because the user is leaving the client application) SHOULD send an HTTP DELETE to the MCP endpoint with the MCP-Session-Id header, to explicitly terminate the session.

basic/transports#session-management

Excluded. Conditional on client intent (no longer needing the session). A teardown DELETE is recorded when it happens — corpus/good/http-session.jsonl carries one — but a session that ends without one may simply not have finished with it, so absence is not a violation.

TRAN-049

MUST · binds the client

The client MUST use HTTP POST to send JSON-RPC messages to the MCP endpoint.

basic/transports#sending-messages-to-the-server

Judged by transport.client-messages-use-post.

TRAN-138

SHOULD · binds the client

The client SHOULD then “poll” the SSE stream by attempting to reconnect.

basic/transports#sending-messages-to-the-server

Excluded. The obligation arises when the server closes the connection without terminating the SSE stream, and that is connection- and SSE-frame-level conduct the capture consumes (TRAN-032’s reason), so no trace shows when it arose. A later reconnecting GET is equally consistent with any other reason to open one, as for TRAN-046.

TRAN-139

SHOULD · binds the server

If the server closes the connection without terminating the stream, it SHOULD follow the same polling behavior as described for POST requests: sending a retry field and allowing the client to reconnect.

basic/transports#listening-for-messages-from-the-server

Excluded. SSE framing is consumed at capture: the tap reassembles data: lines into messages and drops event IDs and retry fields, so SSE-frame-level conduct is invisible in a trace. TRAN-032 is the same rule for streams a POST opened.

TRAN-140

SHOULD · binds the client and server

Custom transports SHOULD document their specific connection establishment and message exchange patterns to aid interoperability.

basic/transports#custom-transports

Excluded. Binds a transport’s documentation, not its messages: the artefact the clause asks for is a document, and no session can be evidence about whether one exists. Custom transports are outside the capture universe besides (TRAN-023).

PING

PING-001

MUST · binds the client and server

The receiver MUST respond promptly with an empty response:

basic/utilities/ping#behavior-requirements

Judged by ping.empty-result.

PING-002

SHOULD · binds the client and server

Implementations SHOULD periodically issue pings to detect connection health

basic/utilities/ping#implementation-considerations

Excluded. “Periodically” is a rate over wall-clock time, and checks may not consult time — the limit LIFE-015 records. A recording would have to show the interval between pings against the length of the session, and it carries neither: a session with no ping and one with few are both what a conforming implementation produces over a short enough connection.

PING-003

SHOULD · binds the client and server

The frequency of pings SHOULD be configurable

basic/utilities/ping#implementation-considerations

Excluded. Binds the implementation’s configuration surface — what its operator can set — which has no protocol representation (LIFE-019’s boundary). A recording shows the pings one configuration produced, never whether another was available.

PING-004

SHOULD · binds the client and server

Timeouts SHOULD be appropriate for the network environment

basic/utilities/ping#implementation-considerations

Excluded. A timeout is a duration held inside the sender, and checks may not consult time (LIFE-015). A recording would have to carry the deadline the sender held a ping to and the network it was chosen for; it shows a ping answered or not, and nothing of either.

PING-005

SHOULD · binds the client and server

Excessive pinging SHOULD be avoided to reduce network overhead

basic/utilities/ping#implementation-considerations

Excluded. “Excessive” is a rate — pings per unit of time — and checks may not consult time (LIFE-015). No count of pings alone separates a flood from a long session checking its connection, the same limit PROG-018 records for rate limiting.

PING-006

SHOULD · binds the client and server

Timeouts SHOULD be treated as connection failures

basic/utilities/ping#error-handling

Excluded. The antecedent, a ping timing out, is the sender’s own deadline expiring, which no message records and checks may not compute from timestamps (LIFE-015). The consequence, treating the connection as failed, is at most a transport-close lifecycle event, which says that a transport ended and not why; a recording cannot tell a connection dropped for a timeout from one closed at the end of a session.

PING-007

SHOULD · binds the client and server

Implementations SHOULD log ping failures for diagnostics

basic/utilities/ping#error-handling

Excluded. Logging is local diagnostics with no wire footprint (CANC-024’s boundary): nothing an implementation writes to its own log is a protocol message, so no recording contains it.

PROG

PROG-009

MUST · binds the client and server

Progress tokens MUST be a string or integer value

basic/utilities/progress#progress-flow

Judged by progress.token-string-or-integer.

PROG-010

MUST · binds the client and server

Progress tokens can be chosen by the sender using any means, but MUST be unique across all active requests.

basic/utilities/progress#progress-flow

Judged by progress.token-unique-among-active-requests.

PROG-011

MUST · binds the client and server

The progress value MUST increase with each notification, even if the total is unknown.

basic/utilities/progress#progress-flow

Judged by progress.value-strictly-increases.

PROG-012

SHOULD · binds the client and server

The message field SHOULD provide relevant human readable progress information.

basic/utilities/progress#progress-flow

Excluded. Whether a message is relevant and human readable is a judgment about its meaning, not its shape; any string satisfies the schema, and no mechanical reading of one decides relevance. The same sentence is PROG-004 at 2026-07-28, excluded for the same reason.

PROG-013

MUST · binds the client and server

Progress notifications MUST only reference tokens that: Were provided in an active request; Are associated with an in-progress operation

basic/utilities/progress#behavior-requirements

Judged by progress.token-issued-in-session, progress.stops-after-completion.

PROG-014

MUST · binds the client and server

For task-augmented requests, the progressToken provided in the original request MUST continue to be used for progress notifications throughout the task’s lifetime, even after the CreateTaskResult has been returned.

basic/utilities/progress#behavior-requirements

Judged by progress.task-token-unchanged.

PROG-015

MUST · binds the client and server

Progress notifications for tasks MUST use the same progressToken that was provided in the initial task-augmented request

basic/utilities/progress#behavior-requirements

Judged by progress.task-token-unchanged.

PROG-016

MUST · binds the client and server

Progress notifications for tasks MUST stop after the task reaches a terminal status (completed, failed, or cancelled)

basic/utilities/progress#behavior-requirements

Judged by progress.stops-after-completion.

PROG-017

SHOULD · binds the client and server

Senders and receivers SHOULD track active progress tokens

basic/utilities/progress#implementation-notes

Excluded. Tracking is bookkeeping inside each party, and a recording carries no message that shows a token being tracked or forgotten. Its wire consequences are the MUST rows beside it, which are judged: a token reused while its request is active (PROG-010), a token no request provided and progress for a finished request (PROG-013, PROG-016, PROG-019).

PROG-018

SHOULD · binds the client and server

Both parties SHOULD implement rate limiting to prevent flooding

basic/utilities/progress#implementation-notes

Excluded. A rate is messages per unit of time, and checks may not consult time — the limit LIFE-015 records. No count of notifications alone separates a flood from a long operation reporting often.

PROG-019

MUST · binds the client and server

Progress notifications MUST stop after completion

basic/utilities/progress#implementation-notes

Judged by progress.stops-after-completion.

CANC

CANC-018

MUST · binds the client and server

Cancellation notifications MUST only reference requests that: Were previously issued in the same direction; Are believed to still be in-progress

basic/utilities/cancellation#behavior-requirements

Judged by cancellation.references-issued-request.

CANC-019

MUST NOT · binds the client

The initialize request MUST NOT be cancelled by clients

basic/utilities/cancellation#behavior-requirements

Judged by cancellation.initialize-not-cancelled.

CANC-020

MUST · binds the client and server

For task-augmented requests, the tasks/cancel request MUST be used instead of the notifications/cancelled notification.

basic/utilities/cancellation#behavior-requirements

Judged by cancellation.task-cancelled-by-request.

CANC-021

SHOULD · binds the client and server

Receivers of cancellation notifications SHOULD: Stop processing the cancelled request; Free associated resources; Not send a response for the cancelled request

basic/utilities/cancellation#behavior-requirements

Judged by cancellation.no-response-after-cancellation.

CANC-022

SHOULD · binds the client and server

The sender of the cancellation notification SHOULD ignore any response to the request that arrives afterward

basic/utilities/cancellation#behavior-requirements

Excluded. Ignoring a response is the absence of a reaction inside the sender. A recording would have to carry a message the sender sends because it acted on the late response, and the protocol defines none: nothing a party does with a response it received reaches the wire.

CANC-023

MUST · binds the client and server

Both parties MUST handle these race conditions gracefully:

basic/utilities/cancellation#timing-considerations

Excluded. Graceful handling is internal; the race itself is what a recording shows, and the checks are built not to convict it — cancellation.no-response-after-cancellation reports an answer to a cancelled request only once the receiver has demonstrably read the cancellation, and the conforming stdio-cancellation trace pins the answer that crosses one. A recording would have to carry a message the specification defines as ungraceful handling, and it defines none; a party that failed to handle the race would show it through some other clause’s violation, judged there.

CANC-024

SHOULD · binds the client and server

Both parties SHOULD log cancellation reasons for debugging

basic/utilities/cancellation#implementation-notes

Excluded. Logging is local diagnostics with no wire footprint: nothing an implementation writes to its own log is a protocol message, so no recording contains it.

CANC-025

SHOULD · binds the client

Application UIs SHOULD indicate when cancellation is requested

basic/utilities/cancellation#implementation-notes

Excluded. User-interface presentation, out by strategy rule 2: what an application shows its user is not a protocol message, so no recording carries it.

CANC-026

SHOULD · binds the client and server

Invalid cancellation notifications SHOULD be ignored: Unknown request IDs; Already completed requests; Malformed notifications

basic/utilities/cancellation#error-handling

Excluded. Ignoring a notification is the absence of a reaction, which a trace cannot tell apart from the notification never mattering: a recording would have to carry a message the receiver sends because it did not ignore the notification, and the protocol defines none (answering a notification is forbidden anyway, BASE-011). The party that sent the invalid notification is judged instead, where it can be: CANC-018 for a cancellation naming a request its sender never issued in the session, CANC-019 for one naming initialize.

TOOL

TOOL-001

MUST · binds the server

Servers that support tools MUST declare the tools capability:

server/tools#capabilities

Judged by tools.capability-declared.

TOOL-002

SHOULD · binds the server · only once server.tools.listChanged is negotiated

When the list of available tools changes, servers that declared the listChanged capability SHOULD send a notification:

server/tools#list-changed-notification

Excluded. The trigger condition — the tool list actually changing — is server-internal state a recorded trace cannot evidence, so absence of the notification is never proof of violation.

TOOL-003

MUST · binds the server · only once server.tools is negotiated

inputSchema: JSON Schema defining expected parameters; MUST be a valid JSON Schema object (not null)

server/tools#tool

Judged by tools.input-schema-object.

TOOL-004

MUST · binds the client

For trust & safety and security, clients MUST consider tool annotations to be untrusted unless they come from trusted servers.

server/tools#tool

Excluded. How a client weighs annotations is internal trust policy with no wire footprint.

TOOL-005

SHOULD · binds the server · only once server.tools is negotiated

Tool names SHOULD be between 1 and 128 characters in length (inclusive).

server/tools#tool-names

Judged by tools.name-length.

TOOL-006

SHOULD · binds the server · only once server.tools is negotiated

The following SHOULD be the only allowed characters: uppercase and lowercase ASCII letters (A-Z, a-z), digits (0-9), underscore (_), hyphen (-), and dot (.)

server/tools#tool-names

Judged by tools.name-charset.

TOOL-007

SHOULD NOT · binds the server · only once server.tools is negotiated

Tool names SHOULD NOT contain spaces, commas, or other special characters.

server/tools#tool-names

Judged by tools.name-charset.

TOOL-008

SHOULD · binds the server · only once server.tools is negotiated

Tool names SHOULD be unique within a server.

server/tools#tool-names

Judged by tools.name-unique.

TOOL-009

SHOULD · binds the server · only once server.tools is negotiated

Servers that use embedded resources SHOULD implement the resources capability:

server/tools#embedded-resources

Judged by tools.embedded-resource-capability.

TOOL-010

SHOULD · binds the server · only once server.tools is negotiated

For backwards compatibility, a tool that returns structured content SHOULD also return the serialized JSON in a TextContent block.

server/tools#structured-content

Judged by tools.structured-content-text.

TOOL-011

MUST · binds the server · only once server.tools is negotiated

If an output schema is provided: Servers MUST provide structured results that conform to this schema.

server/tools#output-schema

Judged by tools.output-schema-structured-result.

TOOL-012

MUST · binds the server · only once server.tools is negotiated

Servers MUST: Validate all tool inputs; Implement proper access controls; Rate limit tool invocations; Sanitize tool outputs

server/tools#security-considerations

Excluded. Input validation, access control, rate limiting, and output sanitization are server-internal enforcement without a deterministic wire signature. Of the four duties, mcp-everything-server implements and tests input validation (tests/roundtrip.rs: tool_call_with_missing_required_argument_is_a_protocol_error and neighbors); access control beyond the transport-layer Host/Origin gate, rate limiting, and output sanitization are not in its scope — it serves fixed synthetic fixtures to a loopback-only harness.

TOOL-013

SHOULD · binds the client and server · only once server.tools is negotiated

Tool names SHOULD be considered case-sensitive.

server/tools#tool-names

Excluded. Name-comparison semantics are consumer-internal; tools.name-unique (TOOL-008) applies case-sensitive comparison in accordance with this clause.

TOOL-014

SHOULD · binds the client · only once server.tools is negotiated

Clients SHOULD validate structured results against this schema.

server/tools#output-schema

Excluded. Client-side validation has no wire footprint; the server-side half of the contract is TOOL-011’s check.

TOOL-015

SHOULD · binds the client · only once server.tools is negotiated

For trust & safety and security, there SHOULD always be a human in the loop with the ability to deny tool invocations.

server/tools#user-interaction-model

Excluded. A host application’s approval UX is outside the protocol session; a trace shows invocations that happened, not the approvals that gated them.

TOOL-047

SHOULD · binds the client

Applications SHOULD: Provide UI that makes clear which tools are being exposed to the AI model; Insert clear visual indicators when tools are invoked; Present confirmation prompts to the user for operations, to ensure a human is in the loop

server/tools#user-interaction-model

Excluded. Binds the application’s user interface — what it shows, when it asks, whether a person is there. None of it is a message, and MCP deliberately does not mandate an interaction model.

TOOL-048

SHOULD · binds the client

Clients SHOULD provide tool execution errors to language models to enable self-correction.

server/tools#error-handling

Excluded. Binds what the client hands to a language model, which is downstream of the session entirely.

TOOL-049

SHOULD · binds the client

Clients SHOULD: Prompt for user confirmation on sensitive operations; Show tool inputs to the user before calling the server, to avoid malicious or accidental data exfiltration; Validate tool results before passing to LLM; Implement timeouts for tool calls; Log tool usage for audit purposes

server/tools#security-considerations

Excluded. Five client-side practices — confirmation prompts, showing inputs, validating results, timeouts, audit logs. Each happens inside the client or in its UI; none is a message.

RES

RES-001

MUST · binds the server

Servers that support resources MUST declare the resources capability:

server/resources#capabilities

Judged by resources.capability-declared.

RES-002

SHOULD · binds the server · only once server.resources.listChanged is negotiated

When the list of available resources changes, servers that declared the listChanged capability SHOULD send a notification:

server/resources#list-changed-notification

Excluded. The trigger condition — the resource list actually changing — is server-internal state a recorded trace cannot evidence.

RES-003

SHOULD · binds the server · only once server.resources is negotiated

Servers SHOULD use this scheme only when the client is able to fetch and load the resource directly from the web on its own—that is, it doesn’t need to read the resource via the MCP server.

server/resources#https//

Excluded. Whether the client can fetch a URI on its own is a property of the client’s environment, not of the recorded session.

RES-004

MUST · binds the server · only once server.resources is negotiated

Custom URI schemes MUST be in accordance with RFC3986, taking the above guidance in to account.

server/resources#custom-uri-schemes

Judged by resources.uri-scheme-rfc3986.

RES-005

MUST · binds the server

Servers MUST validate all resource URIs

server/resources#security-considerations

Excluded. URI validation is server-internal enforcement; a trace shows the URIs exchanged, not whether the server vetted them. mcp-everything-server’s read path is fail-closed — unknown or malformed URIs resolve to None — asserted by template_rejects_malformed_instantiations (src/resources.rs) and the unknown-URI protocol-error assertion in resources_surface_matches_the_scenarios (tests/roundtrip.rs).

RES-006

MUST · binds the server · only once server.resources is negotiated

Binary data MUST be properly encoded

server/resources#security-considerations

Judged by resources.blob-base64.

RES-007

SHOULD · binds the server · only once server.resources is negotiated

For other use cases, servers SHOULD prefer to use another URI scheme, or define a custom one, even if the server will itself be downloading resource contents over the internet.

server/resources#https//

Excluded. The premise — whether the client could fetch the URI directly — is a property of the client’s environment, not of the session (the RES-003 argument).

RES-008

SHOULD · binds the server · only once server.resources is negotiated

Servers SHOULD return standard JSON-RPC errors for common failure cases: Resource not found: -32002; Internal errors: -32603

server/resources#error-handling

Excluded. Whether a failure case actually occurred (the resource was absent, an internal fault happened) is server-side ground truth a trace does not carry.

RES-009

SHOULD · binds the server

Access controls SHOULD be implemented for sensitive resources

server/resources#security-considerations

Excluded. Which resources are sensitive and what controls guard them is deployment policy with no per-session observable.

RES-010

SHOULD · binds the server

Resource permissions SHOULD be checked before operations

server/resources#security-considerations

Excluded. Permission checks are server-internal enforcement; a trace shows the operations served, not the checks that admitted them.

PROM

PROM-001

MUST · binds the server

Servers that support prompts MUST declare the prompts capability during initialization:

server/prompts#capabilities

Judged by prompts.capability-declared.

PROM-002

SHOULD · binds the server · only once server.prompts.listChanged is negotiated

When the list of available prompts changes, servers that declared the listChanged capability SHOULD send a notification:

server/prompts#list-changed-notification

Excluded. The trigger condition — the prompt list actually changing — is server-internal state a recorded trace cannot evidence.

PROM-003

MUST · binds the server · only once server.prompts is negotiated

The image data MUST be base64-encoded and include a valid MIME type.

server/prompts#image-content

Judged by prompts.image-content-encoding.

PROM-004

MUST · binds the server · only once server.prompts is negotiated

The audio data MUST be base64-encoded and include a valid MIME type.

server/prompts#audio-content

Judged by prompts.audio-content-encoding.

PROM-005

MUST · binds the server · only once server.prompts is negotiated

Resources can contain either text or binary (blob) data and MUST include: A valid resource URI; The appropriate MIME type; Either text content or base64-encoded blob data

server/prompts#embedded-resources

Judged by prompts.embedded-resource-shape.

PROM-006

MUST · binds the client and server

Implementations MUST carefully validate all prompt inputs and outputs to prevent injection attacks or unauthorized access to resources.

server/prompts#security

Excluded. Validation thoroughness is implementation-internal; a trace shows the prompt traffic, not the vetting applied to it.

PROM-007

SHOULD · binds the server · only once server.prompts is negotiated

Servers SHOULD return standard JSON-RPC errors for common failure cases: Invalid prompt name: -32602 (Invalid params); Missing required arguments: -32602 (Invalid params); Internal errors: -32603 (Internal error)

server/prompts#error-handling

Excluded. Whether a failure case actually occurred (the name was invalid, an argument was missing) is server-side ground truth a trace does not carry.

PROM-008

SHOULD · binds the server · only once server.prompts is negotiated

Servers SHOULD validate prompt arguments before processing

server/prompts#implementation-considerations

Judged by prompts.arguments-validated.

PROM-009

SHOULD · binds the client · only once server.prompts is negotiated

Clients SHOULD handle pagination for large prompt lists

server/prompts#implementation-considerations

Excluded. Client-side pagination handling is internal; a session whose lists fit one page exercises nothing.

PROM-010

SHOULD · binds the client and server

Both parties SHOULD respect capability negotiation

server/prompts#implementation-considerations

Excluded. Mechanized at the protocol level by LIFE-009’s negotiated-capabilities-only check; this restatement adds no separately observable conduct.

LOG

LOG-001

MUST · binds the server

Servers that emit log message notifications MUST declare the logging capability:

server/utilities/logging#capabilities

Judged by logging.capability-declared.

LOG-002

MUST NOT · binds the server · only once server.logging is negotiated

Log messages MUST NOT contain: Credentials or secrets; Personal identifying information; Internal system details that could aid attacks

server/utilities/logging#security

Excluded. Deciding whether free-form log data contains secrets or PII is semantic content analysis, not structural validation; offline heuristics would produce unsound, unfalsifiable verdicts — a fixed pattern list is deterministic but proves nothing about what it misses.

LOG-003

SHOULD · binds the server · only once server.logging is negotiated

Servers SHOULD return standard JSON-RPC errors for common failure cases: Invalid log level: -32602 (Invalid params); Configuration errors: -32603 (Internal error)

server/utilities/logging#error-handling

Excluded. Whether a failure case actually occurred (the level was invalid for this server, configuration failed) is server-side ground truth a trace does not carry.

LOG-004

SHOULD · binds the server · only once server.logging is negotiated

Servers SHOULD: Rate limit log messages; Include relevant context in data field; Use consistent logger names; Remove sensitive information

server/utilities/logging#implementation-considerations

Excluded. Rate policy, context relevance, naming consistency, and redaction are semantic internals (the LOG-002 argument).

LOG-005

SHOULD · binds the client and server · only once server.logging is negotiated

Implementations SHOULD: Rate limit messages; Validate all data fields; Control log access; Monitor for sensitive content

server/utilities/logging#security

Excluded. Rate limiting, validation, access control, and monitoring are implementation-internal enforcement without trace-level observables.

COMP

COMP-001

MUST · binds the server

Servers that support completions MUST declare the completions capability:

server/utilities/completion#capabilities

Judged by completion.capability-declared.

COMP-002

MUST · binds the client and server

Implementations MUST: Validate all completion inputs; Implement appropriate rate limiting; Control access to sensitive suggestions; Prevent completion-based information disclosure

server/utilities/completion#security

Excluded. Input validation, rate limiting, and access control are implementation-internal enforcement without a deterministic wire signature.

COMP-003

SHOULD · binds the server · only once server.completions is negotiated

Servers SHOULD return standard JSON-RPC errors for common failure cases: Method not found: -32601 (Capability not supported); Invalid prompt name: -32602 (Invalid params); Missing required arguments: -32602 (Invalid params); Internal errors: -32603 (Internal error)

server/utilities/completion#error-handling

Excluded. Whether a failure case actually occurred is server-side ground truth a trace does not carry.

COMP-004

SHOULD · binds the server · only once server.completions is negotiated

Servers SHOULD: Return suggestions sorted by relevance; Implement fuzzy matching where appropriate; Rate limit completion requests; Validate all inputs

server/utilities/completion#implementation-considerations

Excluded. Relevance ordering, fuzziness, rate policy, and input vetting are semantic internals without trace-level observables.

COMP-005

SHOULD · binds the client · only once server.completions is negotiated

Clients SHOULD: Debounce rapid completion requests; Cache completion results where appropriate; Handle missing or partial results gracefully

server/utilities/completion#implementation-considerations

Excluded. Debouncing and caching are client-internal and timing-shaped; checks may not consult time (determinism rule).

PAGE

PAGE-001

MUST NOT · binds the client

Page size is determined by the server, and clients MUST NOT assume a fixed page size

server/utilities/pagination#pagination-model

Excluded. What a client assumes is internal state; the assumption has no wire footprint (MCP pagination requests carry no size parameter to inspect).

PAGE-002

MUST · binds the client

Clients MUST treat cursors as opaque tokens: Don’t make assumptions about cursor format; Don’t attempt to parse or modify cursors; Don’t persist cursors across sessions

server/utilities/pagination#implementation-guidelines

Judged by pagination.cursor-opacity.

PAGE-003

SHOULD · binds the server

Invalid cursors SHOULD result in an error with code -32602 (Invalid params).

server/utilities/pagination#error-handling

Judged by pagination.invalid-cursor-rejected.

PAGE-004

SHOULD · binds the server

Servers SHOULD: Provide stable cursors; Handle invalid cursors gracefully

server/utilities/pagination#implementation-guidelines

Excluded. Cursor stability is cross-request server behavior over hidden state; gracefulness on invalid cursors requires knowing a cursor was invalid (the PAGE-003 argument).

PAGE-005

SHOULD · binds the client

Clients SHOULD: Treat a missing nextCursor as the end of results; Support both paginated and non-paginated flows

server/utilities/pagination#implementation-guidelines

Excluded. How a client interprets a missing cursor, and what flows it supports, is client-internal; the wire-visible cursor discipline is PAGE-002’s check.

ELIC

ELIC-001

MUST NOT · binds the server

Servers MUST NOT use form mode elicitation to request sensitive information such as passwords, API keys, access tokens, or payment credentials

client/elicitation#user-interaction-model

Excluded. Whether a requested field is “sensitive information” — the page’s own definition is “secrets and credentials that grant access or authorize transactions” — is a judgement about meaning, not syntax: a schema property named token may be a display preference and one named answer may collect a password. A check would have to guess from field names, and a guess convicts conforming servers. The server’s author decides it; nothing in the message settles it.

ELIC-002

MUST · binds the server

Servers MUST use URL mode for interactions involving such sensitive information

client/elicitation#user-interaction-model

Excluded. The counterpart of the form mode prohibition, and blocked by the same judgement: that an interaction “involves such sensitive information” is a fact about what the user will be asked for, which no message states, so a form mode request cannot be shown to have needed URL mode.

ELIC-003

MUST · binds the client

MCP clients MUST: Provide UI that makes it clear which server is requesting information; Respect user privacy and provide clear decline and cancel options; For form mode, allow users to review and modify their responses before sending; For URL mode, clearly display the target domain/host and gather user consent before navigation to the target URL

client/elicitation#user-interaction-model

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-004

MUST · binds the client

Clients that support elicitation MUST declare the elicitation capability during initialization:

client/elicitation#capabilities

Judged by elicitation.client-declares-capability.

ELIC-005

MUST · binds the client

Clients declaring the elicitation capability MUST support at least one mode (form or url).

client/elicitation#capabilities

Excluded. No declaration can violate it on the wire. The page makes an elicitation object naming neither mode “equivalent to declaring support for form mode only”, so every declared elicitation capability names at least one mode. What remains is whether the client can actually handle the mode it declared, which is internal: a client that cannot still returns a well-formed decline or cancel.

ELIC-006

MUST NOT · binds the server

Servers MUST NOT send elicitation requests with modes that are not supported by the client.

client/elicitation#capabilities

Judged by elicitation.mode-supported.

ELIC-007

MUST · binds the server

All elicitation requests MUST include the following parameters:

client/elicitation#elicitation-requests

Judged by elicitation.request-parameters.

ELIC-008

MUST · binds the client

Clients MUST treat requests without a mode field as form mode.

client/elicitation#elicitation-requests

Excluded. A reading, not an act, like MRTR-007: a client’s answers to a form mode request and to one without mode are the same messages (accept with content, decline, cancel), and content is optional in the result, so no answer shows which reading the client took. The server half — that such a request is form mode — is what elicitation.mode-supported and elicitation.form-schema-present apply.

ELIC-009

MUST · binds the server

Form mode elicitation requests MUST either specify mode: "form" or omit the mode field, and include these additional parameters:

client/elicitation#form-mode-elicitation-requests

Judged by elicitation.form-schema-present.

ELIC-010

SHOULD · binds the client

Clients that support defaults SHOULD pre-populate form fields with these values.

client/elicitation#requested-schema

Excluded. UI behaviour: pre-populating a form is what the user sees before submitting. The submitted content cannot show it — the user may change or clear every default — so no message carries the clause.

ELIC-011

MUST · binds the server

URL mode elicitation requests MUST specify mode: "url", a message, and include these additional parameters:

client/elicitation#url-mode-elicitation-requests

Judged by elicitation.url-parameters-with-id.

ELIC-012

MUST · binds the server

The url parameter MUST contain a valid URL.

client/elicitation#url-mode-elicitation-requests

Judged by elicitation.url-valid.

ELIC-013

MUST · binds the server

Servers sending notifications: MUST only send the notification to the client that initiated the elicitation request.

client/elicitation#completion-notifications-for-url-mode-elicitation

Excluded. Which client initiated an elicitation is a fact across connections, and a recording holds one session. A completion sent to the wrong client appears in that client’s recording as a notification for an id its session never established — the observation elicitation.complete-notification-id judges under the clause that names the id, because the one recording cannot say which of the two rules was broken.

ELIC-014

MUST · binds the server

Servers sending notifications: MUST include the elicitationId established in the original elicitation/create request.

client/elicitation#completion-notifications-for-url-mode-elicitation

Judged by elicitation.complete-notification-id.

ELIC-015

MUST · binds the client

Clients: MUST ignore notifications referencing unknown or already-completed IDs.

client/elicitation#completion-notifications-for-url-mode-elicitation

Excluded. Ignoring leaves no trace: a client that ignored a notification for an unknown or completed id and one that acted on it internally send the same messages afterwards.

ELIC-016

SHOULD · binds the client

Clients: SHOULD still provide manual controls that let the user retry or cancel the original request (or otherwise resume interacting with the client) if the notification never arrives.

client/elicitation#completion-notifications-for-url-mode-elicitation

Excluded. UI behaviour: the controls the client offers its user. The wire shows only whether a retry or cancellation was eventually sent, which a user may decline to do whatever controls exist.

ELIC-017

MUST NOT · binds the server

The server MUST NOT return this error except when URL mode elicitation is required.

client/elicitation#url-elicitation-required-error

Excluded. Its condition — that URL mode elicitation is required before the request can proceed — is the server’s own determination, which no message states; a -32042 cannot be shown to be unwarranted.

ELIC-018

MUST · binds the server

The error MUST include a list of elicitations that are required to complete before the original can be retried.

client/elicitation#url-elicitation-required-error

Judged by elicitation.url-required-error-lists.

ELIC-019

MUST · binds the server

Any elicitations returned in the error MUST be URL mode elicitations and have an elicitationId property.

client/elicitation#url-elicitation-required-error

Judged by elicitation.url-required-error-url-mode.

ELIC-020

MUST · binds the server

Servers MUST return standard JSON-RPC errors for common failure cases: When a request cannot be processed until an elicitation is completed: -32042 (URLElicitationRequiredError)

client/elicitation#error-handling

Excluded. Its antecedent — that a request cannot be processed until an elicitation completes — is the server’s determination, and the page lets it ask by other means (it “MAY return” the error, or may send the elicitation while the request is pending). A server that chose another way sends no error, and nothing in the trace says it should have.

ELIC-021

MUST · binds the client

Clients MUST return standard JSON-RPC errors for common failure cases: Server sends an elicitation/create request with a mode not declared in client capabilities: -32602 (Invalid params)

client/elicitation#error-handling

Judged by elicitation.undeclared-mode-rejected.

ELIC-022

MUST · binds the server

Servers implementing elicitation MUST securely associate this state with individual users following the guidelines in the security best practices document. Specifically: State MUST NOT be associated with session IDs alone; State storage MUST be protected against unauthorized access; For remote MCP servers, user identification MUST be derived from credentials acquired via MCP authorization when possible (e.g. sub claim)

client/elicitation#statefulness

Excluded. Server-internal state handling. How a server stores per-user state, protects it and binds it to an identity happens behind its own storage and authorization, and the identity it binds to is established outside the session’s messages, by MCP authorization (whose pages this registry keeps out of scope, sources.json). Verified, where verified at all, by the server’s own security review and tests; at 2026-07-28 the state a client carries is requestState, opaque by construction (MRTR-008).

ELIC-023

MUST NOT · binds the server

MCP servers MUST NOT rely on URL mode elicitation to authorize users for themselves.

client/elicitation#url-mode-elicitation-for-oauth-flows

Excluded. Concerns what the server treats as authorization of its own users — an internal decision. A URL mode elicitation used to sign a user in to the server looks on the wire exactly like one used for a third-party grant; the difference is what the server does with the outcome.

ELIC-024

MUST NOT · binds the server

The third-party credentials MUST NOT transit through the MCP client

client/elicitation#understanding-the-distinction

Excluded. Third-party credentials are opaque strings whose provenance no message declares: a check cannot tell one in a result from any other string, and by design they never enter the session at all. The obligation is the server’s — credentials could only transit the client if the server sent them — and it is kept by the flow the server builds, outside the recording.

ELIC-025

MUST NOT · binds the server

The MCP server MUST NOT use the client’s credentials for the third-party service

client/elicitation#understanding-the-distinction

Excluded. Token passthrough happens between the server and the third-party service, outside the MCP session; the recording holds only the client–server exchange, in which the client’s credentials appear (as HTTP authorization) whether or not the server reuses them elsewhere.

ELIC-026

MUST · binds the server

The user MUST authorize the MCP server directly

client/elicitation#understanding-the-distinction

Excluded. By the clause’s own words the interaction “happens outside the MCP protocol, without involving the MCP client”: it is between the user’s browser and the server or a third-party authorization server, so a recording of the MCP session cannot contain it.

ELIC-027

MUST NOT · binds the server

The MCP server MUST NOT transmit credentials obtained through URL mode elicitation to the MCP client.

client/elicitation#understanding-the-distinction

Excluded. The same barrier as the transit clause: a credential obtained through URL mode elicitation is an opaque string whose provenance no message declares, so a check cannot tell one in a result from any other value the server returns.

ELIC-028

MUST · binds the server

Servers MUST bind elicitation requests to the client and user identity

client/elicitation#security-considerations

Excluded. Binding is server-internal state, and the identity it binds to is established by authorization outside the session’s messages, so no message shows whether an elicitation was bound to it.

ELIC-029

MUST · binds the client

Clients MUST provide clear indication of which server is requesting information

client/elicitation#security-considerations

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-030

SHOULD · binds the client

Clients SHOULD implement user approval controls

client/elicitation#security-considerations

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-031

SHOULD · binds the client

Clients SHOULD allow users to decline elicitation requests at any time

client/elicitation#security-considerations

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-032

SHOULD · binds the client

Clients SHOULD implement rate limiting

client/elicitation#security-considerations

Excluded. A request schedule: rate limiting is measured in elapsed time, which checks may not consult (LIFE-015, the time boundary in 02-architecture.md), and its threshold is the client’s own policy.

ELIC-033

SHOULD · binds the client

Clients SHOULD present elicitation requests in a way that makes it clear what information is being requested and why

client/elicitation#security-considerations

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-034

MUST NOT · binds the server

MCP servers requesting elicitation: MUST NOT include sensitive information about the end-user, including credentials, personal identifiable information, etc., in the URL sent to the client in a URL elicitation request.

client/elicitation#safe-url-handling

Excluded. Whether a URL’s path or query carries “sensitive information about the end-user” is a semantic judgement about opaque values — an identifier in a query may be a random nonce or an email address — so a check would convict on a guess. The page’s own examples put an elicitationId in the query, which is exactly the kind of value a pattern would misread.

ELIC-035

MUST NOT · binds the server

MCP servers requesting elicitation: MUST NOT provide a URL which is pre-authenticated to access a protected resource, as the URL could be used to impersonate the user by a malicious client.

client/elicitation#safe-url-handling

Excluded. Whether a URL grants access without further authentication is a property of the server it points to, observable only by dereferencing it — which a validator must not do (the client rules on the same page forbid even pre-fetching it), and which a recording does not contain.

ELIC-036

SHOULD NOT · binds the server

MCP servers requesting elicitation: SHOULD NOT include URLs intended to be clickable in any field of a form mode elicitation request.

client/elicitation#safe-url-handling

Excluded. Intent: the clause forbids URLs “intended to be clickable”, and a form’s message or a field’s description may mention a URL for reference. A check for URL-shaped text would convict a server for mentioning a link, and the intent itself is not on the wire.

ELIC-037

SHOULD · binds the server

MCP servers requesting elicitation: SHOULD use HTTPS URLs for non-development environments.

client/elicitation#safe-url-handling

Excluded. Its antecedent — that this is a non-development environment — is not in the trace. A loopback host suggests development without proving it, and a staging or internal host proves nothing either way, so an http URL is not by itself evidence of a violation. The scheme is recorded; the environment is not.

ELIC-038

MUST · binds the client

Clients implementing URL mode elicitation MUST handle URLs carefully to prevent users from unknowingly clicking malicious links.

client/elicitation#safe-url-handling

Excluded. Binds what the client does with a URL outside the MCP session — fetching it, opening it, displaying it — none of which is a message the session carries. The reference host never dereferences an elicitation URL: it answers URL mode from its interaction script and records the id (answer_elicitation, crates/mcp-reference-host/src/handler.rs).

ELIC-039

MUST NOT · binds the client

When handling URL mode elicitation requests, MCP clients: MUST NOT automatically pre-fetch the URL or any of its metadata.

client/elicitation#safe-url-handling

Excluded. Binds what the client does with a URL outside the MCP session — fetching it, opening it, displaying it — none of which is a message the session carries. The reference host never dereferences an elicitation URL: it answers URL mode from its interaction script and records the id (answer_elicitation, crates/mcp-reference-host/src/handler.rs).

ELIC-040

MUST NOT · binds the client

When handling URL mode elicitation requests, MCP clients: MUST NOT open the URL without explicit consent from the user.

client/elicitation#safe-url-handling

Excluded. Binds what the client does with a URL outside the MCP session — fetching it, opening it, displaying it — none of which is a message the session carries. The reference host never dereferences an elicitation URL: it answers URL mode from its interaction script and records the id (answer_elicitation, crates/mcp-reference-host/src/handler.rs).

ELIC-041

MUST · binds the client

When handling URL mode elicitation requests, MCP clients: MUST show the full URL to the user for examination before consent.

client/elicitation#safe-url-handling

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-042

MUST · binds the client

When handling URL mode elicitation requests, MCP clients: MUST open the URL provided by the server in a secure manner that does not enable the client or LLM to inspect the content or user inputs.

client/elicitation#safe-url-handling

Excluded. Binds what the client does with a URL outside the MCP session — fetching it, opening it, displaying it — none of which is a message the session carries. The reference host never dereferences an elicitation URL: it answers URL mode from its interaction script and records the id (answer_elicitation, crates/mcp-reference-host/src/handler.rs).

ELIC-043

SHOULD · binds the client

When handling URL mode elicitation requests, MCP clients: SHOULD highlight the domain of the URL to mitigate subdomain spoofing.

client/elicitation#safe-url-handling

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-044

SHOULD · binds the client

When handling URL mode elicitation requests, MCP clients: SHOULD have warnings for ambiguous/suspicious URIs (i.e., containing Punycode).

client/elicitation#safe-url-handling

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-045

SHOULD NOT · binds the client

When handling URL mode elicitation requests, MCP clients: SHOULD NOT render URLs as clickable in any field of an elicitation request, except for the url field in a URL elicitation request (with the restrictions detailed above).

client/elicitation#safe-url-handling

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

ELIC-046

MUST NOT · binds the server

Servers MUST NOT rely on client-provided user identification without server verification, as this can be forged.

client/elicitation#identifying-the-user

Excluded. Server-internal: whether the server verified an identity before trusting it is a decision made with information — its authorization context — that the session’s messages do not carry.

ELIC-047

SHOULD · binds the server

Instead, servers SHOULD follow security best practices.

client/elicitation#identifying-the-user

Excluded. Points to a separate document whose practices are server-internal; nothing in the session’s messages shows which were followed.

ELIC-048

MUST NOT · binds the server

Servers MUST NOT request sensitive information (passwords, API keys, etc.) via form mode

client/elicitation#form-mode-security

Excluded. Whether a requested field is “sensitive information” — the page’s own definition is “secrets and credentials that grant access or authorize transactions” — is a judgement about meaning, not syntax: a schema property named token may be a display preference and one named answer may collect a password. A check would have to guess from field names, and a guess convicts conforming servers. The server’s author decides it; nothing in the message settles it.

ELIC-049

SHOULD · binds the client

Clients SHOULD validate all responses against the provided schema

client/elicitation#form-mode-security

Judged by elicitation.response-matches-schema.

ELIC-050

SHOULD · binds the server

Servers SHOULD validate received data matches the requested schema

client/elicitation#form-mode-security

Excluded. Binds an act of validation, as MRTR-021 does: the server’s outcome — accepting the data, re-asking, or failing — is the only thing that reaches the wire, and each is consistent with a server that validated and with one that did not.

ELIC-051

MUST · binds the server

The MCP Server MUST verify the identity of the user who opens the URL before accepting information.

client/elicitation#phishing

Excluded. Identity verification of the user who opens the URL happens between that user’s browser and the server, outside the MCP session; the recording carries the URL the server sent and the client’s accept, not who opened it.

ELIC-052

MUST · binds the server

To prevent this attack, the server MUST ensure that the user who started the elicitation request (the end-user who is accessing the server via the MCP client) is the same user who completes the authorization flow.

client/elicitation#phishing

Excluded. Identity verification of the user who opens the URL happens between that user’s browser and the server, outside the MCP session; the recording carries the URL the server sent and the client’s accept, not who opened it.

ELIC-053

MUST · binds the server

In all implementations, the server MUST ensure that the mechanism to determine the user’s identity is resilient to attacks where an attacker can modify the elicitation URL.

client/elicitation#phishing

Excluded. Identity verification of the user who opens the URL happens between that user’s browser and the server, outside the MCP session; the recording carries the URL the server sent and the client’s accept, not who opened it.

SAMP

SAMP-001

SHOULD · binds the client

For trust & safety and security, there SHOULD always be a human in the loop with the ability to deny sampling requests.

client/sampling#user-interaction-model

Excluded. Policy and UI: whether a human reviews sampling requests, and whether they can deny one, is the client application’s design. A request answered with a result may have been approved by a person or by policy; nothing in the answer says which.

SAMP-002

SHOULD · binds the client

Applications SHOULD: Provide UI that makes it easy and intuitive to review sampling requests; Allow users to view and edit prompts before sending; Present generated responses for review before delivery

client/sampling#user-interaction-model

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

SAMP-003

MUST · binds the client

Clients MUST declare support for tool use via the sampling.tools capability to receive tool-enabled sampling requests.

client/sampling#tools-in-sampling

Excluded. The precondition half of the sentence. A client that has not declared sampling.tools does nothing wrong by receiving a tool-enabled request — the server does, and the sentence’s other half (sampling.tools-declared) judges it. Nothing the client sends can break this half: the declaration is either made or not, and its absence becomes a violation only when such a request arrives, which is the server’s act.

SAMP-004

MUST NOT · binds the server

Servers MUST NOT send tool-enabled sampling requests to Clients that have not declared support for tool use via the sampling.tools capability.

client/sampling#tools-in-sampling

Judged by sampling.tools-declared.

SAMP-005

MUST · binds the client

Clients that support sampling MUST declare the sampling capability during initialization:

client/sampling#capabilities

Judged by sampling.client-declares-capability.

SAMP-006

SHOULD · binds the server

Servers SHOULD avoid using these values (e.g. can just omit includeContext since it defaults to "none")

client/sampling#capabilities

Judged by sampling.include-context-avoided.

SAMP-007

SHOULD NOT · binds the server

and SHOULD NOT use them unless the client declares sampling.context capability.

client/sampling#capabilities

Judged by sampling.include-context-declared.

SAMP-008

MUST · binds the server

When a user message contains tool results (type: “tool_result”), it MUST contain ONLY tool results.

client/sampling#tool-result-messages

Judged by sampling.tool-results-only.

SAMP-009

MUST · binds the server

When using tool use in sampling, every assistant message containing ToolUseContent blocks MUST be followed by a user message that consists entirely of ToolResultContent blocks, with each tool use (e.g. with id: $id) matched by a corresponding tool result (with toolUseId: $id), before any other message.

client/sampling#tool-use-and-result-balance

Judged by sampling.tool-use-answered.

SAMP-010

MUST · binds the client

{mode: "required"}: Model MUST use at least one tool before completing

client/sampling#tool-choice-modes

Judged by sampling.tool-choice-required-honoured.

SAMP-011

MUST NOT · binds the client

{mode: "none"}: Model MUST NOT use any tools

client/sampling#tool-choice-modes

Judged by sampling.tool-choice-none-honoured.

SAMP-012

SHOULD · binds the client

Clients SHOULD return errors for common failure cases: Tool result missing in request: -32602 (Invalid params); Tool results mixed with other content: -32602 (Invalid params)

client/sampling#error-handling

Judged by sampling.malformed-tool-messages-rejected.

SAMP-013

SHOULD · binds the client

Clients SHOULD return errors for common failure cases: User rejected sampling request: -1

client/sampling#error-handling

Excluded. Its antecedent — that the user rejected the request — happens in the client’s interface. An error with another code may be some other failure, and a result may follow the user’s approval, so no answer is wrong without knowing what the user did.

SAMP-014

SHOULD · binds the client

Clients SHOULD implement user approval controls

client/sampling#security-considerations

Excluded. Binds the client’s user interface — what it shows the user, offers them, or lets them do — and none of that reaches the wire: a recording carries the client’s messages, not its screens. The reference host this project ships has no interactive interface at all (it answers from its interaction script, crates/mcp-reference-host/src/handler.rs), so the clause is a host-implementation property, reviewed in the host, never judged from a trace.

SAMP-015

SHOULD · binds the client and server

Both parties SHOULD validate message content

client/sampling#security-considerations

Excluded. Validation is internal; its outcome is whatever each party sends next, and the shape of what they send is judged directly by the clauses that constrain it (tool-message balance, message roles).

SAMP-016

SHOULD · binds the client

Clients SHOULD respect model preference hints

client/sampling#security-considerations

Excluded. Hints are advisory and mapping them is the client’s choice (the page: clients “MAY map hints to equivalent models from different providers”); the result’s model names what was used, but no rule says which model a hint selects, so no answer contradicts one.

SAMP-017

SHOULD · binds the client

Clients SHOULD implement rate limiting

client/sampling#security-considerations

Excluded. A request schedule: rate limiting is measured in elapsed time, which checks may not consult (LIFE-015, the time boundary in 02-architecture.md), and its threshold is the client’s own policy.

SAMP-018

MUST · binds the client and server

Both parties MUST handle sensitive data appropriately

client/sampling#security-considerations

Excluded. “Appropriately” names no observable criterion, and which data is sensitive is a semantic judgement about content (see the elicitation pages’ sensitive-information clauses): no message can be shown to have mishandled it.

SAMP-019

MUST · binds the server

Servers MUST ensure that when replying to a stopReason: "toolUse", each ToolUseContent item is responded to with a ToolResultContent item with a matching toolUseId, and that the user message contains only tool results (no other content types)

client/sampling#security-considerations

Judged by sampling.tool-use-answered, sampling.tool-results-only.

SAMP-020

SHOULD · binds the client and server

Both parties SHOULD implement iteration limits for tool loops

client/sampling#security-considerations

Excluded. A limit on a loop’s length is a policy whose threshold the page does not set: any finite loop in a recording is consistent with some limit, and an unbounded one cannot be recorded.

ROOT

ROOT-001

MUST · binds the client

Clients that support roots MUST declare the roots capability during initialization:

client/roots#capabilities

Judged by roots.client-declares-capability.

ROOT-002

MUST · binds the client

When roots change, clients that support listChanged MUST send a notification:

client/roots#root-list-changes

Excluded. The antecedent — that the client’s roots changed — happens inside the client. A recording sees only the notification, so a session without one cannot be told from one whose roots never changed.

ROOT-003

MUST · binds the client

uri: Unique identifier for the root. This MUST be a file:// URI in the current specification.

client/roots#root

Judged by roots.uri-file-scheme.

ROOT-004

SHOULD · binds the client

Clients SHOULD return standard JSON-RPC errors for common failure cases: Client does not support roots: -32601 (Method not found)

client/roots#error-handling

Judged by roots.unsupported-rejected.

ROOT-005

SHOULD · binds the client

Clients SHOULD return standard JSON-RPC errors for common failure cases: Internal errors: -32603

client/roots#error-handling

Excluded. Its antecedent — an internal error — is the client’s own determination; another error code may be some other failure, so no answer is wrong on its face.

ROOT-006

MUST · binds the client

Clients MUST: Only expose roots with appropriate permissions; Validate all root URIs to prevent path traversal; Implement proper access controls; Monitor root accessibility

client/roots#security-considerations

Excluded. Client-internal policy: which directories the user permitted, how paths are validated and accessed, and whether they remain reachable are facts about the client’s host system, not its messages. The one part a message carries — the URI’s form — is judged by roots.uri-file-scheme; a file:// URI with .. segments is still well formed, and whether it escapes a permitted directory depends on the filesystem.

ROOT-007

SHOULD · binds the server

Servers SHOULD: Handle cases where roots become unavailable; Respect root boundaries during operations; Validate all paths against provided roots

client/roots#security-considerations

Excluded. Server-internal: what the server does with roots — keeping within their boundaries, validating paths against them, coping when they vanish or change, caching them — happens in its own operations on its host, which the MCP session does not record.

ROOT-008

SHOULD · binds the client

Clients SHOULD: Prompt users for consent before exposing roots to servers; Provide clear user interfaces for root management; Validate root accessibility before exposing; Monitor for root changes

client/roots#implementation-guidelines

Excluded. UI and internal monitoring: consent prompts and root-management screens are the client’s interface, and checking or watching roots’ accessibility happens on its filesystem. A recording carries only the roots it finally reported.

ROOT-009

SHOULD · binds the server

Servers SHOULD: Check for roots capability before usage

client/roots#implementation-guidelines

Judged by roots.capability-checked.

ROOT-010

SHOULD · binds the server

Servers SHOULD: Handle root list changes gracefully; Respect root boundaries in operations; Cache root information appropriately

client/roots#implementation-guidelines

Excluded. Server-internal: what the server does with roots — keeping within their boundaries, validating paths against them, coping when they vanish or change, caching them — happens in its own operations on its host, which the MCP session does not record.

AUTH

AUTH-001

SHOULD · binds the client and server

Implementations using an HTTP-based transport SHOULD conform to this specification.

basic/authorization#protocol-requirements

Excluded. Conformance to the page as a whole is what its own entries judge, clause by clause; the sentence adds no property of a message beyond them. It binds only implementations that support authorization at all, which the page makes OPTIONAL. Same sentence as BASE-085 on the basic page.

AUTH-002

SHOULD NOT · binds the client and server

Implementations using an STDIO transport SHOULD NOT follow this specification, and instead retrieve credentials from the environment.

basic/authorization#protocol-requirements

Excluded. A stdio session has no HTTP layer for a challenge or a token header to appear in, so a recording cannot show the specification being followed there; retrieving credentials from the environment is process-local conduct with no wire footprint. Same sentence as BASE-085 on the basic page.

AUTH-003

MUST · binds the client and server

Implementations using alternative transports MUST follow established security best practices for their protocol.

basic/authorization#protocol-requirements

Excluded. Binds transports other than the two this revision defines, which no recording of an MCP session over stdio or Streamable HTTP carries, and names no practice a check could hold a message to.

AUTH-004

MUST · binds the server

Authorization servers MUST implement OAuth 2.1 with appropriate security measures for both confidential and public clients.

basic/authorization#overview

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-005

SHOULD · binds the client and server

Authorization servers and MCP clients SHOULD support OAuth Client ID Metadata Documents

basic/authorization#overview

Excluded. Support for a client registration mechanism is exercised between the client and the authorization server, off the MCP endpoint. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-006

MUST · binds the server

MCP servers MUST implement OAuth 2.0 Protected Resource Metadata (RFC9728).

basic/authorization#overview

Excluded. The Protected Resource Metadata document is not on the MCP endpoint, and a recording cannot show it. The resource_metadata URL names the server’s own address, which mcp-trace-capture does not rewrite, so a client fetches the document past the proxy; the well-known fallback is built from the proxy’s origin, and the proxy maps every path under the upstream’s (/.well-known/... reaches /mcp/.well-known/...), where no server serves it. Where a fetch does pass through, its http event records no request target, so its JSON body cannot be told from any other.

AUTH-007

MUST · binds the client

MCP clients MUST use OAuth 2.0 Protected Resource Metadata for authorization server discovery.

basic/authorization#overview

Excluded. Which document a client used to find its authorization server is visible only in fetches off the MCP endpoint. The Protected Resource Metadata document is not on the MCP endpoint, and a recording cannot show it. The resource_metadata URL names the server’s own address, which mcp-trace-capture does not rewrite, so a client fetches the document past the proxy; the well-known fallback is built from the proxy’s origin, and the proxy maps every path under the upstream’s (/.well-known/... reaches /mcp/.well-known/...), where no server serves it. Where a fetch does pass through, its http event records no request target, so its JSON body cannot be told from any other.

AUTH-008

MUST · binds the server

MCP authorization servers MUST provide at least one of the following discovery mechanisms:

basic/authorization#overview

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-009

MUST · binds the client

MCP clients MUST support both discovery mechanisms to obtain the information required to interact with the authorization server.

basic/authorization#overview

Excluded. Conduct inside the client’s OAuth flow (authorization server metadata discovery), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-010

MUST · binds the server

MCP servers MUST implement the OAuth 2.0 Protected Resource Metadata (RFC9728) specification to indicate the locations of authorization servers.

basic/authorization#authorization-server-location

Excluded. The Protected Resource Metadata document is not on the MCP endpoint, and a recording cannot show it. The resource_metadata URL names the server’s own address, which mcp-trace-capture does not rewrite, so a client fetches the document past the proxy; the well-known fallback is built from the proxy’s origin, and the proxy maps every path under the upstream’s (/.well-known/... reaches /mcp/.well-known/...), where no server serves it. Where a fetch does pass through, its http event records no request target, so its JSON body cannot be told from any other.

AUTH-011

MUST · binds the server

The Protected Resource Metadata document returned by the MCP server MUST include the authorization_servers field containing at least one authorization server.

basic/authorization#authorization-server-location

Excluded. The Protected Resource Metadata document is not on the MCP endpoint, and a recording cannot show it. The resource_metadata URL names the server’s own address, which mcp-trace-capture does not rewrite, so a client fetches the document past the proxy; the well-known fallback is built from the proxy’s origin, and the proxy maps every path under the upstream’s (/.well-known/... reaches /mcp/.well-known/...), where no server serves it. Where a fetch does pass through, its http event records no request target, so its JSON body cannot be told from any other.

AUTH-012

MUST · binds the server

MCP servers MUST implement one of the following discovery mechanisms to provide authorization server location information to MCP clients:

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. A disjunction whose second branch a recording cannot witness. A 401 whose challenge carries no resource_metadata is conforming when the server serves the well-known document instead, and that document is not in the trace: The Protected Resource Metadata document is not on the MCP endpoint, and a recording cannot show it. The resource_metadata URL names the server’s own address, which mcp-trace-capture does not rewrite, so a client fetches the document past the proxy; the well-known fallback is built from the proxy’s origin, and the proxy maps every path under the upstream’s (/.well-known/... reaches /mcp/.well-known/...), where no server serves it. Where a fetch does pass through, its http event records no request target, so its JSON body cannot be told from any other.

AUTH-013

MUST · binds the client

MCP clients MUST support both discovery mechanisms and use the resource metadata URL from the parsed WWW-Authenticate headers when present; otherwise, they MUST fall back to constructing and requesting the well-known URIs in the order listed above.

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. Which URLs the client requested next, and in what order, are fetches off the MCP endpoint. The Protected Resource Metadata document is not on the MCP endpoint, and a recording cannot show it. The resource_metadata URL names the server’s own address, which mcp-trace-capture does not rewrite, so a client fetches the document past the proxy; the well-known fallback is built from the proxy’s origin, and the proxy maps every path under the upstream’s (/.well-known/... reaches /mcp/.well-known/...), where no server serves it. Where a fetch does pass through, its http event records no request target, so its JSON body cannot be told from any other.

AUTH-014

SHOULD · binds the server

MCP servers SHOULD include a scope parameter in the WWW-Authenticate header as defined in RFC 6750 Section 3 to indicate the scopes required for accessing the resource.

basic/authorization#protected-resource-metadata-discovery-requirements

Judged by auth.challenge-scope.

AUTH-015

MUST NOT · binds the client

Clients MUST NOT assume any particular set relationship between the challenged scope set and scopes_supported.

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. Conduct inside the client’s OAuth flow (the scope it requests, whatever it assumes about scopes_supported), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-016

MUST · binds the client

Clients MUST treat the scopes provided in the challenge as authoritative for satisfying the current request.

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. Conduct inside the client’s OAuth flow (the scope it requests in its authorization request), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-017

SHOULD · binds the server

Servers SHOULD strive for consistency in how they construct scope sets but they are not required to surface every dynamically issued scope through scopes_supported.

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. Striving for consistency is a design aim, not a property any one challenge has, and challenges for different operations legitimately name different scopes; scopes_supported lives in the Protected Resource Metadata document, which a recording does not carry.

AUTH-018

MUST · binds the client

MCP clients MUST be able to parse WWW-Authenticate headers and respond appropriately to HTTP 401 Unauthorized responses from the MCP server.

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. Conduct inside the client’s OAuth flow (parsing the challenge, then the discovery, authorization and token requests that are the appropriate response to a 401), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-019

SHOULD · binds the client

If the scope parameter is absent, clients SHOULD apply the fallback behavior defined in the Scope Selection Strategy section.

basic/authorization#protected-resource-metadata-discovery-requirements

Excluded. Conduct inside the client’s OAuth flow (the scope it requests in its authorization request), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-020

MUST · binds the client

To handle different issuer URL formats and ensure interoperability with both OAuth 2.0 Authorization Server Metadata and OpenID Connect Discovery 1.0 specifications, MCP clients MUST attempt multiple well-known endpoints when discovering authorization server metadata.

basic/authorization#authorization-server-metadata-discovery

Excluded. Requests to the authorization server’s well-known endpoints. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-021

MUST · binds the client

For issuer URLs with path components (e.g., https://auth.example.com/tenant1), clients MUST try endpoints in the following priority order:

basic/authorization#authorization-server-metadata-discovery

Excluded. Requests to the authorization server’s well-known endpoints. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-022

MUST · binds the client

For issuer URLs without path components (e.g., https://auth.example.com), clients MUST try:

basic/authorization#authorization-server-metadata-discovery

Excluded. Requests to the authorization server’s well-known endpoints. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-023

SHOULD · binds the client

Clients supporting all options SHOULD follow the following priority order:

basic/authorization#client-registration-approaches

Excluded. Conduct inside the client’s OAuth flow (choosing a registration mechanism), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-024

SHOULD · binds the client and server

MCP clients and authorization servers SHOULD support OAuth Client ID Metadata Documents as specified in OAuth Client ID Metadata Document.

basic/authorization#client-id-metadata-documents

Excluded. Support for a client registration mechanism is exercised between the client and the authorization server, off the MCP endpoint. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-025

MUST · binds the client and server

MCP implementations supporting Client ID Metadata Documents MUST follow the requirements specified in OAuth Client ID Metadata Document.

basic/authorization#implementation-requirements

Excluded. Points at requirements stated elsewhere (the Client ID Metadata Document draft, and the two lists that follow on this page), each entered under its own id there; the sentence adds no obligation a recording could show apart from them.

AUTH-026

MUST · binds the client

Clients MUST host their metadata document at an HTTPS URL following RFC requirements; The client_id URL MUST use the “https” scheme and contain a path component, e.g. https://example.com/client.json; The metadata document MUST include at least the following properties: client_id, client_name, redirect_uris; Clients MUST ensure the client_id value in the metadata matches the document URL exactly

basic/authorization#implementation-requirements

Excluded. The metadata document is hosted by the client and fetched by the authorization server; neither request touches the MCP endpoint, and the client_id travels in the authorization request. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-027

MUST · binds the server

For Authorization Servers: SHOULD fetch metadata documents when encountering URL-formatted client_ids; MUST validate that the fetched document’s client_id matches the URL exactly; SHOULD cache metadata respecting HTTP cache headers; MUST validate redirect URIs presented in an authorization request against those in the metadata document; MUST validate the document structure is valid JSON and contains required fields; SHOULD follow the security considerations in Section 6 of Client ID Metadata Document

basic/authorization#implementation-requirements

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-028

SHOULD · binds the client

MCP clients SHOULD check for this capability and MAY fall back to Dynamic Client Registration or pre-registration if unavailable.

basic/authorization#discovery

Excluded. Conduct inside the client’s OAuth flow (reading authorization server metadata and choosing a registration mechanism), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-029

SHOULD · binds the client

MCP clients SHOULD support an option for static client credentials such as those supplied by a preregistration flow.

basic/authorization#preregistration

Excluded. A configuration option of the client, exercised against the authorization server; no MCP message shows whether the option exists.

AUTH-030

SHOULD · binds the client

When implementing authorization flows, MCP clients SHOULD follow the principle of least privilege by requesting only the scopes necessary for their intended operations.

basic/authorization#scope-selection-strategy

Excluded. Conduct inside the client’s OAuth flow (the scope of its authorization request), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-031

SHOULD · binds the client

During the initial authorization handshake, MCP clients SHOULD follow this priority order for scope selection:

basic/authorization#scope-selection-strategy

Excluded. Conduct inside the client’s OAuth flow (the scope of its authorization request), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-032

MUST · binds the client

MCP clients MUST implement Resource Indicators for OAuth 2.0 as defined in RFC 8707 to explicitly specify the target resource for which the token is being requested.

basic/authorization#resource-parameter-implementation

Excluded. Conduct inside the client’s OAuth flow (the resource parameter of its authorization and token requests), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-033

MUST · binds the client

The resource parameter: MUST be included in both authorization requests and token requests.; MUST identify the MCP server that the client intends to use the token with.; MUST use the canonical URI of the MCP server as defined in RFC 8707 Section 2.

basic/authorization#resource-parameter-implementation

Excluded. Conduct inside the client’s OAuth flow (the resource parameter of its authorization and token requests), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-034

SHOULD · binds the client

MCP clients SHOULD provide the most specific URI that they can for the MCP server they intend to access, following the guidance in RFC 8707.

basic/authorization#canonical-server-uri

Excluded. Conduct inside the client’s OAuth flow (the resource parameter of its authorization and token requests), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-035

SHOULD · binds the client and server

While the canonical form uses lowercase scheme and host components, implementations SHOULD accept uppercase scheme and host components for robustness and interoperability.

basic/authorization#canonical-server-uri

Excluded. Accepting a URI is a comparison made by whoever receives the resource parameter or validates a token’s audience — the authorization server, or the MCP server inside its validation — and neither comparison is a message on the MCP endpoint.

AUTH-036

SHOULD · binds the client and server

While both https://mcp.example.com/ (with trailing slash) and https://mcp.example.com (without trailing slash) are technically valid absolute URIs according to RFC 3986, implementations SHOULD consistently use the form without the trailing slash for better interoperability unless the trailing slash is semantically significant for the specific resource.

basic/authorization#canonical-server-uri

Excluded. The canonical URI’s spelling appears in the resource parameter of requests to the authorization server and in token audiences, neither of which a recording of the MCP endpoint carries; and an http event records no request target, so not even the endpoint URL the client used is there.

AUTH-037

MUST · binds the client

MCP clients MUST send this parameter regardless of whether authorization servers support it.

basic/authorization#canonical-server-uri

Excluded. Conduct inside the client’s OAuth flow (the resource parameter of its authorization and token requests), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-038

MUST · binds the client

Access token handling when making requests to MCP servers MUST conform to the requirements defined in OAuth 2.1 Section 5 “Resource Requests”.

basic/authorization#token-requirements

Excluded. Authorization is never in a trace: recorders keep headers by allowlist (RECORDED_HEADERS), and credentials stay off it by construction (docs/plan/05-security-model.md). Which requests carried a token, and which token, cannot be read back from a recording. The section’s other requirement, no token in the query string, has its own entry.

AUTH-039

MUST · binds the client

MCP client MUST use the Authorization request header field defined in OAuth 2.1 Section 5.1.1:

basic/authorization#token-requirements

Excluded. Authorization is never in a trace: recorders keep headers by allowlist (RECORDED_HEADERS), and credentials stay off it by construction (docs/plan/05-security-model.md). Which requests carried a token, and which token, cannot be read back from a recording.

AUTH-040

MUST · binds the client

Note that authorization MUST be included in every HTTP request from client to server, even if they are part of the same logical session.

basic/authorization#token-requirements

Excluded. Authorization is never in a trace: recorders keep headers by allowlist (RECORDED_HEADERS), and credentials stay off it by construction (docs/plan/05-security-model.md). Which requests carried a token, and which token, cannot be read back from a recording. A 401 to a request in mid-session does not settle it either: an expired token draws the same answer as a missing one.

AUTH-041

MUST NOT · binds the client

Access tokens MUST NOT be included in the URI query string

basic/authorization#token-requirements

Excluded. An http event records the method, status and allowlisted headers, and no request target: neither the path nor the query string a request was sent to is in the trace, so a token in the URI cannot be seen. Recording the query to judge this would write into every trace the very credential the clause keeps out of URIs.

AUTH-042

MUST · binds the server

MCP servers, acting in their role as an OAuth 2.1 resource server, MUST validate access tokens as described in OAuth 2.1 Section 5.2.

basic/authorization#token-handling

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens.

AUTH-043

MUST · binds the server

MCP servers MUST validate that access tokens were issued specifically for them as the intended audience, according to RFC 8707 Section 2.

basic/authorization#token-handling

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens.

AUTH-044

MUST · binds the server

If validation fails, servers MUST respond according to OAuth 2.1 Section 5.3 error handling requirements.

basic/authorization#token-handling

Excluded. Whether validation failed is decided inside the server, against a token the recording never holds, and the sentence imports OAuth 2.1 Section 5.3 wholesale. What a recording can hold the response to is the page’s own statement of it: the status each declared error receives and the 401 for an invalid token, judged by auth.error-status and auth.invalid-token-401.

AUTH-045

MUST · binds the server

Invalid or expired tokens MUST receive a HTTP 401 response.

basic/authorization#token-handling

Judged by auth.invalid-token-401.

AUTH-046

MUST NOT · binds the client

MCP clients MUST NOT send tokens to the MCP server other than ones issued by the MCP server’s authorization server.

basic/authorization#token-handling

Excluded. Authorization is never in a trace: recorders keep headers by allowlist (RECORDED_HEADERS), and credentials stay off it by construction (docs/plan/05-security-model.md). Which requests carried a token, and which token, cannot be read back from a recording.

AUTH-047

MUST · binds the server

MCP servers MUST only accept tokens that are valid for use with their own resources.

basic/authorization#token-handling

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens.

AUTH-048

MUST NOT · binds the server

MCP servers MUST NOT accept or transit any other tokens.

basic/authorization#token-handling

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens. Transiting a token is a request to an upstream service, outside the MCP session.

AUTH-049

MUST · binds the server

Servers MUST return appropriate HTTP status codes for authorization errors

basic/authorization#error-handling

Judged by auth.error-status.

AUTH-050

SHOULD · binds the server

When a client makes a request with an access token with insufficient scope during runtime operations, the server SHOULD respond with: HTTP 403 Forbidden status code (per RFC 6750 Section 3.1); WWW-Authenticate header with the Bearer scheme and additional parameters: error="insufficient_scope" - indicating the specific type of authorization failure; scope="required_scope1 required_scope2" - specifying the minimum scopes needed for the operation; resource_metadata - the URI of the Protected Resource Metadata document (for consistency with 401 responses)

basic/authorization#runtime-insufficient-scope-errors

Judged by auth.insufficient-scope-response.

AUTH-051

SHOULD · binds the server

Server Scope Management: When responding with insufficient scope errors, servers SHOULD include the scopes needed to satisfy the current request in the scope parameter.

basic/authorization#runtime-insufficient-scope-errors

Judged by auth.insufficient-scope-names-scopes.

AUTH-052

SHOULD · binds the server

Servers SHOULD be consistent in their scope inclusion strategy to provide predictable behavior for clients.

basic/authorization#runtime-insufficient-scope-errors

Excluded. A strategy is a policy over every challenge the server issues, across sessions and users; one recording shows a few challenges for different operations, which legitimately name different scopes, and cannot tell an inconsistent strategy from a consistent one applied to different requests.

AUTH-053

SHOULD · binds the server

Servers SHOULD consider the user experience impact when determining which scopes to include in the response, as misconfigured scopes may require frequent user interaction.

basic/authorization#runtime-insufficient-scope-errors

Excluded. Binds the server’s deliberation, not a message: a challenge shows the scopes chosen, not whether their user experience impact was weighed.

AUTH-054

SHOULD · binds the client

Clients SHOULD respond to these errors by requesting a new access token with an increased set of scopes via a step-up authorization flow or handle the errors in other, appropriate ways.

basic/authorization#step-up-authorization-flow

Excluded. Conduct inside the client’s OAuth flow (the token request a step-up makes), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records. The clause also admits “other, appropriate ways”, which no message distinguishes.

AUTH-055

SHOULD · binds the client

Clients acting on behalf of a user SHOULD attempt the step-up authorization flow.

basic/authorization#step-up-authorization-flow

Excluded. Whether a client acts on behalf of a user or on its own (client_credentials) is a fact about its grant, which no MCP message states. Conduct inside the client’s OAuth flow (the step-up re-authorization), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-056

SHOULD · binds the client

Clients SHOULD implement retry limits and SHOULD track scope upgrade attempts to avoid repeated failures for the same resource and operation combination.

basic/authorization#step-up-authorization-flow

Excluded. A limit is a property of the client’s implementation, which a session that simply stops retrying satisfies whatever the limit is; the page fixes no number (“no more than a few times”) a recording could be held to, and the attempts tracked are re-authorizations off the MCP endpoint.

AUTH-057

MUST · binds the client and server

Implementations MUST follow OAuth 2.1 security best practices as laid out in OAuth 2.1 Section 7. “Security Considerations”.

basic/authorization#security-considerations

Excluded. Imports OAuth 2.1 Section 7 wholesale. Its observable consequences for an MCP exchange are the challenge clauses this page states itself, judged under their own ids; the rest is implementation conduct (storage, transport configuration, the OAuth flow) with no footprint on the MCP endpoint.

AUTH-058

MUST · binds the client

MCP clients MUST include the resource parameter in authorization and token requests as specified in the Resource Parameter Implementation section

basic/authorization#token-audience-binding-and-validation

Excluded. Conduct inside the client’s OAuth flow (the resource parameter of its authorization and token requests), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-059

MUST · binds the server

MCP servers MUST validate that tokens presented to them were specifically issued for their use

basic/authorization#token-audience-binding-and-validation

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens.

AUTH-060

MUST · binds the client and server

Clients and servers MUST implement secure token storage and follow OAuth best practices, as outlined in OAuth 2.1, Section 7.1.

basic/authorization#token-theft

Excluded. Token storage is local state of each party, and a token is never recorded: nothing on the wire shows how either party keeps one.

AUTH-061

SHOULD · binds the server

Authorization servers SHOULD issue short-lived access tokens to reduce the impact of leaked tokens.

basic/authorization#token-theft

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-062

MUST · binds the server

For public clients, authorization servers MUST rotate refresh tokens as described in OAuth 2.1 Section 4.3.1 “Token Endpoint Extension”.

basic/authorization#token-theft

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-063

MUST · binds the client and server

Implementations MUST follow OAuth 2.1 Section 1.5 “Communication Security”.

basic/authorization#communication-security

Excluded. Imports OAuth 2.1 Section 1.5 wholesale. Its observable consequences for an MCP exchange are the challenge clauses this page states itself, judged under their own ids; the rest is implementation conduct (storage, transport configuration, the OAuth flow) with no footprint on the MCP endpoint.

AUTH-064

MUST · binds the server

All authorization server endpoints MUST be served over HTTPS.

basic/authorization#communication-security

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-065

MUST · binds the client

All redirect URIs MUST be either localhost or use HTTPS.

basic/authorization#communication-security

Excluded. Redirect URIs are registered with the authorization server and travel in authorization requests through the user’s browser. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-066

MUST · binds the client

To mitigate this, MCP clients MUST implement PKCE according to OAuth 2.1 Section 7.5.2 and MUST verify PKCE support before proceeding with authorization.

basic/authorization#authorization-code-protection

Excluded. Conduct inside the client’s OAuth flow (PKCE and the authorization server metadata it is verified against), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-067

MUST · binds the client

MCP clients MUST use the S256 code challenge method when technically capable, as required by OAuth 2.1 Section 4.1.1.

basic/authorization#authorization-code-protection

Excluded. Conduct inside the client’s OAuth flow (PKCE and the authorization server metadata it is verified against), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-068

MUST · binds the client

Since OAuth 2.1 and PKCE specifications do not define a mechanism for clients to discover PKCE support, MCP clients MUST rely on authorization server metadata to verify this capability:

basic/authorization#authorization-code-protection

Excluded. Conduct inside the client’s OAuth flow (PKCE and the authorization server metadata it is verified against), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-069

MUST · binds the client

OAuth 2.0 Authorization Server Metadata: If code_challenge_methods_supported is absent, the authorization server does not support PKCE and MCP clients MUST refuse to proceed.

basic/authorization#authorization-code-protection

Excluded. Conduct inside the client’s OAuth flow (PKCE and the authorization server metadata it is verified against), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-070

MUST · binds the client

MCP clients MUST verify the presence of code_challenge_methods_supported in the provider metadata response. If the field is absent, MCP clients MUST refuse to proceed.

basic/authorization#authorization-code-protection

Excluded. Conduct inside the client’s OAuth flow (PKCE and the authorization server metadata it is verified against), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-071

MUST · binds the server

Authorization servers providing OpenID Connect Discovery 1.0 MUST include code_challenge_methods_supported in their metadata to ensure MCP compatibility.

basic/authorization#authorization-code-protection

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-072

MUST · binds the client

MCP clients MUST have redirect URIs registered with the authorization server.

basic/authorization#open-redirection

Excluded. Conduct inside the client’s OAuth flow (client registration), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-073

MUST · binds the server

Authorization servers MUST validate exact redirect URIs against pre-registered values to prevent redirection attacks.

basic/authorization#open-redirection

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-074

SHOULD · binds the client

MCP clients SHOULD use and verify state parameters in the authorization code flow and discard any results that do not include or have a mismatch with the original state.

basic/authorization#open-redirection

Excluded. Conduct inside the client’s OAuth flow (the authorization code flow’s state), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.

AUTH-075

MUST · binds the server

Authorization servers MUST take precautions to prevent redirecting user agents to untrusted URI’s, following suggestions laid out in OAuth 2.1 Section 7.12.2

basic/authorization#open-redirection

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-076

SHOULD · binds the server

Authorization servers SHOULD only automatically redirect the user agent if it trusts the redirection URI.

basic/authorization#open-redirection

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-077

MUST · binds the server

When implementing Client ID Metadata Documents, authorization servers MUST consider the security implications detailed in OAuth Client ID Metadata Document, Section 6.

basic/authorization#client-id-metadata-document-security

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-078

SHOULD · binds the server

Authorization servers fetching metadata documents SHOULD consider Server-Side Request Forgery (SSRF) risks

basic/authorization#authorization-server-abuse-protection

Excluded. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-079

MUST · binds the server

Authorization servers: SHOULD display additional warnings for localhost-only redirect URIs; MUST clearly display the redirect URI hostname during authorization

basic/authorization#localhost-redirect-uri-risks

Excluded. What the authorization server shows the user during authorization is consent UI in the user’s browser. Binds the authorization server, the separate OAuth party the page’s Roles section places outside the MCP server. A client reaches it directly, never through the MCP endpoint, so a recording of the MCP exchanges holds none of its conduct.

AUTH-080

MUST · binds the server

MCP proxy servers using static client IDs MUST obtain user consent for each dynamically registered client before forwarding to third-party authorization servers (which may require additional consent).

basic/authorization#confused-deputy-problem

Excluded. Consent is obtained in the user’s browser, and the forwarding is the proxy server’s own OAuth flow with a third-party authorization server; neither is a message on the MCP endpoint the recording captures.

AUTH-081

MUST · binds the server

MCP servers MUST validate access tokens before processing the request, ensuring the access token is issued specifically for the MCP server, and take all necessary steps to ensure no data is returned to unauthorized parties.

basic/authorization#access-token-privilege-restriction

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens. A result returned to an unauthorized party would need the request’s credential to show, and that is the header a recording never keeps.

AUTH-082

MUST · binds the server

A MCP server MUST follow the guidelines in OAuth 2.1 - Section 5.2 to validate inbound tokens.

basic/authorization#access-token-privilege-restriction

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens.

AUTH-083

MUST · binds the server

MCP servers MUST only accept tokens specifically intended for themselves and MUST reject tokens that do not include them in the audience claim or otherwise verify that they are the intended recipient of the token.

basic/authorization#access-token-privilege-restriction

Excluded. Token validation is decided inside the server, against a token the recording never holds (Authorization is not recorded). What the server says about the outcome is its challenge, judged where the page states what it must carry: the error-handling table and the 401 for invalid tokens.

AUTH-084

MUST NOT · binds the server

The MCP server MUST NOT pass through the token it received from the MCP client.

basic/authorization#access-token-privilege-restriction

Excluded. Passthrough is a request from the MCP server to an upstream API, outside the MCP session; the recording holds the client–server exchange only, and not even the token the client sent (Authorization is never recorded).

AUTH-085

MUST · binds the client

MCP clients MUST implement and use the resource parameter as defined in RFC 8707 - Resource Indicators for OAuth 2.0 to explicitly specify the target resource for which the token is being requested.

basic/authorization#access-token-privilege-restriction

Excluded. Conduct inside the client’s OAuth flow (the resource parameter of its authorization and token requests), which runs between the client, the user’s browser and the authorization server, off the MCP endpoint. A recording of the MCP exchanges carries none of it; the only trace the flow leaves there is the token in Authorization, which capture never records.