@@ -96,6 +96,61 @@ class Requirement:
9696 ),
9797 ),
9898 # ═══════════════════════════════════════════════════════════════════════════
99+ # Cancellation
100+ # ═══════════════════════════════════════════════════════════════════════════
101+ "cancellation:in-flight" : Requirement (
102+ source = f"{ SPEC_BASE_URL } /basic/utilities/cancellation#behavior-requirements" ,
103+ behavior = (
104+ "A cancellation notification for an in-flight request stops the server-side handler, and the "
105+ "caller's pending request fails with an error response."
106+ ),
107+ divergence = Divergence (
108+ note = (
109+ "The spec says receivers of a cancellation SHOULD NOT send a response for the cancelled "
110+ "request; the server sends an error response (code 0, 'Request cancelled'), which is what "
111+ "unblocks the SDK client's pending call."
112+ ),
113+ ),
114+ ),
115+ "cancellation:server-survives" : Requirement (
116+ source = f"{ SPEC_BASE_URL } /basic/utilities/cancellation#behavior-requirements" ,
117+ behavior = "The session continues to serve new requests after an earlier request was cancelled." ,
118+ ),
119+ "cancellation:unknown-request" : Requirement (
120+ source = f"{ SPEC_BASE_URL } /basic/utilities/cancellation#behavior-requirements" ,
121+ behavior = (
122+ "A cancellation notification referencing an unknown or already-completed request is ignored without error."
123+ ),
124+ ),
125+ # ═══════════════════════════════════════════════════════════════════════════
126+ # Progress
127+ # ═══════════════════════════════════════════════════════════════════════════
128+ "progress:server-to-client" : Requirement (
129+ source = f"{ SPEC_BASE_URL } /basic/utilities/progress#progress-flow" ,
130+ behavior = (
131+ "Progress notifications emitted by a handler during a request are delivered to the caller's "
132+ "progress callback, in order, with their progress, total, and message."
133+ ),
134+ ),
135+ "progress:token-propagation" : Requirement (
136+ source = f"{ SPEC_BASE_URL } /basic/utilities/progress#progress-flow" ,
137+ behavior = (
138+ "Supplying a progress callback attaches a progress token to the outgoing request, which the "
139+ "server-side handler can observe in its request metadata."
140+ ),
141+ ),
142+ "progress:no-token" : Requirement (
143+ source = f"{ SPEC_BASE_URL } /basic/utilities/progress#progress-flow" ,
144+ behavior = (
145+ "Without a progress callback no token is attached, and a handler that reports progress anyway "
146+ "sends nothing."
147+ ),
148+ ),
149+ "progress:client-to-server" : Requirement (
150+ source = f"{ SPEC_BASE_URL } /basic/utilities/progress#progress-flow" ,
151+ behavior = "A progress notification sent by the client is delivered to the server's progress handler." ,
152+ ),
153+ # ═══════════════════════════════════════════════════════════════════════════
99154 # Ping
100155 # ═══════════════════════════════════════════════════════════════════════════
101156 "ping:client-to-server" : Requirement (
@@ -229,6 +284,21 @@ class Requirement:
229284 behavior = "resources/read for an unknown URI returns a JSON-RPC error; the spec reserves -32002 for it." ,
230285 ),
231286 # ═══════════════════════════════════════════════════════════════════════════
287+ # Notifications: list_changed (server → client)
288+ # ═══════════════════════════════════════════════════════════════════════════
289+ "notifications:tools:list-changed" : Requirement (
290+ source = f"{ SPEC_BASE_URL } /server/tools#list-changed-notification" ,
291+ behavior = "A tools/list_changed notification sent by the server reaches the client's message handler." ,
292+ ),
293+ "notifications:resources:list-changed" : Requirement (
294+ source = f"{ SPEC_BASE_URL } /server/resources#list-changed-notification" ,
295+ behavior = "A resources/list_changed notification sent by the server reaches the client's message handler." ,
296+ ),
297+ "notifications:prompts:list-changed" : Requirement (
298+ source = f"{ SPEC_BASE_URL } /server/prompts#list-changed-notification" ,
299+ behavior = "A prompts/list_changed notification sent by the server reaches the client's message handler." ,
300+ ),
301+ # ═══════════════════════════════════════════════════════════════════════════
232302 # Prompts
233303 # ═══════════════════════════════════════════════════════════════════════════
234304 "prompts:list:basic" : Requirement (
@@ -248,6 +318,88 @@ class Requirement:
248318 behavior = "prompts/get for an unknown prompt name returns a JSON-RPC error." ,
249319 ),
250320 # ═══════════════════════════════════════════════════════════════════════════
321+ # Sampling (server → client)
322+ # ═══════════════════════════════════════════════════════════════════════════
323+ "sampling:create-message:round-trip" : Requirement (
324+ source = f"{ SPEC_BASE_URL } /client/sampling#creating-messages" ,
325+ behavior = (
326+ "A sampling/createMessage request from a server handler is answered by the client's sampling "
327+ "callback, and the callback's result (role, content, model, stopReason) is returned to the handler."
328+ ),
329+ ),
330+ "sampling:create-message:params" : Requirement (
331+ source = f"{ SPEC_BASE_URL } /client/sampling#creating-messages" ,
332+ behavior = (
333+ "The sampling parameters supplied by the server (messages, maxTokens, systemPrompt, "
334+ "modelPreferences, temperature, stopSequences) reach the client callback intact."
335+ ),
336+ ),
337+ "sampling:create-message:image-content" : Requirement (
338+ source = f"{ SPEC_BASE_URL } /client/sampling#message-content" ,
339+ behavior = "Sampling messages can carry image content: base64 data with a mimeType." ,
340+ ),
341+ "sampling:create-message:client-error" : Requirement (
342+ source = f"{ SPEC_BASE_URL } /client/sampling#error-handling" ,
343+ behavior = "A sampling callback that returns an error is surfaced to the requesting handler as an MCPError." ,
344+ ),
345+ "sampling:create-message:not-supported" : Requirement (
346+ source = f"{ SPEC_BASE_URL } /client/sampling#capabilities" ,
347+ behavior = (
348+ "A sampling request to a client that did not declare the sampling capability fails with an "
349+ "error rather than hanging or being silently dropped."
350+ ),
351+ ),
352+ # ═══════════════════════════════════════════════════════════════════════════
353+ # Elicitation (server → client)
354+ # ═══════════════════════════════════════════════════════════════════════════
355+ "elicitation:form:accept" : Requirement (
356+ source = f"{ SPEC_BASE_URL } /client/elicitation#form-mode-elicitation" ,
357+ behavior = (
358+ "A form-mode elicitation answered with action 'accept' returns the user's content to the "
359+ "requesting handler, validated against the requested schema."
360+ ),
361+ ),
362+ "elicitation:form:decline" : Requirement (
363+ source = f"{ SPEC_BASE_URL } /client/elicitation#response-actions" ,
364+ behavior = "A form-mode elicitation answered with action 'decline' returns no content to the handler." ,
365+ ),
366+ "elicitation:form:cancel" : Requirement (
367+ source = f"{ SPEC_BASE_URL } /client/elicitation#response-actions" ,
368+ behavior = "A form-mode elicitation answered with action 'cancel' returns no content to the handler." ,
369+ ),
370+ "elicitation:form:not-supported" : Requirement (
371+ source = f"{ SPEC_BASE_URL } /client/elicitation#capabilities" ,
372+ behavior = (
373+ "An elicitation request to a client that did not declare the elicitation capability fails with "
374+ "an error rather than hanging or being silently dropped."
375+ ),
376+ ),
377+ # ═══════════════════════════════════════════════════════════════════════════
378+ # Roots (server → client)
379+ # ═══════════════════════════════════════════════════════════════════════════
380+ "roots:list:round-trip" : Requirement (
381+ source = f"{ SPEC_BASE_URL } /client/roots#listing-roots" ,
382+ behavior = (
383+ "A roots/list request from a server handler is answered by the client's roots callback, and "
384+ "the returned roots (uri, name) reach the handler."
385+ ),
386+ ),
387+ "roots:list:empty" : Requirement (
388+ source = f"{ SPEC_BASE_URL } /client/roots#listing-roots" ,
389+ behavior = "An empty roots list is a valid response and reaches the handler as such." ,
390+ ),
391+ "roots:list:not-supported" : Requirement (
392+ source = f"{ SPEC_BASE_URL } /client/roots#capabilities" ,
393+ behavior = (
394+ "A roots/list request to a client that did not declare the roots capability fails with an "
395+ "error rather than hanging or being silently dropped."
396+ ),
397+ ),
398+ "roots:list-changed" : Requirement (
399+ source = f"{ SPEC_BASE_URL } /client/roots#root-list-changes" ,
400+ behavior = "A roots/list_changed notification sent by the client is delivered to the server's handler." ,
401+ ),
402+ # ═══════════════════════════════════════════════════════════════════════════
251403 # MCPServer behavioural guarantees (not spec-mandated)
252404 # ═══════════════════════════════════════════════════════════════════════════
253405 "mcpserver:tools:output-schema:model" : Requirement (
0 commit comments