Skip to content

Commit 2d789f8

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 6a3391f commit 2d789f8

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");
@@ -79,6 +80,18 @@ public Mono<Void> closeGracefully() {
7980
return Mono.fromRunnable(() -> this.isClosing = true);
8081
}
8182

83+
public void setGetHandler(GetHandler getHandler) {
84+
Assert.notNull(getHandler, "getHandler must not be null");
85+
86+
this.getHandler = getHandler;
87+
}
88+
89+
public interface GetHandler {
90+
91+
void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
92+
93+
}
94+
8295
/**
8396
* Handles GET requests - returns 405 METHOD NOT ALLOWED as stateless transport
8497
* doesn't support GET requests.
@@ -97,7 +110,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
97110
return;
98111
}
99112

100-
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
113+
getHandler.doGet(request, response);
101114
}
102115

103116
/**

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");
@@ -87,8 +89,20 @@ public RouterFunction<?> getRouterFunction() {
8789
return this.routerFunction;
8890
}
8991

92+
public interface GetHandler {
93+
94+
Mono<ServerResponse> doGet(ServerRequest request);
95+
96+
}
97+
98+
public void setGetHandler(GetHandler getHandler) {
99+
Assert.notNull(getHandler, "getHandler must not be null");
100+
101+
this.getHandler = getHandler;
102+
}
103+
90104
private Mono<ServerResponse> handleGet(ServerRequest request) {
91-
return ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED).build();
105+
return getHandler.doGet(request);
92106
}
93107

94108
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");
@@ -91,8 +93,20 @@ public RouterFunction<ServerResponse> getRouterFunction() {
9193
return this.routerFunction;
9294
}
9395

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

98112
private ServerResponse handlePost(ServerRequest request) {

0 commit comments

Comments
 (0)