Skip to content

Commit 1072617

Browse files
committed
Support an HTTP GET handler for HttpServletStatelessServerTransport
Currently, `HttpServletStatelessServerTransport` always returns `SC_METHOD_NOT_ALLOWED` for GET. With this change, consumers of the library can implement their own GET handler so that they can implement the Session semantics of the MCP protocol.
1 parent dee088d commit 1072617

File tree

3 files changed

+53
-12
lines changed

3 files changed

+53
-12
lines changed

mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStatelessServerTransport.java

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,8 @@
44

55
package io.modelcontextprotocol.server.transport;
66

7-
import java.io.BufferedReader;
8-
import java.io.IOException;
9-
import java.io.PrintWriter;
10-
11-
import org.slf4j.Logger;
12-
import org.slf4j.LoggerFactory;
13-
14-
import io.modelcontextprotocol.json.McpJsonMapper;
15-
167
import io.modelcontextprotocol.common.McpTransportContext;
8+
import io.modelcontextprotocol.json.McpJsonMapper;
179
import io.modelcontextprotocol.server.McpStatelessServerHandler;
1810
import io.modelcontextprotocol.server.McpTransportContextExtractor;
1911
import io.modelcontextprotocol.spec.McpError;
@@ -25,8 +17,14 @@
2517
import jakarta.servlet.http.HttpServlet;
2618
import jakarta.servlet.http.HttpServletRequest;
2719
import jakarta.servlet.http.HttpServletResponse;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
2822
import reactor.core.publisher.Mono;
2923

24+
import java.io.BufferedReader;
25+
import java.io.IOException;
26+
import java.io.PrintWriter;
27+
3028
/**
3129
* Implementation of an HttpServlet based {@link McpStatelessServerTransport}.
3230
*
@@ -58,6 +56,9 @@ public class HttpServletStatelessServerTransport extends HttpServlet implements
5856

5957
private volatile boolean isClosing = false;
6058

59+
private volatile GetHandler getHandler = (request, response) -> response
60+
.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
61+
6162
private HttpServletStatelessServerTransport(McpJsonMapper jsonMapper, String mcpEndpoint,
6263
McpTransportContextExtractor<HttpServletRequest> contextExtractor) {
6364
Assert.notNull(jsonMapper, "jsonMapper must not be null");
@@ -84,6 +85,18 @@ public Mono<Void> closeGracefully() {
8485
return Mono.fromRunnable(() -> this.isClosing = true);
8586
}
8687

88+
public void setGetHandler(GetHandler getHandler) {
89+
Assert.notNull(getHandler, "getHandler must not be null");
90+
91+
this.getHandler = getHandler;
92+
}
93+
94+
public interface GetHandler {
95+
96+
void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
97+
98+
}
99+
87100
/**
88101
* Handles GET requests - returns 405 METHOD NOT ALLOWED as stateless transport
89102
* doesn't support GET requests.
@@ -102,7 +115,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
102115
return;
103116
}
104117

105-
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
118+
getHandler.doGet(request, response);
106119
}
107120

108121
/**

mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStatelessServerTransport.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public class WebFluxStatelessServerTransport implements McpStatelessServerTransp
4646

4747
private volatile boolean isClosing = false;
4848

49+
private volatile GetHandler getHandler = (request) -> ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED).build();
50+
4951
private WebFluxStatelessServerTransport(McpJsonMapper jsonMapper, String mcpEndpoint,
5052
McpTransportContextExtractor<ServerRequest> contextExtractor) {
5153
Assert.notNull(jsonMapper, "jsonMapper must not be null");
@@ -92,8 +94,20 @@ public RouterFunction<?> getRouterFunction() {
9294
return this.routerFunction;
9395
}
9496

97+
public interface GetHandler {
98+
99+
Mono<ServerResponse> doGet(ServerRequest request);
100+
101+
}
102+
103+
public void setGetHandler(GetHandler getHandler) {
104+
Assert.notNull(getHandler, "getHandler must not be null");
105+
106+
this.getHandler = getHandler;
107+
}
108+
95109
private Mono<ServerResponse> handleGet(ServerRequest request) {
96-
return ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED).build();
110+
return getHandler.doGet(request);
97111
}
98112

99113
private Mono<ServerResponse> handlePost(ServerRequest request) {

mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStatelessServerTransport.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public class WebMvcStatelessServerTransport implements McpStatelessServerTranspo
5050

5151
private volatile boolean isClosing = false;
5252

53+
private volatile GetHandler getHandler = (request) -> ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED).build();
54+
5355
private WebMvcStatelessServerTransport(McpJsonMapper jsonMapper, String mcpEndpoint,
5456
McpTransportContextExtractor<ServerRequest> contextExtractor) {
5557
Assert.notNull(jsonMapper, "jsonMapper must not be null");
@@ -96,8 +98,20 @@ public RouterFunction<ServerResponse> getRouterFunction() {
9698
return this.routerFunction;
9799
}
98100

101+
public interface GetHandler {
102+
103+
ServerResponse doGet(ServerRequest request);
104+
105+
}
106+
107+
public void setGetHandler(GetHandler getHandler) {
108+
Assert.notNull(getHandler, "getHandler must not be null");
109+
110+
this.getHandler = getHandler;
111+
}
112+
99113
private ServerResponse handleGet(ServerRequest request) {
100-
return ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED).build();
114+
return getHandler.doGet(request);
101115
}
102116

103117
private ServerResponse handlePost(ServerRequest request) {

0 commit comments

Comments
 (0)