diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java
index dd7c6539..5ed82228 100644
--- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java
+++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java
@@ -36,6 +36,9 @@
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
+import static io.modelcontextprotocol.spec.McpSchema.Headers.LAST_EVENT_ID;
+import static io.modelcontextprotocol.spec.McpSchema.Headers.MCP_SESSION_ID;
+
/**
* An implementation of the Streamable HTTP protocol as defined by the
* 2025-03-26
version of the MCP specification.
@@ -128,7 +131,7 @@ public Mono connect(Function, Mono> onClose = sessionId -> sessionId == null ? Mono.empty()
: webClient.delete().uri(this.endpoint).headers(httpHeaders -> {
- httpHeaders.add("mcp-session-id", sessionId);
+ httpHeaders.add(MCP_SESSION_ID, sessionId);
})
.retrieve()
.toBodilessEntity()
@@ -187,9 +190,9 @@ private Mono reconnect(McpTransportStream stream) {
.uri(this.endpoint)
.accept(MediaType.TEXT_EVENT_STREAM)
.headers(httpHeaders -> {
- transportSession.sessionId().ifPresent(id -> httpHeaders.add("mcp-session-id", id));
+ transportSession.sessionId().ifPresent(id -> httpHeaders.add(MCP_SESSION_ID, id));
if (stream != null) {
- stream.lastId().ifPresent(id -> httpHeaders.add("last-event-id", id));
+ stream.lastId().ifPresent(id -> httpHeaders.add(LAST_EVENT_ID, id));
}
})
.exchangeToFlux(response -> {
@@ -247,12 +250,11 @@ public Mono sendMessage(McpSchema.JSONRPCMessage message) {
.uri(this.endpoint)
.accept(MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_JSON)
.headers(httpHeaders -> {
- transportSession.sessionId().ifPresent(id -> httpHeaders.add("mcp-session-id", id));
+ transportSession.sessionId().ifPresent(id -> httpHeaders.add(MCP_SESSION_ID, id));
})
.bodyValue(message)
.exchangeToFlux(response -> {
- if (transportSession
- .markInitialized(response.headers().asHttpHeaders().getFirst("mcp-session-id"))) {
+ if (transportSession.markInitialized(response.headers().asHttpHeaders().getFirst(MCP_SESSION_ID))) {
// Once we have a session, we try to open an async stream for
// the server to send notifications and requests out-of-band.
reconnect(null).contextWrite(sink.contextView()).subscribe();
diff --git a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
index 59713094..cda76531 100644
--- a/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
+++ b/mcp/src/main/java/io/modelcontextprotocol/spec/McpSchema.java
@@ -141,6 +141,28 @@ public static final class ErrorCodes {
}
+ // ---------------------------
+ // JSON-RPC Protocol Headers
+ // ---------------------------
+ /**
+ * Standard header name used in MCP JSON-RPC request and responses.
+ */
+ public static final class Headers {
+
+ /**
+ * The Model Context Protocol (MCP) session ID header name.
+ */
+ public static final String MCP_SESSION_ID = "Mcp-Session-Id";
+
+ /**
+ * The Last-Event-ID HTTP request header reports an EventSource object's last
+ * event ID string to the server when the user agent is to reestablish the
+ * connection.
+ */
+ public static final String LAST_EVENT_ID = "Last-Event-ID";
+
+ }
+
public sealed interface Request permits InitializeRequest, CallToolRequest, CreateMessageRequest, ElicitRequest,
CompleteRequest, GetPromptRequest {