Skip to main content

mcp_trace_validator/checks/
draft.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2026 Tom F. (https://github.com/tomtom215)
3
4//! Checks for the `2026-07-28` revision.
5//!
6//! Referenced by the `2026-07-28` registry entries and, like every check, run
7//! against whatever registry the caller projects — a check is a pure function of
8//! a trace, not of a revision. They live together here because they arrived
9//! together with that revision's first extracted areas, and because splitting
10//! them out keeps the `2025-11-25` modules reviewable in isolation.
11
12use mcp_conformance_core::trace::{Direction, EventBody};
13
14use crate::context::TraceContext;
15
16pub(super) mod caching;
17pub(super) mod capabilities;
18pub(super) mod discovery;
19pub(super) mod envelope;
20pub(super) mod features;
21pub(super) mod logging;
22pub(super) mod meta;
23pub(super) mod mrtr;
24pub(super) mod subscriptions;
25pub(super) mod transport;
26pub(super) mod versioning;
27
28#[cfg(test)]
29mod testkit;
30#[cfg(test)]
31mod tests;
32
33/// The HTTP status of the response that carried the message at `seq`.
34///
35/// Several clauses pair a JSON-RPC error code with an HTTP status ("`400 Bad
36/// Request` and `-32020`"), so a check needs the status the message travelled
37/// under. The capture format puts the response's `http` event *before* the
38/// message(s) it framed — see `mcp_everything_server::tap::record_response`,
39/// which records the status and then the body — so the search runs backwards
40/// from the message and stops at the first server-sent status. One `http` event
41/// can therefore answer for several messages, which is exactly right for an SSE
42/// stream: every frame rode the same response.
43///
44/// A stdio trace carries no status at all, so callers must treat `None` as "no
45/// evidence" rather than as a failure.
46fn http_status_for(context: &TraceContext<'_>, seq: u64) -> Option<(u64, u16)> {
47    context
48        .events()
49        .iter()
50        .rev()
51        .filter(|event| event.seq < seq && event.direction == Direction::ServerToClient)
52        .find_map(|event| match &event.body {
53            EventBody::Http {
54                status: Some(status),
55                ..
56            } => Some((event.seq, *status)),
57            _ => None,
58        })
59}