Repository navigation
Backport server/discover / METHOD_NOT_FOUND fix (-32601) to pre-2.0 lines — HTTP 500 has no remedy without Spring Boot 4 migration #1085
Description
Activity
Confirming this on the pre-2.0 line. We're on Spring AI 1.1.2, which pins MCP Java SDK 0.17.0, using the stateless WebFlux transport (async).
Reproduction
Request:
{"jsonrpc":"2.0","id":11,"method":"foo/bar"}DefaultMcpStatelessServerHandler.handleRequestreturnsMono.error(new McpError("Missing handler for request type: ..."))as an early return, so it never reaches theonErrorResumea few lines below that maps errors onto a JSON-RPC error response.WebFluxStatelessServerTransportdoes not handle it either — itstry/catchonly covers synchronous deserialization (Invalid message format), and there is noonErrorResumearoundmcpHandler.handleRequest(...).The error therefore escapes the
RouterFunctionand is handled by the application's globalErrorWebExceptionHandler, producing a framework-shaped HTTP error body instead of a JSON-RPC error. Depending onserver.error.include-stacktrace, the response can carry the stack trace.Worth noting the scope: requests for registered methods behave correctly.
tools/callwith an unknown tool name returns a proper-32602, because that path runs through the handler and hitsonErrorResume. Only the unregistered-method dispatch leaks.Still present in 0.18.3 — I checked the
mcp-core0.18.3 sources and the early return is unchanged, so bumping within the 0.x line does not help.That is exactly why the backport matters here: 2.0.x requires Spring Boot 4, while Spring AI 1.1.x users are on Boot 3.x, so "upgrade to 2.0.x" is not an available path. Until a backport lands, the only remedy is wrapping the stateless handler in application code to convert
McpErrorinto-32601ourselves.- addedenhancementNew feature or requestNew feature or requestP1Significant bug affecting many users, highly requested featureSignificant bug affecting many users, highly requested feature
on Aug 17, 2026 Another data point for this ask, plus one thing I think is missing from the current fix plan.
Same failure one minor version up. We hit the identical
server/discover→ HTTP 500 on MCP Java SDK0.18.3(viaspring-ai1.1.8) on Spring Boot 3.3.5, WebMvc stateless transport, tools-only capabilities. Same conclusion about the upgrade path:spring-ai2.0.0'sspring-ai-starter-mcp-server-webmvcpullsspring-boot-starter-web:4.1.0, so it is a Framework 7 migration, not a version bump.For anyone else checking whether they can just upgrade: the fix commit for #784 (
5d3dece) is 11 commits ahead ofv2.0.0(compare v2.0.0...5d3dece→ahead_by: 11, behind_by: 0), and2.0.1is not on Maven Central yet — so there is currently no published artifact with it on any line.The part I think is missing: #1083 only covers
mcp-core.PR #1083 maps
METHOD_NOT_FOUND→ HTTP 404 insideHttpServletStatelessServerTransport. But the Spring transports each carry their own copy of that response-status logic, and none of them delegate to the servlet one:io.modelcontextprotocol.sdk:mcp-spring-webmvc:0.18.3—WebMvcStatelessServerTransport.handlePostusesServerResponse.ok()unconditionally on the handler success path, andHttpStatus.INTERNAL_SERVER_ERRORwhenhandleRequestthrows.io.modelcontextprotocol.sdk:mcp-spring-webflux:0.18.3—WebFluxStatelessServerTransportdoes the same (ServerResponse.ok()/INTERNAL_SERVER_ERROR).org.springframework.ai:mcp-spring-webmvc:2.0.0— still a separate class (org.springframework.ai.mcp.server.webmvc.transport.WebMvcStatelessServerTransport).javap -con it shows onlyMETHOD_NOT_ALLOWED,SERVICE_UNAVAILABLEandINTERNAL_SERVER_ERROR— there is noNOT_FOUNDreference in the class at all.
So even after #1083 merges and ships, a Spring MVC/WebFlux stateless server would still answer HTTP 500 to
server/discover. That matters for this issue specifically, because the pre-2.0 population asking for a backport is largelyspring-aiusers on the Spring transports. Whichever line the fix lands on, it seems it needs to cover those too.What we are doing meanwhile, in case it is useful as input to the "documented interim pattern" option in this issue: a servlet filter in front of the MCP endpoint that answers
404+-32601for unregistered methods. The one detail worth copying is that we do not hardcode the method list — we read the key set ofDefaultMcpStatelessServerHandler.requestHandlersreflectively, so the guard tracks both the SDK's registrations and the server's declared capabilities. (It also coversresources/list/prompts/list, which take the same 500 path when those capabilities are off.) If the handler map cannot be read, the filter passes the request through rather than judging it, and a test builds a real SDK server to pin that reflection so an upgrade breaks the test instead of silently disabling the guard.Happy to open a PR for the Spring transports if that would help.
Reacted by eashwar-mpFixing this would be appreciated 👀
Confirming on 0.17.x. I'm the reporter, env in the issue: MCP Java SDK 0.17.0 via spring-ai 1.1.4, Spring Boot 3.x, WebMvc stateless transport.
Minimal repro, a raw JSON-RPC POST for any unregistered method to the stateless endpoint:
{"jsonrpc":"2.0","id":1,"method":"server/discover"}returns HTTP 500, because
DefaultMcpStatelessServerHandler.handleRequestearly-returnsMono.error(new McpError("Missing handler for request type: server/discover"))before theonErrorResumethat would map it onto a JSON-RPC error, so it escapes to the transport, which maps an escaping handler error to 500. Registered methods are unaffected:tools/callwith an unknown tool name already returns a proper-32602. OpenAI's hosted connector then surfaces the 500 as HTTP 424external_connector_errorand aborts the whole response.I also checked #1104 against 0.17.x: the early-return is byte-for-byte identical and every
McpSchemaAPI it uses (JSONRPC_VERSION, theJSONRPCResponse/JSONRPCErrorconstructors,ErrorCodes.METHOD_NOT_FOUND) is present, so the same three-line fix plus tests apply cleanly on that line too, no line-specific adaptation needed.No strong preference on which lines get a release, just flagging the 0.17.x confirmation since the issue was tagged
needs confirmation. Thanks @olsavmic for the backport.@YoonSung agree the 404 gap is real: #1083 does only touch
HttpServletStatelessServerTransport, and the Spring transports carry their own status logic.But I don't think the 500 survives on the Spring transports once the fix lands, because the fix here is the mcp-core handler change (#800 / #1104), not #1083.
WebMvcStatelessServerTransport.handlePost(and WebFlux likewise) only returns 500 when the handler errors:var resp = this.mcpHandler.handleRequest(ctx, req).block(); // throws only if handler errors return ServerResponse.ok().body(json); // otherwise 200 // catch (Exception e) -> INTERNAL_SERVER_ERROR
Today the handler returns
Mono.error(...)for an unknown method, so.block()throws and you get 500. After #800/#1104 it returnsMono.just(JSONRPCResponse(-32601)), so.block()returns normally and the transport takes theServerResponse.ok()path: HTTP 200 with a-32601body, on all three stateless transports. Since that mcp-core change lives below the transport, the Spring ones need no change of their own for the 500.The 404 is a separate, optional improvement (200 +
-32601is already enough for the OpenAI connector to fall back toinitialize), so a Spring-transport PR would be for the status nicety, not to stop the 500.- added a commit that references this issue
on Aug 26, 2026 Thanks for your reports.
Closed through #1104.We won't implement HTTP 404 as part of this, because it's a 2026-07-28 concern, and nothing mandates 404 in 2025-11-25. I'd rather avoid introducing HTTP behavioral changes in this line.
@Kehrlann do you know when the new version will be released? Thanks!
@JHTosas we're currently working in the design phase. Unsure when it will land, but we're hoping to get the first milestone out in September.
Summary
The
server/discover→ HTTP 500 regression (unknown JSON-RPC method throws instead of returning-32601 Method not found) currently has no remedy for users on the pre-2.0 release lines. The known fixes all target 2.0.x:server/discoverrequests" — open, against 2.0.0; PR fix: return HTTP 404 for METHOD_NOT_FOUND in stateless transport (#1072) #1083 fixes the 2.0.x stateless transport.This issue asks for the fix to also be made available to users still on
0.x/1.x.Why this matters for pre-2.0 users
OpenAI's hosted MCP connector now sends
server/discoverduring its handshake (beforetools/list). On the pre-2.0 SDK the stateless transport responds:OpenAI surfaces that 500 as HTTP 424
external_connector_error, which aborts the entire response — even for a plain "hi" that needs no tool call. In practice this takes an MCP server completely offline for the OpenAI Responses API connector the moment the client starts probing, with no application-side cause. The documented backward-compat behavior is to return-32601so the client falls back to the legacyinitializeflow, and that fallback lives in the SDK's request handling, not in application code — so downstream apps cannot fix it without patching or replacing the SDK.The only forward path today is upgrading to 2.0.x. For Spring AI consumers that is not a version bump:
spring-ai2.x requires Spring Boot 4 / Spring Framework 7, a framework-wide migration. Concretely, we are onspring-ai 1.1.4(MCP Java SDK0.17.0) on Spring Boot 3.x, and a trial bump tospring-ai2.0 compiles and passes unit tests but fails to boot (NoClassDefFoundError: org.springframework.core.Nullness, a Framework 7 class). So a spec-compatibility regression triggered by a client-side change is effectively gating a large, unrelated framework migration.The ask
Either of the following would resolve it for pre-2.0 users:
METHOD_NOT_FOUND/-32601handling to a maintained pre-2.0 line and cut a patch release. This is consistent with lines the project already maintains —0.18.3,1.0.2, and1.1.3all shipped in May–June 2026, so this is not asking to revive an EOL branch.server/discover) return-32601 Method not found/ a non-500 without upgrading. Consumers are currently doing this ad hoc with a servlet filter in front of the SDK; a documented, blessed pattern would be preferable to everyone reinventing it.Environment
0.17.0(viaspring-ai1.1.4)2026-07-28References