A second opinion: mcpsnoop
mcpsnoop is the one other tool that judges a recorded MCP session offline: mcpsnoop check reads a capture and fails on a fixed set of rules. The official suite calibrates this project against live scenarios; mcpsnoop calibrates it against a reader of recordings, which is what this project is. This page is that comparison over all 358 corpus traces, with every disagreement triaged: which tool is right, by which clause, and what was done about it.
How the comparison is made
The binary. mcpsnoop 0.26.1, the current npm release when measured, taken from the npm registry and never built from source. The mcpsnoop package is a launcher with no install script; the Go binary ships in a per-platform package. Both tarballs were fetched with npm pack and checked against the registry’s integrity:
[email protected]—sha512-midlHuFR9PGrrW8BUm/F16k76ccPmVfE8OVBWR7DkSQzZjaGookgTH4ACpytuWnD5VnKIxvNN2Y8smwjyq4xMw==@mcpsnoop/[email protected]—sha512-mNsXyDgs4vznFP6BQz9oxAJYLEo+I2YC2F9vDICd5Z4FSUPTjHWT/A6HW+i6/FvyUu0Ymf3HnMc2zM9X2xZQ2Q==
The binary inside, package/bin/mcpsnoop, has SHA-256 81c3636fa5a371833ab4558d6ac417d9d94a86f99949e0cff32bb09ccf69c2a9. To measure, point MCPSNOOP at it and run cargo xtask mcpsnoop; without it the task skips loudly. mcpsnoop is never a gate on a pull request — a scheduled, informational job re-measures it.
The same session in front of both. Our traces are converted into the capture format mcpsnoop writes itself (xtask/src/mcpsnoop/convert.rs). On stdio the conversion is lossless. On HTTP a frame gets the headers, status and exchange the trace’s own order settles — the rules our validator’s framing applies — and no more; a frame whose context the trace cannot settle is marked unframed, and a finding that reads such context there is set aside, not counted. The conversion is checked against mcpsnoop’s own recordings on every measurement: sessions recorded through both tools at once — the reference host against the everything server, committed under conformance/mcpsnoop/native/ — must draw the same mcpsnoop findings from the converted trace as from mcpsnoop’s capture once that capture’s frames share one connection, the single field the conversion fixes rather than carries. In the committed run 3 of 3 such sessions did: http-2025-11-25 (28 findings), http-2026-07-28 (22 findings), stdio-2025-11-25 (28 findings).
What is compared. mcpsnoop’s conformance signals — invalid, warn and mismatch, the three its own rule descriptions call protocol violations — against our fail and warn rows, an extension’s among them although they never decide our verdict, and the wire schema. Its other signals (a call that ended in an error, one still pending when the capture ended, a deprecated feature) are counted per trace but say nothing about conformance. Each mcpsnoop rule is mapped to the registry clauses its condition violates, read from both texts (conformance/mcpsnoop/rules.json, tabulated below); a mapping is partial where the rule checks only part of the clause. Then, per trace: a fired rule one of whose clauses we flag is agreement; a fired rule none of whose clauses we flag is a mcpsnoop-only divergence; a clause we flag that a rule maps fully, with that rule silent, is an ours-only divergence; a clause we flag that no rule maps fully is beyond mcpsnoop, a difference of scope rather than of reading.
Summary
| Corpus directory | Traces |
|---|---|
corpus/good/ | 14 |
corpus/violations/ | 106 |
corpus/draft/good/ | 28 |
corpus/draft/violations/ | 201 |
corpus/draft/captured/ | 9 |
Verdicts, ours against mcpsnoop’s conformance signals:
| mcpsnoop flags the trace | mcpsnoop does not | |
|---|---|---|
our verdict fail | 83 | 139 |
our verdict pass or pass-with-warnings | 4 | 132 |
Traces by how the two readings relate:
| Relation | Traces |
|---|---|
| both clean | 44 |
| agree | 79 |
| beyond mcpsnoop | 222 |
| divergent | 13 |
mcpsnoop flagging less than we do is mostly scope, not disagreement: its rules cover a part of the registry, and the traces it passes while we fail are the beyond mcpsnoop row. Across the corpus we flag 268 distinct clauses (counted per revision) that no mcpsnoop rule maps fully. Findings were set aside for reading HTTP context the conversion could not supply on 7 traces.
Divergences
Every divergence the run shows, and its triage (conformance/mcpsnoop/triage.json). --check fails while any divergence is untriaged or any triage entry matches nothing.
| # | Kind | Subject | Traces | Class | Right | Resolution |
|---|---|---|---|---|---|---|
| 1 | mcpsnoop-only | invalid-frame | violations/base-007-error-code-float | granularity | both | none: the same defect on the same frame, reported at different granularity |
| 2 | mcpsnoop-only | request-id-in-flight | draft/violations/base-052-null-id-error-then-id-reused | mcpsnoop-defect | ours | upstream: mcpsnoop-null-id-answer |
| 3 | mcpsnoop-only | server-rejected-header-mismatch | draft/violations/tran-098-header-mismatch-without-400, draft/violations/tran-133-omitted-null-header-rejected, draft/violations/tran-135-omitted-absent-header-rejected | mcpsnoop-defect | ours | upstream: mcpsnoop-trusts-header-mismatch-rejection |
| 4 | ours-only | BASE-030 | draft/violations/base-031-malformed-meta-answered-with-result, draft/violations/base-032-invalid-params-not-http-400 | revision-attribution | both | none: the revision is stated to our validator out of band and is absent from the trace |
| 5 | ours-only | MRTR-002 | draft/violations/base-031-malformed-meta-answered-with-result, draft/violations/base-032-invalid-params-not-http-400 | revision-attribution | both | none: the revision is stated to our validator out of band and is absent from the trace |
| 6 | ours-only | TOOL-016 | draft/violations/base-031-malformed-meta-answered-with-result, draft/violations/base-032-invalid-params-not-http-400 | revision-attribution | both | none: the revision is stated to our validator out of band and is absent from the trace |
| 7 | ours-only | BASE-030 | draft/violations/vers-008-initialize-error-without-versions, draft/violations/base-030-legacy-initialize-negotiated-2026-07-28 | spec-ambiguity | undecided | open: decide whether a legacy-era request inside a 2026-07-28 trace is held to that revision’s request-envelope clauses (BASE-030 and its restatements, TRAN-071); the current reading is recorded in checks/stateless/meta.rs |
| 8 | ours-only | MRTR-002 | draft/violations/vers-008-initialize-error-without-versions, draft/violations/base-030-legacy-initialize-negotiated-2026-07-28 | spec-ambiguity | undecided | open: the same decision as BASE-030 on these traces |
| 9 | ours-only | TOOL-016 | draft/violations/vers-008-initialize-error-without-versions, draft/violations/base-030-legacy-initialize-negotiated-2026-07-28 | spec-ambiguity | undecided | open: the same decision as BASE-030 on these traces |
| 10 | ours-only | LIFE-018 | violations/tran-017-protocol-version-header-missing | mcpsnoop-defect | ours | upstream: mcpsnoop-version-header-2025-11-25 |
| 11 | ours-only | TRAN-017 | violations/tran-017-protocol-version-header-missing | mcpsnoop-defect | ours | upstream: mcpsnoop-version-header-2025-11-25 |
| 12 | mcpsnoop-only | response-unmatched | good/http-origin-refused-without-id, draft/good/http-origin-refused-without-id | mcpsnoop-defect | ours | upstream: mcpsnoop-origin-refusal-unmatched |
| 13 | mcpsnoop-only | progress-after-completion | good/stdio-task-progress | mcpsnoop-defect | ours | open: whether to report it upstream is the maintainer’s call; the reproduction is corpus/good/stdio-task-progress.jsonl, whose task handling the 2025-11-25 tasks page defines (PROG-014) |
1. invalid-frame (mcpsnoop-only)
The server answers initialize with "code": -32602.5. We report BASE-007, the clause that names the defect; mcpsnoop’s decoder refuses the frame and reports it as not JSON-RPC at all. Both are true — a non-integer code breaks JSON-RPC 2.0, which BASE-008 incorporates — and the two readings convict the same frame. The difference is only which clause carries the finding: ours attributes it to the most specific clause and leaves BASE-008 to framing faults, mcpsnoop has no rule finer than the parse.
BASE-007 (MUST): Error codes MUST be integers. — source
BASE-008 (MUST): All messages between MCP clients and servers MUST follow the JSON-RPC 2.0 specification. — source
Resolution: none: the same defect on the same frame, reported at different granularity
2. request-id-in-flight (mcpsnoop-only)
On Streamable HTTP the client POSTs tools/call id 1 and the server answers that POST, in its own application/json body, with an error whose id is null although the request’s id was readable — a BASE-052 violation both tools report. The client then sends a new tools/call reusing id 1. mcpsnoop reports the reuse as an id already in flight: having failed to match the null-id error by id, it keeps request 1 open forever. But the answer arrived as the response to that very POST, so the client has received a response for it, and BASE-045 forbids reuse only of an id the sender has “not yet received a response for”. Our framing ties a null-id answer to the request whose exchange framed it; mcpsnoop records the exchange (exchange is in its own capture) but does not use it here. The conversion is not the cause: the request and the error carry the same exchange, exactly as mcpsnoop’s proxy records them.
BASE-045 (MUST NOT): The request ID MUST NOT match the ID of any other request the sender has issued and not yet received a response for. — source
BASE-052 (MUST): 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). — source
Resolution: upstream: mcpsnoop-null-id-answer
3. server-rejected-header-mismatch (mcpsnoop-only)
In each trace the server answers -32020 (HeaderMismatch) to a POST whose headers match its body: a tools/list with every header correct (tran-098), and a tools/call that omits Mcp-Param-Region because region is null or absent — exactly what the client must do (tran-133, tran-135). mcpsnoop reports each as “a routing header disagrees with the body”. By its own documentation a server’s -32020 “counts as the same condition” as a disagreement, so it takes the server’s word over its own comparison — which on these frames found nothing. The defect is the server’s (TRAN-133/TRAN-135: the server MUST NOT expect the header; TRAN-098: the rejection must be 400), and mcpsnoop’s finding attributes it to the client’s headers. Where the client really was at fault (tran-089-sentinel-markers-miscased, tran-077-param-header-value-rejected, tran-079-param-header-value-not-mirrored) the same rule agrees with us.
TRAN-133 (MUST NOT): Parameter value is
null| Client MUST omit the header | Server MUST NOT expect the header — source
TRAN-135 (MUST NOT): Parameter not in arguments | Client MUST omit the header | Server MUST NOT expect the header — source
TRAN-098 (MUST): Servers MUST reject requests with a
400 Bad RequestHTTP status and JSON-RPC error code-32020(HeaderMismatch) if any validation fails. — source
Resolution: upstream: mcpsnoop-trusts-header-mismatch-rejection
4. BASE-030 (ours-only)
Each trace’s only request carries "_meta": {} — no protocol version anywhere, in the body or (base-032, HTTP) in a header. We judge the trace at 2026-07-28 because the corpus files it under draft/, which is how this repository assigns a revision; mcpsnoop infers the revision from the session and finds none, so it applies no 2026-07-28 rule. Given what each tool is told, each is right: an empty _meta is a violation at 2026-07-28 and none at 2025-11-25. mcpsnoop does flag the same field set as missing wherever the session names 2026-07-28 (base-030-request-meta-missing-required-field and the probe capture agree with us).
BASE-030 (MUST): Client requests carry the following
io.modelcontextprotocol/*fields inmeta; fields marked as required MUST be included on every request. — source
Resolution: none: the revision is stated to our validator out of band and is absent from the trace
5. MRTR-002 (ours-only)
The same request and the same reasoning as BASE-030 above: MRTR-002 restates the rule on the multi round-trip page.
MRTR-002 (MUST): Every request MUST include the required
metafields; seemeta. — source
Resolution: none: the revision is stated to our validator out of band and is absent from the trace
6. TOOL-016 (ours-only)
The same request and the same reasoning as BASE-030 above: TOOL-016 restates the required _meta fields on the tools page.
TOOL-016 (MUST): Every request MUST include the required
metafields; seemeta. — source
Resolution: none: the revision is stated to our validator out of band and is absent from the trace
7. BASE-030 (ours-only)
A legacy client sends initialize naming 2025-11-25. In vers-008 the server speaks only 2026-07-28 and refuses; in base-030-legacy-initialize-negotiated-2026-07-28 it answers naming 2026-07-28 and the session goes on under it. Judging the whole trace at 2026-07-28 (the corpus’s draft/ assignment for the first; the server’s initialize result, which is the session’s revision, for the second), we report the initialize as a request missing the required _meta fields — deliberately: checks/stateless/meta.rs exempts this request from BASE-031, citing basic/versioning‘s compatibility matrix (which says of exactly this request that it “also lacks the required _meta fields”), and states that the client’s own defect is still reported, by BASE-030. mcpsnoop 0.26.1 draws nothing on either trace. Measured 2026-10-25 on edited copies of the second trace’s converted capture: it applies request-meta-missing to a request only when that request’s own _meta carries io.modelcontextprotocol/protocolVersion 2026-07-28 (an initialize whose _meta names it and lacks the other fields is flagged, so initialize is not exempt); a request with no _meta, an empty one, or one naming 2025-11-25 draws nothing, and setting the initialize params’ protocolVersion to 2026-07-28 changes nothing. So its per-request revision is the one the request states in _meta, not params.protocolVersion and not the server’s answer; an earlier version of this note said it reads the request’s own protocolVersion, which that measurement does not support. Whether a 2026-07-28 clause binds a request that is itself speaking 2025-11-25 is not settled by the text: the matrix describes the request as lacking the fields without saying the legacy client is non-conformant for it, and nothing makes a 2025-11-25 client subject to 2026-07-28. The same question sits under our TRAN-071 finding on the probe capture’s legacy initialize.
BASE-030 (MUST): Client requests carry the following
io.modelcontextprotocol/*fields inmeta; fields marked as required MUST be included on every request. — source
VERS-008 (SHOULD): A server that supports only modern versions SHOULD name the protocol versions it supports in any error it returns to an
initializerequest, on any transport: legacy clients have no fall-forward mechanism, and this message may be the only diagnostic they can surface to users. — source
Resolution: open: decide whether a legacy-era request inside a 2026-07-28 trace is held to that revision’s request-envelope clauses (BASE-030 and its restatements, TRAN-071); the current reading is recorded in checks/stateless/meta.rs
8. MRTR-002 (ours-only)
The legacy initialize of either trace above, under MRTR-002’s restatement of the same rule.
MRTR-002 (MUST): Every request MUST include the required
metafields; seemeta. — source
Resolution: open: the same decision as BASE-030 on these traces
9. TOOL-016 (ours-only)
The legacy initialize of either trace above, under TOOL-016’s restatement of the same rule.
TOOL-016 (MUST): Every request MUST include the required
metafields; seemeta. — source
Resolution: open: the same decision as BASE-030 on these traces
10. LIFE-018 (ours-only)
A 2025-11-25 HTTP session negotiates, then sends a request without MCP-Protocol-Version. 2025-11-25 requires the header on every request after initialization; mcpsnoop’s rule for a missing routing header (“missing where the negotiated revision requires it”) fires only at 2026-07-28. Reproduced on a session recorded by mcpsnoop’s own proxy, so the conversion is not the cause: native/version-header-omitted-2025-11-25.mcpsnoop.jsonl (initialize, notifications/initialized with the header, tools/list without it) passes mcpsnoop check with every signal enabled.
LIFE-018 (MUST): If using HTTP, the client MUST include the
MCP-Protocol-Version: <protocol-version>HTTP header on all subsequent requests to the MCP server. — source
TRAN-017 (MUST): 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. — source
Resolution: upstream: mcpsnoop-version-header-2025-11-25
11. TRAN-017 (ours-only)
The transport page’s statement of LIFE-018’s rule; the same missing header and the same mcpsnoop gap.
TRAN-017 (MUST): 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. — source
Resolution: upstream: mcpsnoop-version-header-2025-11-25
12. response-unmatched (mcpsnoop-only)
A POST carrying Host and Origin evil.example.com is refused with HTTP 403 and a JSON-RPC error that has no id; the session then proceeds from localhost. The transport’s security warning, at both revisions, describes exactly that answer: “If the Origin header is present and invalid, servers MUST respond with HTTP 403 Forbidden. The HTTP response body MAY comprise a JSON-RPC error response that has no id.” The refusal happens before the request is read, so there is no id to echo, and BASE-009/BASE-052’s id rule does not reach a body the transport clause permits to have none. mcpsnoop reports the id-less error as matching no request. We did the same, as BASE-009, until 2026-10-13 — on the official suite’s dns-rebinding-protection scenario against the everything server (conformance/wire-findings.json) — and these two traces are the regression pair for that fix.
BASE-009 (MUST): 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). — source
BASE-052 (MUST): 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). — source
Resolution: upstream: mcpsnoop-origin-refusal-unmatched
13. progress-after-completion (mcpsnoop-only)
A conforming 2025-11-25 task session: the server answers a task-augmented tools/call with a CreateTaskResult (seq 4) and sends progress under the request’s token while the task is working (seq 5, and seq 10 after a tasks/get that still says working); the task is completed only at seq 12. The tasks page has the token “continue to be used for progress notifications throughout the task’s lifetime, even after the CreateTaskResult has been returned” (PROG-014) and stops progress at the task’s terminal status (PROG-016), which this session respects; our validator passes it. mcpsnoop 0.26.1 warns on both notifications as arriving “after its request completed”, with the text “2026-07-28 requires them to stop”: it takes the CreateTaskResult for the request’s completion and applies that revision’s rule to a 2025-11-25 session. The same rule fires, correctly, on prog-019 (progress after an ordinary response) and, for the earlier of its two notifications, wrongly on prog-016 for the same reason as here; both traces agree with us at the trace level.
PROG-014 (MUST): 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. — source
PROG-016 (MUST): Progress notifications for tasks MUST stop after the task reaches a terminal status (
completed,failed, orcancelled) — source
Resolution: open: whether to report it upstream is the maintainer’s call; the reproduction is corpus/good/stdio-task-progress.jsonl, whose task handling the 2025-11-25 tasks page defines (PROG-014)
Found on live recordings
Divergences that only a session recorded by mcpsnoop itself shows, because they turn on something our trace format does not record.
response-unmatched — mcpsnoop-defect, right: ours
Recorded live: the reference host drives the everything server over Streamable HTTP at 2025-11-25, through mcp-trace-capture and mcpsnoop’s proxy at once. The server sends elicitation/create (and sampling/createMessage) on a tool call’s SSE stream; the client answers each with a new POST, as the transport requires — and its HTTP pool sends that POST on a different TCP connection. mcpsnoop pairs a server request with its answer only within one connection, so it reports each answer as “response id has no matching request” and each server request as never answered: five false warn findings and five false pending ones. Rewriting the capture’s conn_id to one value removes exactly those ten and nothing else, and our converted trace — which carries no connection — draws the remaining findings exactly. A JSON-RPC id is scoped to the session, never to a connection, and nothing obliges a client to reuse one.
Evidence: conformance/mcpsnoop/native/http-2025-11-25.mcpsnoop.jsonl, conformance/mcpsnoop/native/http-2025-11-25.trace.jsonl.
BASE-003 (MUST NOT): The request ID MUST NOT have been previously used by the requestor within the same session. — source
TRAN-024 (MUST): Every JSON-RPC message sent from the client MUST be a new HTTP POST request to the MCP endpoint. — source
Resolution: upstream: mcpsnoop-connection-scoped-ids
protocol-version-header-missing — mcpsnoop-defect, right: ours
The live reproduction of divergence LIFE-018 above: a 2025-11-25 session through mcpsnoop’s proxy whose tools/list POST omits MCP-Protocol-Version after a completed handshake. mcpsnoop check with every signal enabled exits 0.
Evidence: conformance/mcpsnoop/native/version-header-omitted-2025-11-25.mcpsnoop.jsonl.
LIFE-018 (MUST): If using HTTP, the client MUST include the
MCP-Protocol-Version: <protocol-version>HTTP header on all subsequent requests to the MCP server. — source
TRAN-017 (MUST): 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. — source
Resolution: upstream: mcpsnoop-version-header-2025-11-25
Upstream issue drafts
Written for mcpsnoop’s tracker and not filed: filing is the owner’s call.
mcpsnoop-connection-scoped-ids: check: server-to-client requests answered on another connection are reported as unanswered (HTTP)
Version: mcpsnoop 0.26.1 (npm, linux-x64).
What happens. On a streamable-HTTP session at 2025-11-25, the server sends elicitation/create on a tools/call SSE stream. The client answers it with a new POST, as the transport requires (“Every JSON-RPC message sent from the client MUST be a new HTTP POST request to the MCP endpoint”). The client’s HTTP pool sent that POST on a different TCP connection, so it was recorded with a different conn_id. mcpsnoop check then reports response id has no matching request (warn) on the answer and elicitation/create (id 0) never got a response (pending) on the request — once per server request in the session.
Expected. A JSON-RPC id is scoped to the session, not to a connection (2025-11-25 basic: “The request ID MUST NOT have been previously used by the requestor within the same session”), and a client may send each POST on any connection. A server request should be paired with the client’s response by id within the session.
Evidence. Recorded by mcpsnoop http in front of a streamable-HTTP server, with the reference client answering four elicitation/create and one sampling/createMessage: ten findings (five warn, five pending). Rewriting every conn_id in the capture to one value and re-running check removes exactly those ten.
Suggested fix. Key outstanding server-to-client requests by session (and direction), not by conn_id; keep the connection only for routing-header attribution.
mcpsnoop-null-id-answer: check: an id-less error returned in a POST’s own body leaves the request in flight, so a later reuse is reported
Version: mcpsnoop 0.26.1.
What happens. Streamable HTTP, 2026-07-28. The client POSTs tools/call with id: 1; the server answers that POST, in its own application/json body, with {"jsonrpc":"2.0","id":null,"error":{"code":-32602,...}}. check correctly reports response id has no matching request — the id was readable, so the server should have echoed it. The client then POSTs a new request reusing id: 1, and check reports request reuses an id already in flight.
Expected. The request is not in flight: its answer arrived as the response to the very POST that carried it, and both envelopes carry the same exchange. The specification forbids reusing an id only while “the sender has issued and not yet received a response for” it. The null id is the server’s defect, already reported; the reuse is not the client’s.
Suggested fix. On HTTP, when a response with a null (or unmatched) id arrives on an exchange that carried exactly one request, close that request — or at least do not count it as in flight for the reuse rule.
mcpsnoop-trusts-header-mismatch-rejection: check: a server’s -32020 is reported as “a routing header disagrees with the body” even when every header matches
Version: mcpsnoop 0.26.1.
What happens. Streamable HTTP, 2026-07-28. A tools/call whose tool marks region with x-mcp-header, sent with "region": null and therefore no Mcp-Param-Region header — the behaviour table says “Parameter value is null | Client MUST omit the header | Server MUST NOT expect the header”. The server wrongly rejects it with -32020 (HeaderMismatch). check reports mismatch: a routing header disagrees with the body. The same happens when the parameter is absent from the arguments, and when a server answers -32020 to a tools/list whose Mcp-Method and MCP-Protocol-Version match the body.
Expected. No header disagrees with the body in these requests, and mcpsnoop’s own comparison found none. The faulty party is the server. The rule description says a server’s -32020 “counts as the same condition”, which convicts the client’s headers on the server’s word.
Suggested fix. Report a -32020 as a mismatch only when mcpsnoop’s own comparison agrees, or could not be made (for instance, the tool definition was not captured). When the comparison ran and found the headers consistent, report the rejection as the server’s — a separate message, or none.
mcpsnoop-version-header-2025-11-25: check: a missing MCP-Protocol-Version header is not reported on 2025-11-25 sessions
Version: mcpsnoop 0.26.1.
What happens. A streamable-HTTP session negotiates 2025-11-25 (initialize, then notifications/initialized carrying MCP-Protocol-Version: 2025-11-25), then POSTs tools/list without the header. check --fail-on error,invalid,warn,mismatch,pending,late-result,duplicate,deprecated,incomplete exits 0.
Expected. 2025-11-25 requires the header: “If using HTTP, the client MUST include the MCP-Protocol-Version: <protocol-version> HTTP header on all subsequent requests to the MCP server.” The mismatch signal’s description already covers a routing header that “is missing where the negotiated revision requires it”; at present only 2026-07-28 is treated as requiring it.
Reproduce. mcpsnoop http --target <server>/mcp, then with curl: an initialize POST, an initialized POST with the header and the returned Mcp-Session-Id, and a tools/list POST with the session id but no MCP-Protocol-Version. Run mcpsnoop check on the session.
Suggested fix. At 2025-11-25 (and 2025-06-18), require the header on every POST after the initialize exchange.
mcpsnoop-origin-refusal-unmatched: check: the id-less error body of a 403 Origin refusal is reported as a response with no matching request
Version: mcpsnoop 0.26.1.
What happens. Streamable HTTP, 2025-11-25 or 2026-07-28. A POST arrives with Origin: http://evil.example.com; the server refuses it with 403 Forbidden and the body {"jsonrpc":"2.0","error":{"code":-32600,"message":"Forbidden: Origin not allowed"}}. check reports response id has no matching request on that error.
Expected. No finding. The transport’s security warning reads: “If the Origin header is present and invalid, servers MUST respond with HTTP 403 Forbidden. The HTTP response body MAY comprise a JSON-RPC error response that has no id.” The server refuses before it reads the request, so it has no id to echo, and the specification permits the body that results.
Suggested fix. When an id-less error is the body of a 403 answering a request that carried an Origin header, treat it as that exchange’s refusal rather than as an unmatched response.
The rule map
Each mcpsnoop rule, the message template that identifies it (* is any run), and the clauses it corresponds to; italic ids are partial. Fired counts traces where the rule fired and was not set aside. A rule no trace fires was read from the binary’s strings and is untested here.
| Rule | Template | 2025-11-25 | 2026-07-28 | Context | Fired | Reading |
|---|---|---|---|---|---|---|
jsonrpc-version | jsonrpc must be 2.0 | BASE-008 | BASE-042 | body | 1 | A frame whose jsonrpc member is not "2.0": one of the JSON-RPC 2.0 rules every message must follow. |
invalid-frame | frame on the protocol channel is not valid JSON-RPC | BASE-008, TRAN-004, TRAN-005 | BASE-042, TRAN-117, TRAN-118 | body | 3 | A frame that does not parse as a JSON-RPC message at all (a non-JSON line, an array, an object of no JSON-RPC shape). A frame that parses but breaks a narrower JSON-RPC rule is left to the rules below. |
request-id-type | request id has type * MCP requires a string or integer id | BASE-001 | BASE-043 | body | 1 | A request id that is neither a string nor an integer. |
request-id-null | request id is null; MCP requires a string or integer id | BASE-001, BASE-002 | BASE-043, BASE-044 | body | 1 | A request id that is null. The message itself names both clauses: null is not a string or integer id, and MCP forbids it outright. |
request-id-in-flight | request reuses an id already in flight | BASE-003 | BASE-045 | pairing | 2 | A request reusing the id of one of its sender’s requests that has not been answered. At 2025-11-25 the clause is wider — no reuse within the session at all — and in-flight reuse is the part mcpsnoop checks. |
response-unmatched | response id has no matching request | BASE-004, BASE-009 | BASE-046, BASE-052 | pairing | 10 | A response whose id names no outstanding request: the clauses requiring a response to carry the id of the request it answers. |
response-duplicate | duplicate response for the same id | BASE-004, BASE-009 | BASE-046, BASE-052 | pairing | 1 | A second response for an id already answered, which corresponds to no outstanding request. |
response-without-result-or-error | response has neither result nor error | BASE-010 | BASE-047 | body | 1 | A response carrying neither result nor error. |
response-with-result-and-error | response has both result and error | BASE-008 | BASE-042 | body | 0 | A response carrying both result and error, which JSON-RPC 2.0 forbids. Template read from the binary; no corpus trace exercises it. |
result-type-missing | result is missing required resultType | — | BASE-048 | body | 1 | A result without resultType. The field does not exist at 2025-11-25. |
client-sent-response | client sent a JSON-RPC response, which * no longer defines | — | TRAN-060, TRAN-119, BASE-084 | body | 1 | A client sending a JSON-RPC response at 2026-07-28, where a server sends no requests to answer. |
server-sent-request | server sent a JSON-RPC request *, which * replaced with the MRTR pattern | — | BASE-084, MRTR-001, TRAN-066, TRAN-120 | body | 1 | A server-initiated JSON-RPC request at 2026-07-28, which replaced them with multi round-trip requests. |
request-meta-missing | request _meta is missing required io.modelcontextprotocol/ | — | BASE-030, MRTR-002, TOOL-016 | body | 6 | A request without one of the _meta fields 2026-07-28 requires on every request. |
protocol-version-header-missing | required routing header MCP-Protocol-Version is missing | LIFE-018, TRAN-017 | TRAN-071 | http | 1 | A POST without the MCP-Protocol-Version header where the negotiated revision requires it. |
method-name-header-missing | required routing header Mcp-Method is missingrequired routing header Mcp-Name is missing | — | TRAN-058 | http | 2 | A POST without its Mcp-Method or Mcp-Name request metadata header. |
param-header-missing | required routing header Mcp-Param-* is missing for body parameter | — | TRAN-079, TRAN-130 | http | 4 | A tools/call carrying a parameter its tool marks with x-mcp-header, sent without the mirrored Mcp-Param-* header. |
protocol-version-header-disagrees | MCP-Protocol-Version header * disagrees with _meta protocolVersion | — | TRAN-072 | http | 7 | An MCP-Protocol-Version header that differs from the body’s _meta protocol version. |
method-header-disagrees | routing header Mcp-Method * disagrees with body method | — | TRAN-058 | http | 0 | An Mcp-Method header that is not the body’s method. Template read from the binary; no corpus trace exercises it. |
name-header-disagrees | routing header Mcp-Name * disagrees with body name | — | TRAN-058, TRAN-077, TRAN-092 | http | 3 | An Mcp-Name header that is not the body’s name after Base64 decoding. It catches an encoding fault only when the fault changes the value: a plain value shaped like the sentinel decodes to something else (TRAN-092), while an unencoded non-ASCII name that equals the body passes (TRAN-077). |
param-header-disagrees | routing header Mcp-Param-* disagrees with body parameter | — | TRAN-079, TRAN-086, TRAN-087, TRAN-089, TRAN-092 | http | 4 | An Mcp-Param-* header that is not the mirrored body value after Base64 decoding. The encoding clauses are caught only where a fault changes the value (a miscased sentinel does not decode); an unencoded value equal to the body passes. |
param-header-without-value | routing header Mcp-Param-* is present but body parameter * is absent or null | — | TRAN-132, TRAN-134 | http | 2 | An Mcp-Param-* header sent although the body parameter is null or absent. |
batch-routing-headers | routing headers are invalid on a JSON-RPC batch | TRAN-026 | TRAN-059 | http | 0 | Routing headers on a POST whose body is a batch. Template read from the binary; mcpsnoop reports an HTTP batch only when routing headers ride it. |
server-rejected-header-mismatch | a routing header disagrees with the body | — | TRAN-058, TRAN-071, TRAN-072, TRAN-077, TRAN-079, TRAN-086, TRAN-087, TRAN-089, TRAN-092, TRAN-130, TRAN-132, TRAN-134 | http | 10 | The server answered -32020 (HeaderMismatch). mcpsnoop counts the rejection itself as the routing fault, which convicts the client’s headers on the server’s word. |
response-content-type | the response to a request * the transport * application/json or text/event-stream | TRAN-029 | TRAN-063 | http | 4 | A POST carrying a request answered with a Content-Type other than application/json or text/event-stream, or with none. |
cacheable-without-ttl | cacheable * result declares no ttlMs, which * requires | — | CACH-001 | body | 9 | A complete result of a cacheable operation without ttlMs. CACH-001 asks for caching hints; mcpsnoop checks ttlMs and not cacheScope. |
cache-scope-across-pages | cacheScope * on a later page of * disagrees with | — | CACH-015, CACH-016 | body | 1 | Pages of one list request carrying different cacheScope values. |
cache-scope-value | cacheScope is *, and * defines only public and private | — | wire-schema | body | 1 | A cacheScope outside public and private. No RFC 2119 clause states the enumeration; the revision’s JSON Schema does, which the report judges as its wire schema. |
negative-ttl | ttlMs is *, and * requires a value of zero or more | — | CACH-008 | body | 1 | A negative ttlMs. |
input-required-empty | InputRequiredResult carries neither inputRequests nor requestState | — | MRTR-011 | body | 1 | An InputRequiredResult with neither inputRequests nor requestState. |
input-required-on-method | InputRequiredResult on *, which * allows only on | — | MRTR-004 | body | 1 | An InputRequiredResult answering a method that may not return one. |
input-request-method | inputRequests names *, and * allows only | — | MRTR-006 | body | 1 | An inputRequests entry that is not an elicitation, sampling or roots request. |
input-request-undeclared | inputRequests asks for * while the request declared no | — | BASE-034, MRTR-012, MRTR-013 | body | 3 | An inputRequests entry for a capability the request did not declare at all. A declared capability whose mode or sub-capability is missing (URL-mode elicitation, sampling.tools) is not compared. |
request-state-changed | MRTR retry changed requestState | — | MRTR-016, MRTR-003, MRTR-017 | body | 2 | A retry echoing a requestState other than the one the server sent. |
request-state-missing | MRTR retry is missing requestState | — | MRTR-016 | body | 0 | A retry leaving out the requestState the server sent. Template read from the binary; no corpus trace exercises it. |
request-state-invented | MRTR retry invented requestState | — | MRTR-018 | body | 1 | A retry carrying a requestState the server never sent. |
subscription-before-ack | arrived on subscription * before its acknowledgment | — | SUBS-002 | body | 2 | A subscription notification sent before the subscription’s acknowledgment. |
subscription-untagged | carries no io.modelcontextprotocol/subscriptionId | — | BASE-039 | body | 1 | A notification on a subscription stream without io.modelcontextprotocol/subscriptionId. BASE-039 also requires the id to be the stream’s own; mcpsnoop checks presence. |
subscription-unrequested | was not requested by subscription | — | SUBS-001 | body | 1 | A notification type the subscription did not ask for. SUBS-001 binds every notification the server sends; mcpsnoop checks those that carry a subscription id. |
progress-not-increasing | progress for token * went from * requires it to increase | PROG-011 | PROG-003 | body | 2 | A progress value that does not increase. |
progress-after-completion | progress notification for token * arrived after its request completed | PROG-019 | PROG-008 | body | 4 | A progress notification after its request was answered. |
server-cancellation | server cancelled *, and * lets a server cancel only a subscriptions/listen request | — | CANC-003, CANC-011 | body | 2 | A server-sent notifications/cancelled naming anything but a subscriptions/listen request. |
input-schema-not-object | advertises an inputSchema that is not a JSON object | TOOL-003 | TOOL-025 | body | 1 | A tool whose inputSchema is not a JSON Schema object. |
x-mcp-header-chain | declares an x-mcp-header under *, which * does not allow in the chain | — | TRAN-082, TRAN-137, TOOL-045 | body | 5 | An x-mcp-header on a property not reachable through properties alone. |
x-mcp-header-repeated | declares x-mcp-header * on more than one property | — | TRAN-080, TOOL-033 | body | 1 | One x-mcp-header name on two properties of a tool: one of the constraints TRAN-080 lists. |
task-for-undeclaring-client | a task handle uses the io.modelcontextprotocol/tasks extension, which the client never advertised | — | TASK-001, VERS-005 | body | 1 | A CreateTaskResult answering a request whose client capabilities do not declare the tasks extension. The tasks extension’s own clause, TASK-001 — reported in the extension’s block and never scored — names exactly this; mcpsnoop cites the core negotiation clause VERS-005, of which it is one case and which our registry excludes because each extension, not the core, says what falling back means. |
Every trace
| Trace | Revision | Ours | We flag | mcpsnoop | Rules fired | Set aside | Relation |
|---|---|---|---|---|---|---|---|
good/http-authorization | 2025-11-25 | pass | — | silent | — | — | both clean |
good/http-origin-refused-without-id | 2025-11-25 | pass | — | flags | response-unmatched | — | divergent |
good/http-session | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-cancellation | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-client-features | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-feature-session | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-full-session | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-minimal-init | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-progress | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-request-unanswered-at-close | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-requests-partly-unanswered | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-server-negotiates-2024-11-05 | 2025-11-25 | pass | — | silent | — | — | both clean |
good/stdio-task-progress | 2025-11-25 | pass | — | flags | progress-after-completion | — | divergent |
good/stdio-tool-image-base64-padding | 2025-11-25 | pass | — | silent | — | — | both clean |
violations/auth-014-challenge-without-scope | 2025-11-25 | pass-with-warnings | AUTH-014 | silent | — | — | beyond mcpsnoop |
violations/auth-045-invalid-token-answered-403 | 2025-11-25 | fail | AUTH-045, AUTH-049 | silent | — | — | beyond mcpsnoop |
violations/auth-049-insufficient-scope-answered-401 | 2025-11-25 | fail | AUTH-049, AUTH-050 | silent | — | — | beyond mcpsnoop |
violations/auth-050-insufficient-scope-without-resource-metadata | 2025-11-25 | pass-with-warnings | AUTH-050 | silent | — | — | beyond mcpsnoop |
violations/auth-051-insufficient-scope-names-no-scope | 2025-11-25 | pass-with-warnings | AUTH-050, AUTH-051 | silent | — | — | beyond mcpsnoop |
violations/base-001-request-id-boolean | 2025-11-25 | fail | BASE-001, wire-schema | flags | request-id-type | — | agree |
violations/base-002-request-id-null | 2025-11-25 | fail | BASE-001, BASE-002, wire-schema | flags | request-id-null | — | agree |
violations/base-003-request-id-reuse | 2025-11-25 | fail | BASE-003 | silent | — | — | beyond mcpsnoop |
violations/base-004-request-answered-twice-cross-flavor | 2025-11-25 | fail | BASE-004, PING-001 | flags | response-duplicate | — | agree |
violations/base-004-result-unknown-id | 2025-11-25 | fail | BASE-004 | flags | response-unmatched | — | agree |
violations/base-005-notification-with-id | 2025-11-25 | fail | BASE-005, LIFE-003 | silent | — | — | beyond mcpsnoop |
violations/base-006-error-missing-message | 2025-11-25 | fail | BASE-006, wire-schema | silent | — | — | beyond mcpsnoop |
violations/base-007-error-code-float | 2025-11-25 | fail | BASE-007, wire-schema | flags | invalid-frame | — | divergent |
violations/base-008-jsonrpc-version | 2025-11-25 | fail | BASE-008, wire-schema | flags | jsonrpc-version | — | agree |
violations/base-009-error-unknown-id | 2025-11-25 | fail | BASE-009 | flags | response-unmatched | — | agree |
violations/base-010-response-without-result | 2025-11-25 | fail | BASE-008, BASE-010, TRAN-004, wire-schema | flags | response-without-result-or-error | — | agree |
violations/base-017-input-schema-invalid | 2025-11-25 | fail | BASE-017 | silent | — | — | beyond mcpsnoop |
violations/base-019-meta-key-bad-prefix | 2025-11-25 | fail | BASE-019, BASE-020 | silent | — | — | beyond mcpsnoop |
violations/base-086-input-schema-draft-07 | 2025-11-25 | pass-with-warnings | BASE-086 | silent | — | — | beyond mcpsnoop |
violations/canc-018-cancellation-of-unknown-request | 2025-11-25 | fail | CANC-018 | silent | — | — | beyond mcpsnoop |
violations/canc-019-initialize-cancelled | 2025-11-25 | fail | CANC-019 | silent | — | — | beyond mcpsnoop |
violations/canc-020-task-cancelled-by-notification | 2025-11-25 | fail | CANC-020 | silent | — | — | beyond mcpsnoop |
violations/canc-021-response-after-cancellation-read | 2025-11-25 | pass-with-warnings | CANC-021 | silent | — | — | beyond mcpsnoop |
violations/comp-001-capability-undeclared | 2025-11-25 | fail | COMP-001, LIFE-009 | silent | — | — | beyond mcpsnoop |
violations/elic-004-answered-without-capability | 2025-11-25 | fail | ELIC-004, ELIC-006, LIFE-009 | silent | — | — | beyond mcpsnoop |
violations/elic-006-url-mode-undeclared | 2025-11-25 | fail | ELIC-006, LIFE-009 | silent | — | — | beyond mcpsnoop |
violations/elic-007-request-without-message | 2025-11-25 | fail | ELIC-007, wire-schema | silent | — | — | beyond mcpsnoop |
violations/elic-009-form-without-schema | 2025-11-25 | fail | ELIC-009, wire-schema | silent | — | — | beyond mcpsnoop |
violations/elic-011-url-without-elicitation-id | 2025-11-25 | fail | ELIC-011, wire-schema | silent | — | — | beyond mcpsnoop |
violations/elic-012-url-without-scheme | 2025-11-25 | fail | ELIC-012 | silent | — | — | beyond mcpsnoop |
violations/elic-014-complete-names-unknown-id | 2025-11-25 | fail | ELIC-014 | silent | — | — | beyond mcpsnoop |
violations/elic-018-url-required-error-without-list | 2025-11-25 | fail | ELIC-018, wire-schema | silent | — | — | beyond mcpsnoop |
violations/elic-019-url-required-error-form-mode | 2025-11-25 | fail | ELIC-019, wire-schema | silent | — | — | beyond mcpsnoop |
violations/elic-021-undeclared-mode-accepted | 2025-11-25 | fail | ELIC-006, ELIC-021, LIFE-009 | silent | — | — | beyond mcpsnoop |
violations/elic-049-accepted-content-violates-schema | 2025-11-25 | pass-with-warnings | ELIC-049 | silent | — | — | beyond mcpsnoop |
violations/life-001-first-message-not-initialize | 2025-11-25 | fail | LIFE-001, LIFE-004 | silent | — | — | beyond mcpsnoop |
violations/life-002-initialize-missing-protocolversion | 2025-11-25 | fail | LIFE-002, LIFE-007, wire-schema | silent | — | — | beyond mcpsnoop |
violations/life-003-missing-initialized | 2025-11-25 | fail | LIFE-003 | silent | — | — | beyond mcpsnoop |
violations/life-004-client-request-before-init-response | 2025-11-25 | pass-with-warnings | LIFE-004 | silent | — | — | beyond mcpsnoop |
violations/life-005-server-request-before-initialized | 2025-11-25 | pass-with-warnings | LIFE-005 | silent | — | — | beyond mcpsnoop |
violations/life-006-result-version-invalid | 2025-11-25 | fail | LIFE-006 | silent | — | — | beyond mcpsnoop |
violations/life-007-initialize-protocolversion-not-string | 2025-11-25 | fail | LIFE-002, LIFE-007, wire-schema | silent | — | — | beyond mcpsnoop |
violations/life-009-undeclared-capability-use | 2025-11-25 | fail | LIFE-009 | silent | — | — | beyond mcpsnoop |
violations/life-010-initialize-result-missing-capabilities | 2025-11-25 | fail | LIFE-010, wire-schema | silent | — | — | beyond mcpsnoop |
violations/log-001-capability-undeclared | 2025-11-25 | fail | LIFE-009, LOG-001 | silent | — | — | beyond mcpsnoop |
violations/page-002-cursor-never-issued | 2025-11-25 | fail | PAGE-002, PAGE-003 | silent | — | — | beyond mcpsnoop |
violations/page-002-fabricated-cursor-rejected | 2025-11-25 | fail | PAGE-002 | silent | — | — | beyond mcpsnoop |
violations/ping-001-ping-answered-with-content | 2025-11-25 | fail | PING-001 | silent | — | — | beyond mcpsnoop |
violations/prog-009-progress-token-float | 2025-11-25 | fail | PROG-009, wire-schema | silent | — | — | beyond mcpsnoop |
violations/prog-010-progress-token-reused-in-flight | 2025-11-25 | fail | PROG-010 | silent | — | — | beyond mcpsnoop |
violations/prog-011-progress-value-decreases | 2025-11-25 | fail | PROG-011 | flags | progress-not-increasing | — | agree |
violations/prog-013-progress-token-never-issued | 2025-11-25 | fail | PROG-013 | silent | — | — | beyond mcpsnoop |
violations/prog-015-task-progress-token-differs | 2025-11-25 | fail | PROG-013, PROG-014, PROG-015 | silent | — | — | beyond mcpsnoop |
violations/prog-016-task-progress-after-terminal-status | 2025-11-25 | fail | PROG-013, PROG-016, PROG-019 | flags | progress-after-completion | — | agree |
violations/prog-019-progress-after-completion | 2025-11-25 | fail | PROG-013, PROG-016, PROG-019 | flags | progress-after-completion | — | agree |
violations/prom-001-capability-undeclared | 2025-11-25 | fail | LIFE-009, PROM-001 | silent | — | — | beyond mcpsnoop |
violations/prom-003-image-data-invalid | 2025-11-25 | fail | PROM-003, wire-schema | silent | — | — | beyond mcpsnoop |
violations/prom-004-audio-data-invalid | 2025-11-25 | fail | PROM-004, wire-schema | silent | — | — | beyond mcpsnoop |
violations/prom-005-embedded-resource-malformed | 2025-11-25 | fail | PROM-005, wire-schema | silent | — | — | beyond mcpsnoop |
violations/prom-008-required-argument-unvalidated | 2025-11-25 | pass-with-warnings | PROM-008 | silent | — | — | beyond mcpsnoop |
violations/res-001-capability-undeclared | 2025-11-25 | fail | LIFE-009, RES-001 | silent | — | — | beyond mcpsnoop |
violations/res-004-uri-bad-scheme | 2025-11-25 | fail | RES-004 | silent | — | — | beyond mcpsnoop |
violations/res-006-blob-not-base64 | 2025-11-25 | fail | RES-006, wire-schema | silent | — | — | beyond mcpsnoop |
violations/root-001-answered-without-capability | 2025-11-25 | fail | LIFE-009, ROOT-001, ROOT-004, ROOT-009 | silent | — | — | beyond mcpsnoop |
violations/root-003-root-not-file-uri | 2025-11-25 | fail | ROOT-003 | silent | — | — | beyond mcpsnoop |
violations/root-004-unsupported-answered-internal-error | 2025-11-25 | fail | LIFE-009, ROOT-004, ROOT-009 | silent | — | — | beyond mcpsnoop |
violations/root-009-asked-without-capability | 2025-11-25 | fail | LIFE-009, ROOT-009 | silent | — | — | beyond mcpsnoop |
violations/samp-004-tools-without-sampling-tools | 2025-11-25 | fail | LIFE-009, SAMP-004 | silent | — | — | beyond mcpsnoop |
violations/samp-005-answered-without-capability | 2025-11-25 | fail | LIFE-009, SAMP-005 | silent | — | — | beyond mcpsnoop |
violations/samp-006-include-context-deprecated | 2025-11-25 | pass-with-warnings | SAMP-006 | silent | — | — | beyond mcpsnoop |
violations/samp-007-include-context-undeclared | 2025-11-25 | pass-with-warnings | SAMP-006, SAMP-007 | silent | — | — | beyond mcpsnoop |
violations/samp-008-tool-results-mixed | 2025-11-25 | fail | SAMP-008, SAMP-009, SAMP-019 | silent | — | — | beyond mcpsnoop |
violations/samp-009-tool-use-unanswered | 2025-11-25 | fail | SAMP-009, SAMP-019 | silent | — | — | beyond mcpsnoop |
violations/samp-010-required-tool-choice-ignored | 2025-11-25 | fail | SAMP-010 | silent | — | — | beyond mcpsnoop |
violations/samp-011-none-tool-choice-ignored | 2025-11-25 | fail | SAMP-011 | silent | — | — | beyond mcpsnoop |
violations/samp-012-malformed-tool-messages-answered | 2025-11-25 | fail | SAMP-009, SAMP-012, SAMP-019 | silent | — | — | beyond mcpsnoop |
violations/tool-001-capability-undeclared | 2025-11-25 | fail | LIFE-009, TOOL-001 | silent | — | — | beyond mcpsnoop |
violations/tool-003-input-schema-null | 2025-11-25 | fail | BASE-017, TOOL-003, wire-schema | flags | input-schema-not-object | — | agree |
violations/tool-005-name-length | 2025-11-25 | pass-with-warnings | TOOL-005 | silent | — | — | beyond mcpsnoop |
violations/tool-006-name-charset | 2025-11-25 | pass-with-warnings | TOOL-006, TOOL-007 | silent | — | — | beyond mcpsnoop |
violations/tool-008-name-duplicate | 2025-11-25 | pass-with-warnings | TOOL-008 | silent | — | — | beyond mcpsnoop |
violations/tool-009-embedded-resource-without-capability | 2025-11-25 | pass-with-warnings | TOOL-009 | silent | — | — | beyond mcpsnoop |
violations/tool-010-structured-without-text | 2025-11-25 | pass-with-warnings | TOOL-010 | silent | — | — | beyond mcpsnoop |
violations/tool-011-output-schema-no-structured-result | 2025-11-25 | fail | TOOL-011 | silent | — | — | beyond mcpsnoop |
violations/tool-011-structured-content-not-conforming | 2025-11-25 | fail | TOOL-011 | silent | — | — | beyond mcpsnoop |
violations/tran-004-stdout-invalid-message | 2025-11-25 | fail | BASE-008, TRAN-004, wire-schema | flags | invalid-frame | — | agree |
violations/tran-005-stdin-invalid-message | 2025-11-25 | fail | BASE-008, TRAN-005, wire-schema | flags | invalid-frame | — | agree |
violations/tran-011-session-id-invisible-ascii | 2025-11-25 | fail | TRAN-011 | silent | — | — | beyond mcpsnoop |
violations/tran-013-session-id-not-echoed | 2025-11-25 | fail | TRAN-013 | silent | — | — | beyond mcpsnoop |
violations/tran-017-protocol-version-header-missing | 2025-11-25 | fail | LIFE-018, TRAN-017 | silent | — | — | divergent |
violations/tran-018-declined-version-header-refused-400 | 2025-11-25 | pass-with-warnings | TRAN-018 | silent | — | — | beyond mcpsnoop |
violations/tran-018-protocol-version-mismatched | 2025-11-25 | pass-with-warnings | TRAN-018 | silent | — | — | beyond mcpsnoop |
violations/tran-020-declined-version-header-accepted | 2025-11-25 | fail | TRAN-018, TRAN-020 | silent | — | — | beyond mcpsnoop |
violations/tran-025-accept-header-json-missing | 2025-11-25 | fail | TRAN-025 | silent | — | — | beyond mcpsnoop |
violations/tran-025-accept-header-missing | 2025-11-25 | fail | TRAN-025 | silent | — | — | beyond mcpsnoop |
violations/tran-026-http-post-batch | 2025-11-25 | fail | BASE-008, TRAN-026, wire-schema | silent | — | — | beyond mcpsnoop |
violations/tran-027-notification-answered-200 | 2025-11-25 | fail | TRAN-027 | silent | — | — | beyond mcpsnoop |
violations/tran-029-content-type-unexpected | 2025-11-25 | fail | TRAN-029 | flags | response-content-type | — | agree |
violations/tran-029-error-without-content-type | 2025-11-25 | fail | TRAN-029 | flags | response-content-type | — | agree |
violations/tran-039-get-accept-header-missing | 2025-11-25 | fail | TRAN-039 | silent | — | — | beyond mcpsnoop |
violations/tran-040-get-answered-json | 2025-11-25 | fail | TRAN-040 | silent | — | — | beyond mcpsnoop |
violations/tran-049-message-not-posted | 2025-11-25 | fail | TRAN-049 | silent | — | — | beyond mcpsnoop |
violations/wire-schema-content-block-unknown-type | 2025-11-25 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
violations/wire-schema-log-level-not-in-enum | 2025-11-25 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
violations/wire-schema-resource-missing-uri | 2025-11-25 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
violations/wire-schema-tool-image-data-not-base64 | 2025-11-25 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
draft/good/caching-ttl-written-as-float | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/client-features-mrtr | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/http-authorization | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/http-close-after-another-response | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/http-concurrent-posts | 2026-07-28 | pass | — | silent | — | method-name-header-missing, protocol-version-header-missing | both clean |
draft/good/http-dual-era-modern-request-first | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/http-origin-refused-without-id | 2026-07-28 | pass | — | flags | response-unmatched | — | divergent |
draft/good/http-stream-closed-by-client | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/http-upstream-abort | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/http-x-mcp-header-omitted | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/input-required-id-reused | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/logging-per-request | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/mrtr-parallel-rounds | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/mrtr-retry-round-before-recording | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/resource-read-existing-empty | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/skills-session | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/stateless-session | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/stdio-cancellation-race | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/stdio-cancelled-id-reused | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/stdio-discover-preferred-version-unsupported | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/stdio-progress | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/stdio-x-mcp-header-large-integer | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/streamable-http-session | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/subscription-id-reused-after-close | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/subscription-server-teardown | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/tasks-http | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/tasks-session | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/good/traceparent-higher-version | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/violations/auth-097-challenge-without-scope | 2026-07-28 | pass-with-warnings | AUTH-097 | silent | — | — | beyond mcpsnoop |
draft/violations/auth-124-invalid-token-answered-403 | 2026-07-28 | fail | AUTH-124, AUTH-130 | silent | — | — | beyond mcpsnoop |
draft/violations/auth-129-offline-access-challenged | 2026-07-28 | pass-with-warnings | AUTH-129 | silent | — | — | beyond mcpsnoop |
draft/violations/auth-130-insufficient-scope-answered-401 | 2026-07-28 | fail | AUTH-130, AUTH-131 | silent | — | — | beyond mcpsnoop |
draft/violations/auth-131-insufficient-scope-without-resource-metadata | 2026-07-28 | pass-with-warnings | AUTH-131 | silent | — | — | beyond mcpsnoop |
draft/violations/auth-132-insufficient-scope-names-no-scope | 2026-07-28 | pass-with-warnings | AUTH-131, AUTH-132 | silent | — | — | beyond mcpsnoop |
draft/violations/auth-133-scope-challenged-incrementally | 2026-07-28 | pass-with-warnings | AUTH-133 | silent | — | — | beyond mcpsnoop |
draft/violations/base-030-legacy-initialize-negotiated-2026-07-28 | 2026-07-28 | fail | BASE-030, COMP-006, DISC-002, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, TRAN-128 | silent | — | — | divergent |
draft/violations/base-030-malformed-request-id-reused-correctly | 2026-07-28 | fail | BASE-030, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | flags | request-meta-missing | — | agree |
draft/violations/base-030-malformed-request-refused-without-id | 2026-07-28 | fail | BASE-030, BASE-052, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | flags | request-meta-missing, response-unmatched | — | agree |
draft/violations/base-030-request-meta-missing-required-field | 2026-07-28 | fail | BASE-030, BASE-031, CACH-001, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | flags | cacheable-without-ttl, request-meta-missing | — | agree |
draft/violations/base-030-unsupported-version-refused-as-invalid-params | 2026-07-28 | fail | BASE-030, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | flags | request-meta-missing | — | agree |
draft/violations/base-031-malformed-meta-answered-with-result | 2026-07-28 | fail | BASE-030, BASE-031, CACH-001, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | silent | — | — | divergent |
draft/violations/base-031-reused-id-malformed-answered | 2026-07-28 | fail | BASE-030, BASE-031, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | flags | request-meta-missing | — | agree |
draft/violations/base-032-invalid-params-not-http-400 | 2026-07-28 | fail | BASE-030, BASE-032, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, wire-schema | silent | — | — | divergent |
draft/violations/base-033-request-without-client-info | 2026-07-28 | pass-with-warnings | BASE-033 | silent | — | — | beyond mcpsnoop |
draft/violations/base-034-input-request-for-undeclared-capability | 2026-07-28 | fail | BASE-034, ELIC-059, MRTR-012, MRTR-013, wire-schema | flags | input-request-undeclared | — | agree |
draft/violations/base-034-input-request-for-undeclared-mode | 2026-07-28 | fail | BASE-034, ELIC-059, MRTR-012, MRTR-013, SAMP-026 | silent | — | — | beyond mcpsnoop |
draft/violations/base-035-missing-capability-error-without-capabilities | 2026-07-28 | fail | BASE-035, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/base-036-missing-capability-not-http-400 | 2026-07-28 | fail | BASE-035, BASE-036, TRAN-063, wire-schema | flags | response-content-type | method-name-header-missing, protocol-version-header-missing | agree |
draft/violations/base-037-result-without-server-info | 2026-07-28 | pass-with-warnings | BASE-037 | silent | — | — | beyond mcpsnoop |
draft/violations/base-039-subscription-notification-mistagged | 2026-07-28 | fail | BASE-039 | silent | — | — | beyond mcpsnoop |
draft/violations/base-039-subscription-notification-untagged | 2026-07-28 | fail | BASE-039, wire-schema | flags | subscription-untagged | — | agree |
draft/violations/base-040-malformed-traceparent | 2026-07-28 | fail | BASE-040, CACH-001, wire-schema | flags | cacheable-without-ttl | — | agree |
draft/violations/base-040-traceparent-version-ff | 2026-07-28 | fail | BASE-040 | silent | — | — | beyond mcpsnoop |
draft/violations/base-045-request-id-reused-in-flight | 2026-07-28 | fail | BASE-045, CACH-001, wire-schema | flags | cacheable-without-ttl, request-id-in-flight | — | agree |
draft/violations/base-048-result-without-result-type | 2026-07-28 | fail | BASE-048, wire-schema | flags | result-type-missing | — | agree |
draft/violations/base-052-null-id-error-then-id-reused | 2026-07-28 | fail | BASE-052, wire-schema | flags | request-id-in-flight, response-unmatched | — | divergent |
draft/violations/base-057-undefined-reserved-error-code | 2026-07-28 | fail | BASE-057 | silent | — | — | beyond mcpsnoop |
draft/violations/base-058-withdrawn-error-code | 2026-07-28 | fail | BASE-058, BASE-083, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/base-060-app-code-in-reserved-range | 2026-07-28 | pass-with-warnings | BASE-060 | silent | — | — | beyond mcpsnoop |
draft/violations/base-073-input-schema-invalid | 2026-07-28 | fail | BASE-073 | silent | — | — | beyond mcpsnoop |
draft/violations/base-083-legacy-error-code | 2026-07-28 | pass-with-warnings | BASE-083 | silent | — | — | beyond mcpsnoop |
draft/violations/base-088-input-schema-draft-07 | 2026-07-28 | pass-with-warnings | BASE-088 | silent | — | — | beyond mcpsnoop |
draft/violations/cach-001-cacheable-result-without-hints | 2026-07-28 | fail | CACH-001, wire-schema | flags | cacheable-without-ttl | — | agree |
draft/violations/cach-001-ttl-without-cache-scope | 2026-07-28 | fail | CACH-001, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/cach-008-negative-ttl | 2026-07-28 | fail | CACH-008, wire-schema | flags | negative-ttl | — | agree |
draft/violations/cach-015-page-scope-changes | 2026-07-28 | fail | CACH-015, CACH-016 | flags | cache-scope-across-pages | — | agree |
draft/violations/canc-003-server-cancels-tool-call | 2026-07-28 | fail | CANC-003, CANC-011 | flags | server-cancellation | — | agree |
draft/violations/comp-007-completions-undeclared | 2026-07-28 | fail | COMP-007 | silent | — | — | beyond mcpsnoop |
draft/violations/disc-001-server-discover-method-not-found | 2026-07-28 | fail | DISC-001, VERS-003 | silent | — | — | beyond mcpsnoop |
draft/violations/disc-002-dual-era-client-skips-probe | 2026-07-28 | pass-with-warnings | DISC-002, TRAN-128 | silent | — | — | beyond mcpsnoop |
draft/violations/disc-003-discover-result-without-server-info | 2026-07-28 | pass-with-warnings | BASE-037, DISC-003 | silent | — | — | beyond mcpsnoop |
draft/violations/elic-057-answered-without-capability | 2026-07-28 | fail | ELIC-057 | silent | — | — | beyond mcpsnoop |
draft/violations/elic-059-url-mode-undeclared | 2026-07-28 | fail | BASE-034, ELIC-059, MRTR-012, MRTR-013 | silent | — | — | beyond mcpsnoop |
draft/violations/elic-060-request-without-message | 2026-07-28 | fail | ELIC-060, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/elic-062-form-without-schema | 2026-07-28 | fail | ELIC-062, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/elic-064-url-mode-without-url | 2026-07-28 | fail | ELIC-064, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/elic-065-url-not-a-valid-url | 2026-07-28 | fail | ELIC-065 | silent | — | — | beyond mcpsnoop |
draft/violations/elic-095-accepted-content-violates-schema | 2026-07-28 | pass-with-warnings | ELIC-095 | silent | — | — | beyond mcpsnoop |
draft/violations/log-007-logging-undeclared | 2026-07-28 | fail | LOG-007, TOOL-019, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/log-008-log-for-request-without-level | 2026-07-28 | fail | LOG-008 | silent | — | — | beyond mcpsnoop |
draft/violations/log-008-log-without-requested-level | 2026-07-28 | fail | LOG-008, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/log-009-log-on-subscription-stream | 2026-07-28 | fail | LOG-009, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/log-009-log-with-no-request-in-flight | 2026-07-28 | fail | LOG-009 | silent | — | — | beyond mcpsnoop |
draft/violations/log-010-unrecognized-log-level-accepted | 2026-07-28 | fail | LOG-010, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/mrtr-004-input-required-on-unsupported-method | 2026-07-28 | fail | MRTR-004 | flags | input-required-on-method | — | agree |
draft/violations/mrtr-006-input-request-unknown-method | 2026-07-28 | fail | MRTR-006, wire-schema | flags | input-request-method | — | agree |
draft/violations/mrtr-011-input-required-empty | 2026-07-28 | fail | MRTR-011 | flags | input-required-empty | — | agree |
draft/violations/mrtr-015-retry-without-input-responses | 2026-07-28 | fail | MRTR-015 | silent | — | — | beyond mcpsnoop |
draft/violations/mrtr-016-parallel-retry-alters-state | 2026-07-28 | fail | MRTR-003, MRTR-016, MRTR-017 | flags | request-state-changed | — | agree |
draft/violations/mrtr-016-request-state-not-echoed | 2026-07-28 | fail | MRTR-003, MRTR-016, MRTR-017 | flags | request-state-changed | — | agree |
draft/violations/mrtr-018-unsolicited-request-state | 2026-07-28 | fail | MRTR-018 | flags | request-state-invented | — | agree |
draft/violations/mrtr-019-retry-reuses-id | 2026-07-28 | fail | MRTR-019, TOOL-023 | silent | — | — | beyond mcpsnoop |
draft/violations/mrtr-020-request-state-on-another-method | 2026-07-28 | fail | MRTR-020 | silent | — | — | beyond mcpsnoop |
draft/violations/mrtr-024-shortfall-answered-with-error | 2026-07-28 | fail | MRTR-015, MRTR-024 | silent | — | — | beyond mcpsnoop |
draft/violations/prog-001-progress-token-not-integer | 2026-07-28 | fail | PROG-001, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/prog-002-progress-token-reused-in-flight | 2026-07-28 | fail | PROG-002 | silent | — | — | beyond mcpsnoop |
draft/violations/prog-003-progress-value-decreases | 2026-07-28 | fail | PROG-003 | flags | progress-not-increasing | — | agree |
draft/violations/prog-008-progress-after-completion | 2026-07-28 | fail | PROG-005, PROG-008 | flags | progress-after-completion | — | agree |
draft/violations/prom-012-prompts-undeclared | 2026-07-28 | fail | PROM-012 | silent | — | — | beyond mcpsnoop |
draft/violations/prom-013-declared-prompts-list-unimplemented | 2026-07-28 | fail | PROM-013 | silent | — | — | beyond mcpsnoop |
draft/violations/res-012-resources-undeclared | 2026-07-28 | fail | RES-012 | silent | — | — | beyond mcpsnoop |
draft/violations/res-013-declared-resources-list-unimplemented | 2026-07-28 | fail | RES-013 | silent | — | — | beyond mcpsnoop |
draft/violations/res-022-read-empty-contents | 2026-07-28 | fail | RES-022 | silent | — | — | beyond mcpsnoop |
draft/violations/root-013-answered-without-capability | 2026-07-28 | fail | ROOT-013 | silent | — | — | beyond mcpsnoop |
draft/violations/root-014-root-not-file-uri | 2026-07-28 | fail | ROOT-014 | silent | — | — | beyond mcpsnoop |
draft/violations/root-018-asked-without-capability | 2026-07-28 | fail | BASE-034, MRTR-012, MRTR-013, ROOT-018 | flags | input-request-undeclared | — | agree |
draft/violations/samp-026-tools-without-sampling-tools | 2026-07-28 | fail | BASE-034, MRTR-012, MRTR-013, SAMP-026 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-027-answered-without-capability | 2026-07-28 | fail | SAMP-027 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-028-include-context-deprecated | 2026-07-28 | pass-with-warnings | SAMP-028 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-029-include-context-undeclared | 2026-07-28 | pass-with-warnings | SAMP-028, SAMP-029 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-030-tool-results-mixed | 2026-07-28 | fail | SAMP-030, SAMP-031, SAMP-042 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-031-tool-use-unanswered | 2026-07-28 | fail | SAMP-031, SAMP-042 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-032-required-tool-choice-ignored | 2026-07-28 | fail | SAMP-032 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-033-none-tool-choice-ignored | 2026-07-28 | fail | SAMP-033 | silent | — | — | beyond mcpsnoop |
draft/violations/samp-034-message-without-role | 2026-07-28 | fail | SAMP-034, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/skill-003-directory-read-not-implemented | 2026-07-28 | pass | SKILL-003 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-004-directory-read-undeclared | 2026-07-28 | pass | SKILL-004 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-005-skills-without-resources | 2026-07-28 | pass | SKILL-005 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-007-entry-uri-not-skill-md | 2026-07-28 | pass | SKILL-007 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-008-skill-md-without-frontmatter | 2026-07-28 | pass | SKILL-008 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-011-skill-under-other-scheme | 2026-07-28 | pass | SKILL-011 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-012-path-not-ending-in-name | 2026-07-28 | pass | SKILL-012, SKILL-027 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-013-name-breaks-naming-rules | 2026-07-28 | pass | SKILL-013 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-014-authority-not-reg-name | 2026-07-28 | pass | SKILL-014 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-015-prefix-segment-invalid | 2026-07-28 | pass | SKILL-015 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-018-skill-md-not-markdown | 2026-07-28 | pass | SKILL-018 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-019-resource-name-not-skill-name | 2026-07-28 | pass | SKILL-019 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-020-resource-description-differs | 2026-07-28 | pass | SKILL-020 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-026-entry-frontmatter-differs | 2026-07-28 | pass | SKILL-026 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-029-listing-names-collide | 2026-07-28 | pass | SKILL-029 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-034-entry-without-resources | 2026-07-28 | pass | SKILL-034 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-035-manifest-without-skill-md | 2026-07-28 | pass | SKILL-035 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-036-manifest-file-outside-skill | 2026-07-28 | pass | SKILL-036 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-037-manifest-entry-without-size | 2026-07-28 | pass | SKILL-037 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-042-skill-beyond-limits | 2026-07-28 | pass | SKILL-042 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-044-list-not-implemented | 2026-07-28 | pass | SKILL-002, SKILL-044 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-045-list-result-type-not-complete | 2026-07-28 | pass | SKILL-045 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-047-list-without-cache-fields | 2026-07-28 | pass | SKILL-047 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-048-get-not-implemented | 2026-07-28 | pass | SKILL-002, SKILL-048 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-049-get-result-type-not-complete | 2026-07-28 | pass | SKILL-049 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-050-get-names-a-directory | 2026-07-28 | pass | SKILL-050 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-051-unknown-skill-wrong-error | 2026-07-28 | pass | SKILL-051, SKILL-071 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-053-get-without-cache-fields | 2026-07-28 | pass | SKILL-053 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-065-directory-result-type-not-complete | 2026-07-28 | pass | SKILL-065 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-066-directory-read-of-a-file-answered | 2026-07-28 | pass | SKILL-066, SKILL-071 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-067-skill-directory-refused | 2026-07-28 | pass | SKILL-067 | silent | — | — | beyond mcpsnoop |
draft/violations/skill-100-directory-result-without-cache-fields | 2026-07-28 | pass | SKILL-100 | silent | — | — | beyond mcpsnoop |
draft/violations/subs-001-cancelled-for-another-request | 2026-07-28 | fail | CANC-003, CANC-011, SUBS-001 | flags | server-cancellation | — | agree |
draft/violations/subs-001-unrequested-notification-type | 2026-07-28 | fail | SUBS-001, wire-schema | flags | subscription-unrequested | — | agree |
draft/violations/subs-002-notification-before-acknowledgment | 2026-07-28 | fail | SUBS-002, wire-schema | flags | subscription-before-ack | — | agree |
draft/violations/subs-002-reused-id-first-opening-unacknowledged | 2026-07-28 | fail | SUBS-002 | flags | subscription-before-ack | — | agree |
draft/violations/subs-006-graceful-close-result-not-empty | 2026-07-28 | pass-with-warnings | SUBS-005, SUBS-006 | silent | — | — | beyond mcpsnoop |
draft/violations/task-001-task-for-undeclaring-client | 2026-07-28 | pass | TASK-001 | flags | task-for-undeclaring-client | — | agree |
draft/violations/task-006-task-without-result-type | 2026-07-28 | fail | TASK-006, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/task-007-task-result-type-without-task | 2026-07-28 | pass | TASK-007 | silent | — | — | beyond mcpsnoop |
draft/violations/task-015-get-result-not-a-task | 2026-07-28 | pass | TASK-015 | silent | — | — | beyond mcpsnoop |
draft/violations/task-015-input-required-without-requests | 2026-07-28 | pass | TASK-015 | silent | — | — | beyond mcpsnoop |
draft/violations/task-017-get-result-type-not-complete | 2026-07-28 | pass | TASK-017, TASK-028, TASK-032 | silent | — | — | beyond mcpsnoop |
draft/violations/task-022-input-request-key-reused | 2026-07-28 | pass | TASK-022, TASK-023 | silent | — | — | beyond mcpsnoop |
draft/violations/task-024-update-ack-not-empty | 2026-07-28 | pass | TASK-024, TASK-030 | silent | — | — | beyond mcpsnoop |
draft/violations/task-026-input-answered-twice | 2026-07-28 | pass | TASK-026 | silent | — | — | beyond mcpsnoop |
draft/violations/task-029-task-cancelled-by-notification | 2026-07-28 | pass | TASK-029 | silent | — | — | beyond mcpsnoop |
draft/violations/task-033-task-listen-without-declaration | 2026-07-28 | pass | TASK-033, TASK-038 | silent | — | — | beyond mcpsnoop |
draft/violations/task-034-progress-on-task-stream | 2026-07-28 | fail | LOG-007, LOG-008, LOG-009, SUBS-001, TASK-034 | silent | — | — | beyond mcpsnoop |
draft/violations/task-035-mcp-name-missing | 2026-07-28 | pass | TASK-035 | silent | — | — | beyond mcpsnoop |
draft/violations/task-039-get-without-declaration | 2026-07-28 | pass | TASK-039 | silent | — | — | beyond mcpsnoop |
draft/violations/task-041-failed-without-status-message | 2026-07-28 | pass | TASK-041 | silent | — | — | beyond mcpsnoop |
draft/violations/task-042-failed-without-error | 2026-07-28 | pass | TASK-015, TASK-042, TASK-045 | silent | — | — | beyond mcpsnoop |
draft/violations/task-043-tool-error-reported-failed | 2026-07-28 | pass | TASK-008, TASK-043, TASK-044 | silent | — | — | beyond mcpsnoop |
draft/violations/task-046-completed-without-result | 2026-07-28 | pass | TASK-015, TASK-044, TASK-046 | silent | — | — | beyond mcpsnoop |
draft/violations/tool-019-tools-undeclared | 2026-07-28 | fail | TOOL-019 | silent | — | — | beyond mcpsnoop |
draft/violations/tool-020-declared-tools-list-unimplemented | 2026-07-28 | fail | TOOL-020 | silent | — | — | beyond mcpsnoop |
draft/violations/tool-022-tools-list-order-changes | 2026-07-28 | pass-with-warnings | TOOL-022 | silent | — | — | beyond mcpsnoop |
draft/violations/tool-034-mirrored-integer-out-of-range | 2026-07-28 | fail | TOOL-034, TRAN-081 | silent | — | method-name-header-missing, param-header-missing, protocol-version-header-missing | beyond mcpsnoop |
draft/violations/tool-038-embedded-resource-undeclared | 2026-07-28 | pass-with-warnings | TOOL-038 | silent | — | — | beyond mcpsnoop |
draft/violations/tool-040-structured-content-not-conforming | 2026-07-28 | fail | TOOL-040 | silent | — | — | beyond mcpsnoop |
draft/violations/tool-045-x-mcp-header-in-defs | 2026-07-28 | fail | TOOL-045, TRAN-082, TRAN-137 | flags | x-mcp-header-chain | method-name-header-missing, protocol-version-header-missing | agree |
draft/violations/tran-058-mcp-name-mismatch-refused-without-id | 2026-07-28 | fail | BASE-052, TRAN-058, TRAN-141, wire-schema | flags | name-header-disagrees, response-unmatched | — | agree |
draft/violations/tran-058-request-metadata-headers-missing | 2026-07-28 | fail | TRAN-058, TRAN-141 | flags | method-name-header-missing | — | agree |
draft/violations/tran-060-client-posts-a-response | 2026-07-28 | fail | BASE-046, CACH-001, TRAN-060, TRAN-119, wire-schema | flags | cacheable-without-ttl, client-sent-response, response-unmatched | — | agree |
draft/violations/tran-061-notification-answered-200 | 2026-07-28 | fail | TRAN-061 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-063-error-without-content-type | 2026-07-28 | fail | TRAN-063 | flags | response-content-type | — | agree |
draft/violations/tran-066-independent-server-request | 2026-07-28 | fail | BASE-084, MRTR-001, TRAN-066, TRAN-120 | flags | server-sent-request | — | agree |
draft/violations/tran-068-sse-media-type-mixed-case | 2026-07-28 | pass-with-warnings | TRAN-068 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-068-sse-without-accel-buffering | 2026-07-28 | pass-with-warnings | TRAN-068 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-070-message-after-stream-close | 2026-07-28 | fail | TRAN-070 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-071-protocol-version-header-missing | 2026-07-28 | fail | CACH-001, TRAN-071, wire-schema | flags | cacheable-without-ttl, protocol-version-header-missing | — | agree |
draft/violations/tran-072-mismatch-rejected-without-id | 2026-07-28 | fail | BASE-052, TRAN-072, wire-schema | flags | protocol-version-header-disagrees, response-unmatched | — | agree |
draft/violations/tran-072-protocol-version-header-mismatched | 2026-07-28 | fail | TRAN-072 | flags | protocol-version-header-disagrees, server-rejected-header-mismatch | — | agree |
draft/violations/tran-072-unsupported-body-version-header-mismatch | 2026-07-28 | fail | TRAN-072 | flags | protocol-version-header-disagrees, server-rejected-header-mismatch | — | agree |
draft/violations/tran-072-unsupported-body-version-refused-as-unsupported | 2026-07-28 | fail | TRAN-072 | flags | protocol-version-header-disagrees | — | agree |
draft/violations/tran-073-header-mismatch-not-rejected | 2026-07-28 | fail | CACH-001, TRAN-072, TRAN-073, wire-schema | flags | cacheable-without-ttl, protocol-version-header-disagrees | — | agree |
draft/violations/tran-073-mismatch-refused-without-id | 2026-07-28 | fail | BASE-052, TRAN-072, TRAN-073, wire-schema | flags | protocol-version-header-disagrees, response-unmatched | — | agree |
draft/violations/tran-074-unsupported-version-accepted | 2026-07-28 | fail | CACH-001, TOOL-019, TRAN-074, VERS-001, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/tran-074-unsupported-version-without-400 | 2026-07-28 | fail | TRAN-074 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-074-unsupported-version-without-supported-list | 2026-07-28 | fail | TRAN-074, VERS-001, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/tran-075-method-not-found-not-404 | 2026-07-28 | fail | TRAN-075 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-077-mcp-name-unencoded | 2026-07-28 | fail | CACH-001, TRAN-077, TRAN-086, TRAN-087, wire-schema | flags | cacheable-without-ttl | — | agree |
draft/violations/tran-077-param-header-value-rejected | 2026-07-28 | fail | TRAN-077, TRAN-086, TRAN-087 | flags | server-rejected-header-mismatch | — | agree |
draft/violations/tran-079-missing-param-header-rejected | 2026-07-28 | fail | TRAN-079, TRAN-130 | flags | param-header-missing, server-rejected-header-mismatch | — | agree |
draft/violations/tran-079-param-header-value-not-mirrored | 2026-07-28 | fail | TRAN-079 | flags | param-header-disagrees, server-rejected-header-mismatch | — | agree |
draft/violations/tran-079-x-mcp-header-not-mirrored | 2026-07-28 | fail | TRAN-079, TRAN-130, TRAN-136 | flags | param-header-missing | — | agree |
draft/violations/tran-080-x-mcp-header-name-invalid | 2026-07-28 | fail | TOOL-033, TRAN-080 | flags | x-mcp-header-repeated | — | agree |
draft/violations/tran-082-invalid-tool-excluded-valid-called | 2026-07-28 | fail | TOOL-045, TRAN-082, TRAN-137 | flags | x-mcp-header-chain | — | agree |
draft/violations/tran-082-x-mcp-header-under-any-of | 2026-07-28 | fail | TOOL-045, TRAN-082, TRAN-137 | flags | x-mcp-header-chain | method-name-header-missing, protocol-version-header-missing | agree |
draft/violations/tran-083-invalid-tool-called | 2026-07-28 | fail | TOOL-035, TOOL-045, TOOL-046, TRAN-082, TRAN-083, TRAN-084, TRAN-137 | flags | x-mcp-header-chain | — | agree |
draft/violations/tran-089-sentinel-markers-miscased | 2026-07-28 | fail | TRAN-089 | flags | param-header-disagrees, server-rejected-header-mismatch | — | agree |
draft/violations/tran-092-sentinel-pattern-unencoded | 2026-07-28 | fail | CACH-001, TRAN-092, wire-schema | flags | cacheable-without-ttl, name-header-disagrees | — | agree |
draft/violations/tran-096-invalid-param-header-accepted | 2026-07-28 | fail | TRAN-077, TRAN-086, TRAN-087, TRAN-096 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-097-header-body-mismatch-accepted | 2026-07-28 | fail | TRAN-079, TRAN-097, TRAN-100, TRAN-131 | flags | param-header-disagrees | — | agree |
draft/violations/tran-097-integer-header-different-number | 2026-07-28 | fail | TRAN-079, TRAN-097, TRAN-100, TRAN-131 | flags | param-header-disagrees | — | agree |
draft/violations/tran-097-mismatch-after-concurrent-posts | 2026-07-28 | fail | TRAN-058, TRAN-097, TRAN-100, TRAN-131, TRAN-141 | flags | name-header-disagrees | method-name-header-missing, protocol-version-header-missing | agree |
draft/violations/tran-098-header-mismatch-without-400 | 2026-07-28 | fail | TRAN-098, TRAN-102 | flags | server-rejected-header-mismatch | — | divergent |
draft/violations/tran-123-cancellation-without-request-id | 2026-07-28 | fail | CANC-005, TRAN-123, wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/tran-124-message-after-cancel-notification | 2026-07-28 | fail | TRAN-124 | silent | — | — | beyond mcpsnoop |
draft/violations/tran-132-null-parameter-header-sent | 2026-07-28 | fail | TRAN-132 | flags | param-header-without-value | — | agree |
draft/violations/tran-133-omitted-null-header-rejected | 2026-07-28 | fail | TRAN-133 | flags | server-rejected-header-mismatch | — | divergent |
draft/violations/tran-134-absent-parameter-header-sent | 2026-07-28 | fail | TRAN-134 | flags | param-header-without-value | — | agree |
draft/violations/tran-135-omitted-absent-header-rejected | 2026-07-28 | fail | TRAN-135 | flags | server-rejected-header-mismatch | — | divergent |
draft/violations/tran-136-missing-param-header-accepted | 2026-07-28 | fail | TRAN-079, TRAN-130, TRAN-136 | flags | param-header-missing | — | agree |
draft/violations/tran-137-x-mcp-header-under-items | 2026-07-28 | fail | TOOL-045, TRAN-082, TRAN-137 | flags | x-mcp-header-chain | method-name-header-missing, protocol-version-header-missing | agree |
draft/violations/tran-141-mcp-name-header-missing | 2026-07-28 | fail | TRAN-058, TRAN-141 | flags | method-name-header-missing | — | agree |
draft/violations/vers-002-retry-with-unsupported-version | 2026-07-28 | pass-with-warnings | VERS-002 | silent | — | — | beyond mcpsnoop |
draft/violations/vers-004-extension-identifier-without-prefix | 2026-07-28 | fail | VERS-004 | silent | — | — | beyond mcpsnoop |
draft/violations/vers-008-initialize-error-without-versions | 2026-07-28 | fail | BASE-030, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, VERS-008 | silent | — | — | divergent |
draft/violations/wire-schema-cache-scope-not-in-enum | 2026-07-28 | fail | wire-schema | flags | cache-scope-value | — | agree |
draft/violations/wire-schema-content-block-unknown-type | 2026-07-28 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/wire-schema-resource-missing-uri | 2026-07-28 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
draft/violations/wire-schema-tool-image-data-not-base64 | 2026-07-28 | fail | wire-schema | silent | — | — | beyond mcpsnoop |
draft/captured/official-suite-2026-07-28-scenarios | 2026-07-28 | pass-with-warnings | BASE-037 | silent | — | — | beyond mcpsnoop |
draft/captured/official-suite-2026-07-28-stateless | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/captured/probe-2026-07-28-http | 2026-07-28 | fail | BASE-030, BASE-033, COMP-006, MRTR-002, PAGE-006, PROM-011, RES-011, TOOL-016, TRAN-071, TRAN-072, TRAN-079, TRAN-130, wire-schema | flags | param-header-missing, protocol-version-header-disagrees, request-meta-missing, server-rejected-header-mismatch | — | agree |
draft/captured/reference-host-2026-07-28-http | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/captured/reference-host-2026-07-28-stdio | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/captured/sdk-go-2026-07-28 | 2026-07-28 | fail | BASE-034, ELIC-059, MRTR-012, MRTR-013, TRAN-068 | flags | input-request-undeclared | — | agree |
draft/captured/sdk-python-2026-07-28 | 2026-07-28 | pass | — | silent | — | — | both clean |
draft/captured/sdk-rust-2026-07-28 | 2026-07-28 | pass-with-warnings | BASE-037 | silent | — | — | beyond mcpsnoop |
draft/captured/sdk-typescript-v2-2026-07-28 | 2026-07-28 | pass | — | silent | — | — | both clean |