You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rename ExperimentalProtocolVersion to ProtocolVersion + sync draft version to 2026-07-28
- Drop ExperimentalProtocolVersion from McpClientOptions/McpServerOptions and use
ProtocolVersion == McpSessionHandler.DraftProtocolVersion as the draft predicate.
- McpHttpHeaders.DraftProtocolVersion and McpSessionHandler.DraftProtocolVersion are
now `2026-07-28` (matches the published spec) instead of `DRAFT-2026-v1`.
- Server always advertises draft via SupportedProtocolVersions; ConfigureDiscover no
longer takes an opt-in flag.
- Drop _serverHasExperimental machinery from DraftConnectionTests; the test class
now relies on the unconditional draft support.
- Skip Mrtr_MixedExceptionAndAwaitStyle(experimentalClient: True) over Streamable
HTTP; the await-style path needs session affinity and draft HTTP is sessionless.
Stdio coverage stays in DraftProtocolBackcompatTests.
- Sweep the remaining DRAFT-2026-v1 / 2026-06-XX literals across docs and tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: docs/concepts/elicitation/elicitation.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -172,10 +172,10 @@ Here's an example implementation of how a console application might handle elici
172
172
173
173
### Multi Round-Trip Requests (MRTR)
174
174
175
-
[MRTR](xref:mrtr) is the SEP-2322 mechanism for server-driven input requests, finalized in protocol revision `DRAFT-2026-v1`. Under the draft protocol, the server-to-client `elicitation/create` request method is removed; the recommended way to ask the user for input from a server handler is to throw <xref:ModelContextProtocol.Protocol.InputRequiredException> and let the SDK emit an <xref:ModelContextProtocol.Protocol.InputRequiredResult> on the wire.
175
+
[MRTR](xref:mrtr) is the SEP-2322 mechanism for server-driven input requests, finalized in protocol revision `2026-07-28`. Under the draft protocol, the server-to-client `elicitation/create` request method is removed; the recommended way to ask the user for input from a server handler is to throw <xref:ModelContextProtocol.Protocol.InputRequiredException> and let the SDK emit an <xref:ModelContextProtocol.Protocol.InputRequiredResult> on the wire.
176
176
177
177
> [!IMPORTANT]
178
-
> `ElicitAsync` throws `InvalidOperationException("Elicitation is not supported in stateless mode.")` whenever the server is running stateless — which includes every Streamable HTTP server under `DRAFT-2026-v1` once that revision is forced to stateless-only in a future PR. Stdio servers and current-protocol stateful Streamable HTTP servers continue to work via the legacy server-to-client `elicitation/create` request flow. For code that needs to run on stateless servers — including all `DRAFT-2026-v1` Streamable HTTP servers going forward — throw `InputRequiredException` from your handler instead. It works under both protocols and both session modes.
178
+
> `ElicitAsync` throws `InvalidOperationException("Elicitation is not supported in stateless mode.")` whenever the server is running stateless — which includes every Streamable HTTP server under `2026-07-28` once that revision is forced to stateless-only in a future PR. Stdio servers and current-protocol stateful Streamable HTTP servers continue to work via the legacy server-to-client `elicitation/create` request flow. For code that needs to run on stateless servers — including all `2026-07-28` Streamable HTTP servers going forward — throw `InputRequiredException` from your handler instead. It works under both protocols and both session modes.
179
179
180
180
For example:
181
181
@@ -196,7 +196,7 @@ public static string ElicitWithMrtr(
196
196
197
197
if (!server.IsMrtrSupported)
198
198
{
199
-
return"This tool requires MRTR support (DRAFT-2026-v1, or a stateful current-protocol session).";
199
+
return"This tool requires MRTR support (2026-07-28, or a stateful current-protocol session).";
Copy file name to clipboardExpand all lines: docs/concepts/mrtr/mrtr.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ uid: mrtr
9
9
10
10
<!-- mlc-disable-next-line -->
11
11
> [!WARNING]
12
-
> MRTR is part of the **`DRAFT-2026-v1`** revision of the MCP specification ([SEP-2322](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2322)). The wire format and API surface may change before the revision is ratified. See the [Experimental APIs](../../experimental.md) documentation for details on working with experimental APIs.
12
+
> MRTR is part of the **`2026-07-28`** revision of the MCP specification ([SEP-2322](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2322)). The wire format and API surface may change before the revision is ratified. See the [Experimental APIs](../../experimental.md) documentation for details on working with experimental APIs.
13
13
14
14
Multi Round-Trip Requests (MRTR) let a server tool request input from the client — such as [elicitation](xref:elicitation), [sampling](xref:sampling), or [roots](xref:roots) — as part of a single tool call, without requiring a separate server-to-client JSON-RPC request for each interaction. Instead of returning a final result, the server returns an **incomplete result** containing one or more input requests. The client fulfills those requests and retries the original tool call with the responses attached.
15
15
@@ -33,13 +33,13 @@ MRTR is useful when:
33
33
34
34
## Opting in
35
35
36
-
MRTR activates when both peers negotiate protocol revision **`DRAFT-2026-v1`** during `initialize`. The C# SDK opts in by listing `DRAFT-2026-v1` as a supported protocol version on the client; servers automatically accept it when offered. No experimental flags are required.
36
+
MRTR activates when both peers negotiate protocol revision **`2026-07-28`** during `initialize`. The C# SDK opts in by listing `2026-07-28` as a supported protocol version on the client; servers automatically accept it when offered. No experimental flags are required.
37
37
38
38
```csharp
39
39
// Client
40
40
varclientOptions=newMcpClientOptions
41
41
{
42
-
ProtocolVersion="DRAFT-2026-v1",
42
+
ProtocolVersion="2026-07-28",
43
43
Handlers=newMcpClientHandlers
44
44
{
45
45
ElicitationHandler=HandleElicitationAsync,
@@ -48,7 +48,7 @@ var clientOptions = new McpClientOptions
48
48
};
49
49
```
50
50
51
-
Under `DRAFT-2026-v1`, MRTR is the recommended way to obtain client input from a server handler. The spec removes the legacy server-to-client `elicitation/create`, `sampling/createMessage`, and `roots/list` request methods, so any code that needs to work on a `DRAFT-2026-v1` Streamable HTTP server (which will be stateless-only in a future revision) must use `InputRequiredException` rather than <xref:ModelContextProtocol.Server.McpServer.ElicitAsync*>, <xref:ModelContextProtocol.Server.McpServer.SampleAsync*>, or <xref:ModelContextProtocol.Server.McpServer.RequestRootsAsync*>. The legacy methods still work on stateful sessions — that's how stdio servers keep working under draft today — but they throw `InvalidOperationException("X is not supported in stateless mode.")` on any stateless session, current or draft.
51
+
Under `2026-07-28`, MRTR is the recommended way to obtain client input from a server handler. The spec removes the legacy server-to-client `elicitation/create`, `sampling/createMessage`, and `roots/list` request methods, so any code that needs to work on a `2026-07-28` Streamable HTTP server (which will be stateless-only in a future revision) must use `InputRequiredException` rather than <xref:ModelContextProtocol.Server.McpServer.ElicitAsync*>, <xref:ModelContextProtocol.Server.McpServer.SampleAsync*>, or <xref:ModelContextProtocol.Server.McpServer.RequestRootsAsync*>. The legacy methods still work on stateful sessions — that's how stdio servers keep working under draft today — but they throw `InvalidOperationException("X is not supported in stateless mode.")` on any stateless session, current or draft.
52
52
53
53
Under the current protocol revision (`2025-06-18` and earlier), `InputRequiredException` is still supported in stateful sessions via a backward-compatibility resolver — see [Compatibility](#compatibility) below.
54
54
@@ -60,7 +60,7 @@ A tool participates in MRTR by throwing <xref:ModelContextProtocol.Protocol.Inpu
60
60
61
61
Tools should check <xref:ModelContextProtocol.Server.McpServer.IsMrtrSupported> before throwing `InputRequiredException`. It returns `true` when either:
62
62
63
-
- The negotiated protocol revision is `DRAFT-2026-v1` (MRTR is native), or
63
+
- The negotiated protocol revision is `2026-07-28` (MRTR is native), or
64
64
- The session is stateful under the current protocol (the SDK can resolve input requests via legacy JSON-RPC and retry the handler).
65
65
66
66
```csharp
@@ -71,7 +71,7 @@ public static string MyTool(
71
71
{
72
72
if (!server.IsMrtrSupported)
73
73
{
74
-
return"This tool requires a client that negotiates DRAFT-2026-v1, "
74
+
return"This tool requires a client that negotiates 2026-07-28, "
75
75
+"or a stateful current-protocol session.";
76
76
}
77
77
@@ -258,7 +258,7 @@ When MRTR is not supported, you can provide domain-specific guidance:
258
258
if (!server.IsMrtrSupported)
259
259
{
260
260
return"This tool requires interactive input. To use it:\n"
261
-
+"1. Connect with a client that negotiates MCP protocol revision DRAFT-2026-v1, or\n"
261
+
+"1. Connect with a client that negotiates MCP protocol revision 2026-07-28, or\n"
262
262
+"2. Use a stateful current-protocol session so the server can resolve the input requests for you.\n"
@@ -270,22 +270,22 @@ The SDK supports `InputRequiredException` across two protocol revisions and two
270
270
271
271
| Negotiated protocol | Session mode | Behavior |
272
272
|---|---|---|
273
-
|`DRAFT-2026-v1`| Stateful | Native MRTR — `InputRequiredResult` is serialized directly to the wire. |
274
-
|`DRAFT-2026-v1`| Stateless | Native MRTR — `InputRequiredResult` is serialized directly to the wire. No server-side handler state needed. |
273
+
|`2026-07-28`| Stateful | Native MRTR — `InputRequiredResult` is serialized directly to the wire. |
274
+
|`2026-07-28`| Stateless | Native MRTR — `InputRequiredResult` is serialized directly to the wire. No server-side handler state needed. |
275
275
| Current (`2025-06-18` and earlier) | Stateful | Backward-compatibility resolver — the SDK sends standard `elicitation/create` / `sampling/createMessage` / `roots/list` JSON-RPC requests to the client, collects the responses, and retries the handler with `inputResponses` populated. Up to 10 retry rounds. |
276
276
| Current (`2025-06-18` and earlier) | Stateless |**Not supported** — `InputRequiredException` raises an `McpException`. The client doesn't speak MRTR, and the server can't resolve input requests via JSON-RPC without a persistent session. |
277
277
278
278
> [!NOTE]
279
-
> The backcompat resolver is intentionally limited to 10 retry rounds. Tools that need more rounds should require `DRAFT-2026-v1` (check `IsMrtrSupported`).
279
+
> The backcompat resolver is intentionally limited to 10 retry rounds. Tools that need more rounds should require `2026-07-28` (check `IsMrtrSupported`).
`ElicitAsync` / `SampleAsync` / `RequestRootsAsync` issue a JSON-RPC request to the client and wait for the response on the same session. Stateless servers don't have a persistent session to wait on, so the SDK fails fast with `InvalidOperationException("X is not supported in stateless mode.")` (the check is `McpServer.ClientCapabilities is null`, which is the SDK's proxy for stateless).
284
284
285
-
Under the current protocol revision (`2025-06-18` and earlier), stdio and stateful Streamable HTTP keep `ClientCapabilities` populated, so the legacy methods work normally and remain the recommended way to do one-shot client interactions. Under `DRAFT-2026-v1`, the spec removes those request methods from Streamable HTTP entirely; the SDK still allows the legacy methods on draft stdio sessions because stdio is implicitly single-process / stateful and the client handler is wired up regardless of negotiated revision. `InputRequiredException` is the way to write tools that work on every supported configuration.
285
+
Under the current protocol revision (`2025-06-18` and earlier), stdio and stateful Streamable HTTP keep `ClientCapabilities` populated, so the legacy methods work normally and remain the recommended way to do one-shot client interactions. Under `2026-07-28`, the spec removes those request methods from Streamable HTTP entirely; the SDK still allows the legacy methods on draft stdio sessions because stdio is implicitly single-process / stateful and the client handler is wired up regardless of negotiated revision. `InputRequiredException` is the way to write tools that work on every supported configuration.
286
286
287
287
### Future direction
288
288
289
-
The `DRAFT-2026-v1` revision is moving toward a stateless-only model: `Mcp-Session-Id` is being removed, and Streamable HTTP servers will run statelessly by default under the draft revision. When that lands, the `Stateful` row for `DRAFT-2026-v1` in the compatibility matrix above collapses into the `Stateless` row (Streamable HTTP under draft becomes stateless-only), and `InputRequiredException` becomes uniformly required for non-stdio servers. The current-protocol resolver path will remain for backward compatibility with older clients and stateful servers.
289
+
The `2026-07-28` revision is moving toward a stateless-only model: `Mcp-Session-Id` is being removed, and Streamable HTTP servers will run statelessly by default under the draft revision. When that lands, the `Stateful` row for `2026-07-28` in the compatibility matrix above collapses into the `Stateless` row (Streamable HTTP under draft becomes stateless-only), and `InputRequiredException` becomes uniformly required for non-stdio servers. The current-protocol resolver path will remain for backward compatibility with older clients and stateful servers.
[MRTR](xref:mrtr) is the SEP-2322 mechanism for server-driven input requests, finalized in protocol revision `DRAFT-2026-v1`. Under the draft protocol, the server-to-client `roots/list` request method is removed; the recommended way to ask the client for its roots from a server handler is to throw <xref:ModelContextProtocol.Protocol.InputRequiredException> and let the SDK emit an <xref:ModelContextProtocol.Protocol.InputRequiredResult> on the wire.
109
+
[MRTR](xref:mrtr) is the SEP-2322 mechanism for server-driven input requests, finalized in protocol revision `2026-07-28`. Under the draft protocol, the server-to-client `roots/list` request method is removed; the recommended way to ask the client for its roots from a server handler is to throw <xref:ModelContextProtocol.Protocol.InputRequiredException> and let the SDK emit an <xref:ModelContextProtocol.Protocol.InputRequiredResult> on the wire.
110
110
111
111
> [!IMPORTANT]
112
-
> `RequestRootsAsync` throws `InvalidOperationException("Roots are not supported in stateless mode.")` whenever the server is running stateless — which includes every Streamable HTTP server under `DRAFT-2026-v1` once that revision is forced to stateless-only in a future PR. Stdio servers and current-protocol stateful Streamable HTTP servers continue to work via the legacy server-to-client `roots/list` request flow. For code that needs to run on stateless servers — including all `DRAFT-2026-v1` Streamable HTTP servers going forward — throw `InputRequiredException` from your handler instead. It works under both protocols and both session modes.
112
+
> `RequestRootsAsync` throws `InvalidOperationException("Roots are not supported in stateless mode.")` whenever the server is running stateless — which includes every Streamable HTTP server under `2026-07-28` once that revision is forced to stateless-only in a future PR. Stdio servers and current-protocol stateful Streamable HTTP servers continue to work via the legacy server-to-client `roots/list` request flow. For code that needs to run on stateless servers — including all `2026-07-28` Streamable HTTP servers going forward — throw `InputRequiredException` from your handler instead. It works under both protocols and both session modes.
113
113
114
114
For example:
115
115
@@ -128,7 +128,7 @@ public static string ListRootsWithMrtr(
128
128
129
129
if (!server.IsMrtrSupported)
130
130
{
131
-
return"This tool requires MRTR support (DRAFT-2026-v1, or a stateful current-protocol session).";
131
+
return"This tool requires MRTR support (2026-07-28, or a stateful current-protocol session).";
Copy file name to clipboardExpand all lines: docs/concepts/sampling/sampling.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -123,10 +123,10 @@ Sampling requires the client to advertise the `sampling` capability. This is han
123
123
124
124
### Multi Round-Trip Requests (MRTR)
125
125
126
-
[MRTR](xref:mrtr) is the SEP-2322 mechanism for server-driven input requests, finalized in protocol revision `DRAFT-2026-v1`. Under the draft protocol, the server-to-client `sampling/createMessage` request method is removed; the recommended way to ask the client to sample from a server handler is to throw <xref:ModelContextProtocol.Protocol.InputRequiredException> and let the SDK emit an <xref:ModelContextProtocol.Protocol.InputRequiredResult> on the wire.
126
+
[MRTR](xref:mrtr) is the SEP-2322 mechanism for server-driven input requests, finalized in protocol revision `2026-07-28`. Under the draft protocol, the server-to-client `sampling/createMessage` request method is removed; the recommended way to ask the client to sample from a server handler is to throw <xref:ModelContextProtocol.Protocol.InputRequiredException> and let the SDK emit an <xref:ModelContextProtocol.Protocol.InputRequiredResult> on the wire.
127
127
128
128
> [!IMPORTANT]
129
-
> `SampleAsync` and `AsSamplingChatClient` throw `InvalidOperationException("Sampling is not supported in stateless mode.")` whenever the server is running stateless — which includes every Streamable HTTP server under `DRAFT-2026-v1` once that revision is forced to stateless-only in a future PR. Stdio servers and current-protocol stateful Streamable HTTP servers continue to work via the legacy server-to-client `sampling/createMessage` request flow. For code that needs to run on stateless servers — including all `DRAFT-2026-v1` Streamable HTTP servers going forward — throw `InputRequiredException` from your handler instead. It works under both protocols and both session modes.
129
+
> `SampleAsync` and `AsSamplingChatClient` throw `InvalidOperationException("Sampling is not supported in stateless mode.")` whenever the server is running stateless — which includes every Streamable HTTP server under `2026-07-28` once that revision is forced to stateless-only in a future PR. Stdio servers and current-protocol stateful Streamable HTTP servers continue to work via the legacy server-to-client `sampling/createMessage` request flow. For code that needs to run on stateless servers — including all `2026-07-28` Streamable HTTP servers going forward — throw `InputRequiredException` from your handler instead. It works under both protocols and both session modes.
130
130
131
131
For example:
132
132
@@ -146,7 +146,7 @@ public static string SampleWithMrtr(
146
146
147
147
if (!server.IsMrtrSupported)
148
148
{
149
-
return"This tool requires MRTR support (DRAFT-2026-v1, or a stateful current-protocol session).";
149
+
return"This tool requires MRTR support (2026-07-28, or a stateful current-protocol session).";
150
150
}
151
151
152
152
// First call — request LLM completion from the client
Copy file name to clipboardExpand all lines: docs/concepts/tools/tools.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -339,7 +339,7 @@ Rules and constraints:
339
339
- The header name must contain only visible ASCII characters (0x21–0x7E) excluding colon (`:`).
340
340
- Values containing non-ASCII characters, control characters, or leading/trailing whitespace are Base64-encoded using the `=?base64?{value}?=` wrapper.
341
341
- Header names must be case-insensitively unique within the tool's input schema.
342
-
- Header validation is enforced only for protocol versions that support the HTTP Standardization feature (currently `DRAFT-2026-v1` and later).
342
+
- Header validation is enforced only for protocol versions that support the HTTP Standardization feature (currently `2026-07-28` and later).
0 commit comments