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.
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.
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.
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.
Judged by base.result-id-matches.
BASE-005
MUST NOT · binds the client and server
Notifications MUST NOT include an ID.
Judged by base.notification-no-id.
BASE-006
MUST · binds the client and server
Error responses MUST include an
errorfield with acodeandmessage.
Judged by base.error-shape.
BASE-007
MUST · binds the client and server
Error codes MUST be integers.
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.
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).
Judged by base.error-id-matches.
BASE-010
MUST · binds the client and server
Result responses MUST include a
resultfield.
Judged by base.result-field.
BASE-011
MUST NOT · binds the client and server
The receiver MUST NOT send a response.
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.
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
$schemafield
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
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.
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 (-)
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
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 thanexample.com/).
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:
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:
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.
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
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.
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.
Judged by base.schemas-use-2020-12.
BASE-087
SHOULD · binds the client
image/png- PNG images (safe, universal compatibility)image/jpeg(andimage/jpg) - JPEG images (safe, universal compatibility) Clients that support rendering icons SHOULD also support:
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
initializerequest 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
initializednotification 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
initializerequest.
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
initializednotification.
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
initializerequest, 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
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
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
SIGTERMif the server does not exit within a reasonable time; SendingSIGKILLif the server does not exit within a reasonable time afterSIGTERM
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.
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.
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.
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.
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.
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
Originheader 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.
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
stdoutthat is not a valid MCP message.
Judged by transport.stdio-server-output-valid.
TRAN-005
MUST NOT · binds the client
The client MUST NOT write anything to the server’s
stdinthat is not a valid MCP message.
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
Originheader 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-Idis returned by the server during initialization, clients using the Streamable HTTP transport MUST include it in theMCP-Session-Idheader 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-Idheader (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 newInitializeRequestwithout 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-Versionheader, 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 version2025-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 with400 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
stderroutput and SHOULD NOT assumestderroutput indicates error conditions.
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.
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
Acceptheader, listing bothapplication/jsonandtext/event-streamas 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, orContent-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
datafield in order to prime the client to reconnect (using that event ID asLast-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
retryfield 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
retryfield, 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
Acceptheader, listingtext/event-streamas 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-streamin 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-IDto 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-IDheader 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-Idheader, 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
retryfield 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
progressvalue 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
messagefield 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
progressTokenprovided in the original request MUST continue to be used for progress notifications throughout the task’s lifetime, even after theCreateTaskResulthas 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
progressTokenthat 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, orcancelled)
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
initializerequest 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/cancelrequest MUST be used instead of thenotifications/cancellednotification.
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
toolscapability:
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
listChangedcapability 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 (notnull)
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.
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).
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 (.)
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.
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.
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
resourcescapability:
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.
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.
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.
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.
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
resourcescapability:
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
listChangedcapability 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.
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.
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
promptscapability during initialization:
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
listChangedcapability 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.
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.
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.
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)
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
loggingcapability:
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
completionscapability:
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
nextCursoras 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
elicitationcapability during initialization:
client/elicitation#capabilities
Judged by elicitation.client-declares-capability.
ELIC-005
MUST · binds the client
Clients declaring the
elicitationcapability MUST support at least one mode (formorurl).
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
modefield 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 themodefield, 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", amessage, 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
urlparameter 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
elicitationIdestablished in the originalelicitation/createrequest.
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
elicitationIdproperty.
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/createrequest 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.
subclaim)
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
urlfield 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.
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.
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.
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.toolscapability 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.toolscapability.
client/sampling#tools-in-sampling
Judged by sampling.tools-declared.
SAMP-005
MUST · binds the client
Clients that support sampling MUST declare the
samplingcapability during initialization:
Judged by sampling.client-declares-capability.
SAMP-006
SHOULD · binds the server
Servers SHOULD avoid using these values (e.g. can just omit
includeContextsince it defaults to"none")
Judged by sampling.include-context-avoided.
SAMP-007
SHOULD NOT · binds the server
and SHOULD NOT use them unless the client declares
sampling.contextcapability.
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
ToolUseContentblocks MUST be followed by a user message that consists entirely ofToolResultContentblocks, with each tool use (e.g. withid: $id) matched by a corresponding tool result (withtoolUseId: $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", eachToolUseContentitem is responded to with aToolResultContentitem with a matchingtoolUseId, 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
rootscapability during initialization:
Judged by roots.client-declares-capability.
ROOT-002
MUST · binds the client
When roots change, clients that support
listChangedMUST 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 afile://URI in the current specification.
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)
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
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.
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
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).
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.
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:
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.
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_serversfield 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-Authenticateheaders 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
scopeparameter in theWWW-Authenticateheader 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-Authenticateheaders and respond appropriately toHTTP 401 Unauthorizedresponses 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
scopeparameter 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_idURL 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 theclient_idvalue 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_idmatches 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.
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
resourceparameter: 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) andhttps://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 Forbiddenstatus code (per RFC 6750 Section 3.1);WWW-Authenticateheader with theBearerscheme 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
scopeparameter.
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
resourceparameter 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
localhostor 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
S256code 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_supportedis 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_supportedin 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_supportedin 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
resourceparameter 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.