mcp_trace_validator/checks/
inventory.rs1use super::{Check, base, lifecycle, negotiation, prompts, resources, tools, transport, utilities};
12
13macro_rules! check {
17 ($id:literal, $run:path) => {
18 Check { id: $id, run: $run }
19 };
20}
21
22const SHIPPED: &[Check] = &[
24 check!("base.request-id-type", base::request_id_type),
25 check!("base.request-id-not-null", base::request_id_not_null),
26 check!("base.request-id-unique", base::request_id_unique),
27 check!("base.result-id-matches", base::result_id_matches),
28 check!("base.notification-no-id", base::notification_no_id),
29 check!("base.error-shape", base::error_shape),
30 check!("base.error-code-integer", base::error_code_integer),
31 check!("base.jsonrpc-version", base::jsonrpc_version),
32 check!("base.error-id-matches", base::error_id_matches),
33 check!(
34 "lifecycle.first-interaction-initialize",
35 lifecycle::first_interaction_initialize
36 ),
37 check!("lifecycle.initialize-params", lifecycle::initialize_params),
38 check!(
39 "lifecycle.initialized-notification",
40 lifecycle::initialized_notification
41 ),
42 check!(
43 "lifecycle.client-requests-before-init-response",
44 lifecycle::client_requests_before_init_response
45 ),
46 check!(
47 "lifecycle.server-requests-before-initialized",
48 lifecycle::server_requests_before_initialized
49 ),
50 check!(
51 "lifecycle.initialize-result-version",
52 lifecycle::initialize_result_version
53 ),
54 check!(
55 "lifecycle.initialize-result-shape",
56 lifecycle::initialize_result_shape
57 ),
58 check!("base.meta-key-format", base::meta_key_format),
59 check!("base.result-field", base::result_field),
60 check!(
61 "lifecycle.initialize-protocol-version",
62 lifecycle::initialize_protocol_version
63 ),
64 check!(
65 "lifecycle.negotiated-capabilities-only",
66 negotiation::negotiated_capabilities_only
67 ),
68 check!(
69 "transport.stdio-server-output-valid",
70 transport::stdio_server_output_valid
71 ),
72 check!(
73 "transport.stdio-client-input-valid",
74 transport::stdio_client_input_valid
75 ),
76 check!(
77 "transport.session-id-visible-ascii",
78 transport::session_id_visible_ascii
79 ),
80 check!("transport.session-id-echoed", transport::session_id_echoed),
81 check!(
82 "transport.protocol-version-header",
83 transport::protocol_version_header
84 ),
85 check!(
86 "transport.protocol-version-negotiated",
87 transport::protocol_version_negotiated
88 ),
89 check!(
90 "transport.http-post-single-message",
91 transport::http_post_single_message
92 ),
93 check!(
94 "transport.client-post-accept-header",
95 transport::client_post_accept_header
96 ),
97 check!(
98 "transport.client-get-accept-header",
99 transport::client_get_accept_header
100 ),
101 check!(
102 "transport.client-messages-use-post",
103 transport::client_messages_use_post
104 ),
105 check!(
106 "transport.success-content-type",
107 transport::success_content_type
108 ),
109 check!("tools.capability-declared", tools::capability_declared),
110 check!("tools.input-schema-object", tools::input_schema_object),
111 check!("tools.name-length", tools::name_length),
112 check!("tools.name-charset", tools::name_charset),
113 check!("tools.name-unique", tools::name_unique),
114 check!(
115 "tools.embedded-resource-capability",
116 tools::embedded_resource_capability
117 ),
118 check!(
119 "tools.structured-content-text",
120 tools::structured_content_text
121 ),
122 check!(
123 "tools.output-schema-structured-result",
124 tools::output_schema_structured_result
125 ),
126 check!(
127 "resources.capability-declared",
128 resources::capability_declared
129 ),
130 check!(
131 "resources.uri-scheme-rfc3986",
132 resources::uri_scheme_rfc3986
133 ),
134 check!("resources.blob-base64", resources::blob_base64),
135 check!("prompts.capability-declared", prompts::capability_declared),
136 check!(
137 "prompts.image-content-encoding",
138 prompts::image_content_encoding
139 ),
140 check!(
141 "prompts.audio-content-encoding",
142 prompts::audio_content_encoding
143 ),
144 check!(
145 "prompts.embedded-resource-shape",
146 prompts::embedded_resource_shape
147 ),
148 check!("prompts.arguments-validated", prompts::arguments_validated),
149 check!(
150 "logging.capability-declared",
151 utilities::logging_capability_declared
152 ),
153 check!(
154 "completion.capability-declared",
155 utilities::completion_capability_declared
156 ),
157 check!("pagination.cursor-opacity", utilities::cursor_opacity),
158 check!(
159 "pagination.invalid-cursor-rejected",
160 utilities::invalid_cursor_rejected
161 ),
162];
163
164const fn concatenated<const N: usize>(first: &[Check], second: &[Check]) -> [Check; N] {
168 let mut out = [first[0]; N];
169 let mut index = 0;
170 while index < first.len() {
171 out[index] = first[index];
172 index += 1;
173 }
174 let mut offset = 0;
175 while offset < second.len() {
176 out[first.len() + offset] = second[offset];
177 offset += 1;
178 }
179 out
180}
181
182static EVERY: [Check; SHIPPED.len() + draft_rows::DRAFT.len()] =
184 concatenated(SHIPPED, draft_rows::DRAFT);
185
186pub static ALL: &[Check] = &EVERY;
188#[must_use]
190pub fn find(id: &str) -> Option<&'static Check> {
191 ALL.iter().find(|check| check.id == id)
192}
193
194mod draft_rows;
195
196#[cfg(test)]
197mod planned;
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use std::collections::HashSet;
203
204 #[test]
205 fn check_ids_are_unique() {
206 let mut seen = HashSet::new();
207 for check in ALL {
208 assert!(seen.insert(check.id), "duplicate check id {}", check.id);
209 }
210 }
211}