Skip to content

Commit b9e6fc5

Browse files
mcp: add documentation for new protocol version (#1019)
Add documentation for new protocol version in the `internal/docs`
1 parent 01847b3 commit b9e6fc5

9 files changed

Lines changed: 719 additions & 36 deletions

File tree

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ contains feature documentation, mapping the MCP spec to the packages above.
3434

3535
The following table shows which versions of the Go SDK support which versions of the MCP specification:
3636

37-
| SDK Version | Latest MCP Spec | All Supported MCP Specs |
38-
|-----------------|-------------------|----------------------------------------------------|
39-
| v1.4.0+ | 2025-11-25\* | 2025-11-25\*, 2025-06-18, 2025-03-26, 2024-11-05 |
40-
| v1.2.0 - v1.3.1 | 2025-11-25\*\* | 2025-11-25\*\*, 2025-06-18, 2025-03-26, 2024-11-05 |
41-
| v1.0.0 - v1.1.0 | 2025-06-18 | 2025-06-18, 2025-03-26, 2024-11-05 |
37+
| SDK Version | Latest MCP Spec | All Supported MCP Specs |
38+
|-----------------|-------------------|------------------------------------------------------------------|
39+
| v1.7.0+ | 2026-07-28 | 2026-07-28, 2025-11-25\*, 2025-06-18, 2025-03-26, 2024-11-05 |
40+
| v1.4.0 - v1.6.1 | 2025-11-25\* | 2025-11-25\*, 2025-06-18, 2025-03-26, 2024-11-05 |
41+
| v1.2.0 - v1.3.1 | 2025-11-25\*\* | 2025-11-25\*\*, 2025-06-18, 2025-03-26, 2024-11-05 |
42+
| v1.0.0 - v1.1.0 | 2025-06-18 | 2025-06-18, 2025-03-26, 2024-11-05 |
4243

4344
\* Client side OAuth has experimental support.
4445

docs/client.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
1. [Roots](#roots)
55
1. [Sampling](#sampling)
66
1. [Elicitation](#elicitation)
7+
1. [Multi Round-Trip Requests (MRTR)](#multi-round-trip-requests-(mrtr))
78
1. [Capabilities](#capabilities)
89
1. [Capability inference](#capability-inference)
910
1. [Explicit capabilities](#explicit-capabilities)
11+
1. [Extensions](#extensions)
1012

1113
## Roots
1214

@@ -34,6 +36,10 @@ client, a call to `AddRoot` or `RemoveRoots` will result in a
3436
[`ServerSession.ListRoots`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerSession.ListRoots)
3537
method. To receive notifications about root changes, set
3638
[`ServerOptions.RootsListChangedHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.RootsListChangedHandler).
39+
For protocol versions `2026-07-28` and later, `ListRoots` requests are
40+
delivered via the
41+
[Multi Round-Trip Requests](protocol.md#multi-round-trip-requests-mrtr)
42+
pattern.
3743

3844
```go
3945
func Example_roots() {
@@ -102,6 +108,11 @@ This function is invoked whenever the server requests sampling.
102108
**Server-side**: To use sampling from the server, call
103109
[`ServerSession.CreateMessage`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerSession.CreateMessage).
104110

111+
For protocol versions `2026-07-28` and later, sampling requests are
112+
delivered via the
113+
[Multi Round-Trip Requests](protocol.md#multi-round-trip-requests-mrtr)
114+
pattern.
115+
105116
```go
106117
func Example_sampling() {
107118
ctx := context.Background()
@@ -154,6 +165,11 @@ you must declare that capability explicitly (see [Capabilities](#capabilities))
154165
**Server-side**: To use elicitation from the server, call
155166
[`ServerSession.Elicit`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerSession.Elicit).
156167

168+
For protocol versions `2026-07-28` and later, elicitation requests are
169+
delivered via the
170+
[Multi Round-Trip Requests](protocol.md#multi-round-trip-requests-mrtr)
171+
pattern.
172+
157173
```go
158174
func Example_elicitation() {
159175
ctx := context.Background()
@@ -191,6 +207,37 @@ func Example_elicitation() {
191207
}
192208
```
193209

210+
## Multi Round-Trip Requests (MRTR)
211+
212+
[SEP-2322](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2322)
213+
introduces the MRTR pattern: server-to-client requests for sampling,
214+
elicitation, and roots are no longer issued as fresh JSON-RPC requests but
215+
are carried inside the in-flight reply of a `tools/call`, `prompts/get`, or
216+
`resources/read`. The client must respond by retrying the original request
217+
with the produced responses.
218+
219+
The SDK installs `clientMultiRoundTripMiddleware` for every client by
220+
default. The middleware:
221+
222+
1. Inspects each `tools/call`/`prompts/get`/`resources/read` reply.
223+
2. If the result's `NeedsInput()` is true, fans out the `InputRequests` map
224+
concurrently, calling the configured handler for each (`elicit`,
225+
`createMessage`/`createMessageWithTools`, or `listRoots`).
226+
3. Threads the server-supplied opaque `RequestState` back unchanged.
227+
4. Retries the original request with the responses set, repeating until the
228+
result no longer needs input.
229+
230+
The middleware is enabled by default. To opt out, set
231+
[`ClientOptions.MultiRoundTrip.Disabled = true`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#MultiRoundTripOptions);
232+
the client will then surface `InputRequiredResult` values directly to the
233+
caller and your code must fulfil the requests manually.
234+
235+
For legacy (`<= 2025-11-25`) servers, the SDK transparently sends server
236+
requests on the legacy server-initiated channel; the MRTR machinery is a
237+
no-op in that direction. For legacy clients talking to MRTR-style servers,
238+
the server SDK applies the inverse compatibility shim — see the
239+
[server-side documentation](server.md#multi-round-trip-requests-mrtr).
240+
194241
## Capabilities
195242

196243
Client capabilities are advertised to servers during the initialization
@@ -247,3 +294,11 @@ client := mcp.NewClient(impl, &mcp.ClientOptions{
247294
})
248295
```
249296

297+
### Extensions
298+
299+
[SEP-2133](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2133)
300+
adds an `extensions` map to `ClientCapabilities` and `ServerCapabilities` so
301+
that optional capabilities outside the core protocol can be declared on the
302+
wire. Keys are namespaced as `"{vendor-prefix}/{extension-name}"`; values
303+
are per-extension settings objects.
304+

docs/protocol.md

Lines changed: 132 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Support for the MCP base protocol
33

44
1. [Lifecycle](#lifecycle)
5+
1. [Discovery (`server/discover`)](#discovery-(server/discover))
6+
1. [Per-request `_meta` keys](#per-request-meta-keys)
57
1. [Transports](#transports)
68
1. [Stdio Transport](#stdio-transport)
79
1. [Streamable Transport](#streamable-transport)
@@ -20,20 +22,27 @@
2022
1. [Cancellation](#cancellation)
2123
1. [Ping](#ping)
2224
1. [Progress](#progress)
25+
1. [Error codes](#error-codes)
2326

2427
## Lifecycle
2528

2629
The SDK provides an API for defining both MCP clients and servers, and
2730
connecting them over various transports. When a client and server are
28-
connected, it creates a logical session, which follows the MCP spec's
29-
[lifecycle](https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle).
31+
connected, it creates a logical session.
3032

31-
In this SDK, both a
32-
[`Client`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Client)
33-
and
34-
[`Server`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server)
35-
can handle multiple peers. Every time a new peer is connected, it creates a new
36-
session.
33+
The MCP specification defines two lifecycle models, and the SDK supports both
34+
transparently based on the negotiated protocol version:
35+
36+
- The **legacy `initialize` handshake**
37+
([lifecycle](https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle))
38+
used by protocol versions through `2025-11-25`.
39+
- A **stateless** model introduced in `2026-07-28` by
40+
[SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575),
41+
in which there is no `initialize`/`notifications/initialized` handshake, and
42+
each request carries its protocol version, client identity, and client
43+
capabilities in `_meta`.
44+
45+
In both models, the SDK exposes the same API:
3746

3847
- A `Client` is a logical MCP client, configured with various
3948
[`ClientOptions`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ClientOptions).
@@ -49,11 +58,16 @@ session.
4958
[`Server.Connect`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#Server.Connect),
5059
it creates a
5160
[`ServerSession`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerSession).
52-
This session is not initialized until the client sends the
53-
`notifications/initialized` message. Use `ServerOptions.InitializedHandler`
54-
to listen for this event, or just use the session through various feature
55-
handlers (such as a `ToolHandler`). Requests to the server are rejected until
56-
the client has initialized the session.
61+
62+
In the legacy model, the server session is not considered initialized until
63+
the client sends the `notifications/initialized` message. Use
64+
`ServerOptions.InitializedHandler` to listen for this event, or just use the
65+
session through various feature handlers (such as a `ToolHandler`). Requests
66+
to the server are rejected until the client has initialized the session.
67+
68+
In the stateless model (`2026-07-28`+), there is no handshake. The server
69+
processes the first request the moment it arrives, validates the per-request
70+
`_meta` fields.
5771

5872
Both `ClientSession` and `ServerSession` have a `Close` method to terminate the
5973
session, and a `Wait` method to await session termination by the peer. Typically,
@@ -98,6 +112,41 @@ func Example_lifecycle() {
98112
}
99113
```
100114

115+
### Discovery (`server/discover`)
116+
117+
Introduced in `2026-07-28` by
118+
[SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575),
119+
the `server/discover` RPC lets a client discover a server's supported
120+
protocol versions, capabilities, and identity before issuing any other
121+
request. Servers implementing `2026-07-28` MUST implement it.
122+
123+
- **Server**: `Server.Connect` registers the
124+
`server/discover` handler automatically; the response is computed from the
125+
server's static configuration (capabilities, server info, instructions) and
126+
the transport-filtered list of supported protocol versions.
127+
- **Client**: `Client.Connect` calls `server/discover` first and
128+
uses the result to negotiate a mutually supported version. If discovery
129+
fails or the server does not support the latest version, the client falls back to the
130+
legacy `initialize` handshake.
131+
132+
### Per-request `_meta` keys
133+
134+
When the negotiated protocol version is `2026-07-28` or later, every request
135+
carries these keys inside its `_meta` map (constants live in
136+
[`mcp/protocol.go`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#pkg-constants)):
137+
138+
| Constant | Wire key | Type |
139+
|---|---|---|
140+
| `MetaKeyProtocolVersion` | `io.modelcontextprotocol/protocolVersion` | `string` |
141+
| `MetaKeyClientInfo` | `io.modelcontextprotocol/clientInfo` | `*Implementation` |
142+
| `MetaKeyClientCapabilities` | `io.modelcontextprotocol/clientCapabilities` | `*ClientCapabilities` |
143+
| `MetaKeyLogLevel` | `io.modelcontextprotocol/logLevel` | `LoggingLevel` (deprecated by SEP-2577) |
144+
145+
The client populates these keys automatically on every outgoing request.
146+
Server-side handlers can read them
147+
through `ServerRequest[P].ProtocolVersion()`, `ServerRequest[P].ClientInfo()`,
148+
and `ServerRequest[P].ClientCapabilities()`.
149+
101150
## Transports
102151

103152
A
@@ -188,6 +237,39 @@ client, err := mcp.Connect(ctx, transport, &mcp.ClientOptions{...})
188237
The `StreamableClientTransport` handles the HTTP requests and communicates with
189238
the server using the streamable transport protocol.
190239

240+
#### HTTP Headers
241+
242+
[SEP-2243](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2243)
243+
standardises a small set of MCP-specific HTTP headers, sent and validated by
244+
the SDK only for sessions negotiated on protocol version `2026-07-28` or
245+
later.
246+
247+
| Header | Direction | Purpose |
248+
|---|---|---|
249+
| `Mcp-Protocol-Version` | request | Mirrors `_meta.io.modelcontextprotocol/protocolVersion` from the body |
250+
| `Mcp-Session-Id` | request/response | Logical session identifier (removed in stateless mode) |
251+
| `Mcp-Method` | request | Mirrors the JSON-RPC `method` field; mismatch ⇒ `-32020` |
252+
| `Mcp-Name` | request | Mirrors the request's principal name (`tools/call.params.name`, `prompts/get.params.name`, `resources/read.params.uri`); mismatch ⇒ `-32020` |
253+
| `Mcp-Param-{Header}` | request | Per-tool parameter passthrough; see below |
254+
255+
The header-name set is exhaustive: for protocol versions earlier than
256+
`2026-07-28`, only `Mcp-Protocol-Version` and `Mcp-Session-Id` are recognised.
257+
258+
**Body↔header mirroring.** When `Mcp-Method` or `Mcp-Name` is present but
259+
does not match the JSON-RPC body, the server returns
260+
[`CodeHeaderMismatch`](#error-codes) (`-32020`). The same applies to a
261+
mismatch between `Mcp-Protocol-Version` and the body's
262+
`_meta.io.modelcontextprotocol/protocolVersion`.
263+
264+
**`Mcp-Param-*` passthrough.** A tool may annotate properties of its
265+
`InputSchema` with `x-mcp-header: "<HeaderName>"`. When a client invokes that
266+
tool over HTTP, the SDK serializes the matching argument(s) as
267+
`Mcp-Param-<HeaderName>` request headers (using `=?base64?...?=` encoding for
268+
non-ASCII values). On the server, the headers are validated against the body
269+
and either accepted or rejected with `-32020`. Properties so annotated must
270+
be typed `string`, `integer`, or `boolean`; tools that fail validation at
271+
registration time are silently dropped from `tools/list`.
272+
191273
#### Resumability and Redelivery
192274

193275
By default, the streamable server does not support [resumability or
@@ -201,6 +283,13 @@ value. The SDK provides a `MemoryEventStore` for testing or simple use cases;
201283
for production use it is generally advisable to use a more sophisticated
202284
implementation.
203285

286+
> **Note**: [SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575)
287+
> removes SSE stream resumability (`Last-Event-ID`, SSE event IDs) for protocol
288+
> version `2026-07-28`. The SDK preserves the `EventStore` and `Last-Event-ID`
289+
> code paths for backward compatibility with `2025-11-25` and earlier; on
290+
> `2026-07-28` sessions, a broken response stream loses the in-flight request
291+
> and the client must re-issue it as a new request with a new ID.
292+
204293
#### Stateless Mode
205294

206295
The streamable server supports a _stateless mode_ by setting
@@ -219,6 +308,10 @@ to see the logical session
219308
> modelcontextprotocol/modelcontextprotocol#1372, or
220309
> modelcontextprotocol/modelcontextprotocol#1442 for potential refinements.
221310
311+
> **Required for `2026-07-28`**: the streamable HTTP transport accepts
312+
> requests at protocol version `2026-07-28` **only** when `Stateless = true`.
313+
> Requests at that version against a non-stateless handler are rejected.
314+
222315
_See [examples/server/distributed](https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/distributed/main.go) for
223316
an example using stateless mode to implement a server distributed across
224317
multiple processes._
@@ -597,6 +690,13 @@ session if the ping fails, set
597690
or
598691
[`ServerOptions.KeepAlive`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.KeepAlive).
599692

693+
> **Note**: `ping` is removed from the protocol as of `2026-07-28` by
694+
> [SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575).
695+
> The SDK preserves the API for backward compatibility with legacy clients;
696+
> when both peers negotiate `2026-07-28`, the server returns
697+
> `MethodNotFound` (`-32601`) for `ping` and `KeepAlive` should not be
698+
> enabled.
699+
600700
### Progress
601701

602702
[Progress](https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/progress)
@@ -658,3 +758,22 @@ func Example_progress() {
658758
}
659759
```
660760

761+
### Error codes
762+
763+
The SDK uses the standard JSON-RPC base codes (parse error `-32700`,
764+
invalid request `-32600`, method not found `-32601`, invalid params
765+
`-32602`, internal error `-32603`) plus the following MCP-specific codes:
766+
767+
| Constant | Code | Meaning |
768+
|---|---|---|
769+
| [`CodeHeaderMismatch`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#CodeHeaderMismatch) | `-32020` | An MCP HTTP header (`Mcp-Method`, `Mcp-Name`, `Mcp-Protocol-Version`, or `Mcp-Param-*`) does not match the JSON-RPC body |
770+
| [`CodeMissingRequiredClientCapabilities`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#CodeMissingRequiredClientCapabilities) | `-32021` | Server requires client capabilities the client did not declare |
771+
| [`CodeUnsupportedProtocolVersion`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#CodeUnsupportedProtocolVersion) | `-32022` | Requested protocol version not supported. Data: `UnsupportedProtocolVersionData{Supported []string, Requested string}` |
772+
| [`CodeResourceNotFound`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#CodeResourceNotFound) | `-32602` | Resource URI not found (variable; was `-32002` before SEP-2164) |
773+
774+
The error code allocation policy defined in `2026-07-28`
775+
([SEP-2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575))
776+
partitions the JSON-RPC server-error range:
777+
778+
- `-32000` to `-32019`: implementation-defined; existing SDK usage is grandfathered.
779+
- `-32020` to `-32099`: reserved for the MCP specification.

0 commit comments

Comments
 (0)