Skip to content

Commit b9c6c90

Browse files
committed
feat: implement MCP protocol version header support
Add MCP-Protocol-Version header to all HTTP requests as required by MCP specification 2025-06-18. This enables proper server-side version negotiation and backwards compatibility handling. - Add protocol version constants (2025-06-18 for streamable HTTP, 2024-11-05 for SSE) - Include MCP-Protocol-Version header in all GET/POST/DELETE requests - Update WebClientStreamableHttpTransport, WebFluxSseClientTransport, HttpClientSseClientTransport, and HttpClientStreamableHttpTransport Complies with MCP specification requirement that HTTP clients MUST include protocol version header on all requests to MCP servers. Related to #398 , #363 , #250 Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
1 parent 8d71b76 commit b9c6c90

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public class WebClientStreamableHttpTransport implements McpClientTransport {
6565

6666
private static final Logger logger = LoggerFactory.getLogger(WebClientStreamableHttpTransport.class);
6767

68+
private static final String MCP_PROTOCOL_VERSION = "2025-06-18";
69+
70+
private static final String MCP_PROTOCOL_VERSION_HEADER_NAME = "MCP-Protocol-Version";
71+
6872
private static final String DEFAULT_ENDPOINT = "/mcp";
6973

7074
/**
@@ -127,12 +131,20 @@ public Mono<Void> connect(Function<Mono<McpSchema.JSONRPCMessage>, Mono<McpSchem
127131

128132
private DefaultMcpTransportSession createTransportSession() {
129133
Function<String, Publisher<Void>> onClose = sessionId -> sessionId == null ? Mono.empty()
130-
: webClient.delete().uri(this.endpoint).headers(httpHeaders -> {
131-
httpHeaders.add("mcp-session-id", sessionId);
132-
}).retrieve().toBodilessEntity().onErrorComplete(e -> {
133-
logger.warn("Got error when closing transport", e);
134-
return true;
135-
}).then();
134+
: webClient.delete()
135+
.uri(this.endpoint)
136+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
137+
.headers(httpHeaders -> {
138+
httpHeaders.add("mcp-session-id", sessionId);
139+
httpHeaders.add(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION);
140+
})
141+
.retrieve()
142+
.toBodilessEntity()
143+
.onErrorComplete(e -> {
144+
logger.warn("Got error when closing transport", e);
145+
return true;
146+
})
147+
.then();
136148
return new DefaultMcpTransportSession(onClose);
137149
}
138150

@@ -185,6 +197,7 @@ private Mono<Disposable> reconnect(McpTransportStream<Disposable> stream) {
185197
Disposable connection = webClient.get()
186198
.uri(this.endpoint)
187199
.accept(MediaType.TEXT_EVENT_STREAM)
200+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
188201
.headers(httpHeaders -> {
189202
transportSession.sessionId().ifPresent(id -> httpHeaders.add("mcp-session-id", id));
190203
if (stream != null) {
@@ -245,6 +258,7 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage message) {
245258
Disposable connection = webClient.post()
246259
.uri(this.endpoint)
247260
.accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON)
261+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
248262
.headers(httpHeaders -> {
249263
transportSession.sessionId().ifPresent(id -> httpHeaders.add("mcp-session-id", id));
250264
})

mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebFluxSseClientTransport.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public class WebFluxSseClientTransport implements McpClientTransport {
6262

6363
private static final Logger logger = LoggerFactory.getLogger(WebFluxSseClientTransport.class);
6464

65+
private static final String MCP_PROTOCOL_VERSION = "2024-11-05";
66+
67+
private static final String MCP_PROTOCOL_VERSION_HEADER_NAME = "MCP-Protocol-Version";
68+
6569
/**
6670
* Event type for JSON-RPC messages received through the SSE connection. The server
6771
* sends messages with this event type to transmit JSON-RPC protocol data.
@@ -249,6 +253,7 @@ public Mono<Void> sendMessage(JSONRPCMessage message) {
249253
return webClient.post()
250254
.uri(messageEndpointUri)
251255
.contentType(MediaType.APPLICATION_JSON)
256+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
252257
.bodyValue(jsonText)
253258
.retrieve()
254259
.toBodilessEntity()
@@ -281,6 +286,7 @@ protected Flux<ServerSentEvent<String>> eventStream() {// @formatter:off
281286
.get()
282287
.uri(this.sseEndpoint)
283288
.accept(MediaType.TEXT_EVENT_STREAM)
289+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
284290
.retrieve()
285291
.bodyToFlux(SSE_TYPE)
286292
.retryWhen(Retry.from(retrySignal -> retrySignal.handle(inboundRetryHandler)));

mcp/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
*/
6262
public class HttpClientSseClientTransport implements McpClientTransport {
6363

64+
private static final String MCP_PROTOCOL_VERSION = "2024-11-05";
65+
66+
private static final String MCP_PROTOCOL_VERSION_HEADER_NAME = "MCP-Protocol-Version";
67+
6468
private static final Logger logger = LoggerFactory.getLogger(HttpClientSseClientTransport.class);
6569

6670
/** SSE event type for JSON-RPC messages */
@@ -330,6 +334,7 @@ public Mono<Void> connect(Function<Mono<JSONRPCMessage>, Mono<JSONRPCMessage>> h
330334
.uri(Utils.resolveUri(this.baseUri, this.sseEndpoint))
331335
.header("Accept", "text/event-stream")
332336
.header("Cache-Control", "no-cache")
337+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
333338
.GET()
334339
.build();
335340

@@ -457,6 +462,7 @@ private Mono<HttpResponse<String>> sendHttpPost(final String endpoint, final Str
457462
final URI requestUri = Utils.resolveUri(baseUri, endpoint);
458463
final HttpRequest request = this.requestBuilder.copy()
459464
.uri(requestUri)
465+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
460466
.POST(HttpRequest.BodyPublishers.ofString(body))
461467
.build();
462468

mcp/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public class HttpClientStreamableHttpTransport implements McpClientTransport {
7272

7373
private static final Logger logger = LoggerFactory.getLogger(HttpClientStreamableHttpTransport.class);
7474

75+
private static final String MCP_PROTOCOL_VERSION = "2025-06-18";
76+
77+
private static final String MCP_PROTOCOL_VERSION_HEADER_NAME = "MCP-Protocol-Version";
78+
7579
private static final String DEFAULT_ENDPOINT = "/mcp";
7680

7781
/**
@@ -158,6 +162,7 @@ private Publisher<Void> createDelete(String sessionId) {
158162
.uri(Utils.resolveUri(this.baseUri, this.endpoint))
159163
.header("Cache-Control", "no-cache")
160164
.header("mcp-session-id", sessionId)
165+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
161166
.DELETE()
162167
.build();
163168

@@ -222,6 +227,7 @@ private Mono<Disposable> reconnect(McpTransportStream<Disposable> stream) {
222227
HttpRequest request = requestBuilder.uri(Utils.resolveUri(this.baseUri, this.endpoint))
223228
.header("Accept", TEXT_EVENT_STREAM)
224229
.header("Cache-Control", "no-cache")
230+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
225231
.GET()
226232
.build();
227233

@@ -361,6 +367,7 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sendMessage) {
361367
.header("Accept", TEXT_EVENT_STREAM + ", " + APPLICATION_JSON)
362368
.header("Content-Type", APPLICATION_JSON)
363369
.header("Cache-Control", "no-cache")
370+
.header(MCP_PROTOCOL_VERSION_HEADER_NAME, MCP_PROTOCOL_VERSION)
364371
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
365372
.build();
366373

0 commit comments

Comments
 (0)