Skip to content

Wire mcpServerJsonMapper into stateless MCP server builders#5895

Open
PVPankaj wants to merge 1 commit intospring-projects:mainfrom
PVPankaj:gh-5894-stateless-jsonmapper
Open

Wire mcpServerJsonMapper into stateless MCP server builders#5895
PVPankaj wants to merge 1 commit intospring-projects:mainfrom
PVPankaj:gh-5894-stateless-jsonmapper

Conversation

@PVPankaj
Copy link
Copy Markdown

@PVPankaj PVPankaj commented Apr 28, 2026

McpServerStatelessAutoConfiguration builds the stateless sync and async McpServer without calling .jsonMapper(...). This causes the handler stage (e.g. convertValue(req, InitializeRequest.class)) to fall back to McpJsonMapper.getDefault() - a strict vanilla ObjectMapper with FAIL_ON_UNKNOWN_PROPERTIES=true.

Meanwhile, the transport layer correctly uses the lenient mcpServerJsonMapper bean. So we end up with two different mappers at different stages:

  • Stage 1 (transport) - JSON-RPC envelope -> JSONRPCRequest: lenient mapper ✅
  • Stage 2 (handler) - params -> InitializeRequest: strict default ❌

Any MCP client implementing the 2025-11-25 spec (e.g. Codex) sends fields like capabilities.elicitation.form that the current SDK records don't model yet, so the strict mapper rejects them and the initialize handshake fails with:

Unrecognized field "form" (class ...ClientCapabilities$Elicitation),
not marked as ignorable

This change adds @Qualifier("mcpServerJsonMapper") JsonMapper to both mcpStatelessSyncServer and mcpStatelessAsyncServer bean methods and wires it via .jsonMapper(new JacksonMcpJsonMapper(...)) on the builder - the same pattern already used by McpServerAutoConfiguration for the stdio transport.

Closes gh-5894

McpServerStatelessAutoConfiguration did not pass the configured
mcpServerJsonMapper to the McpServer builder, causing the handler
stage to fall back to a strict default ObjectMapper. This rejected
unknown fields from MCP clients implementing the 2025-11-25 spec
(e.g. Codex), breaking the initialize handshake.

Add @qualifier("mcpServerJsonMapper") JsonMapper parameter and
.jsonMapper(new JacksonMcpJsonMapper(...)) call to both the sync
and async stateless server bean methods, consistent with how the
stdio transport is already wired in McpServerAutoConfiguration.

Closes spring-projectsgh-5894

Signed-off-by: Pankaj <pankajvpande@gmail.com>
@PVPankaj PVPankaj force-pushed the gh-5894-stateless-jsonmapper branch from ec0f397 to 567ee2d Compare April 28, 2026 01:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP server: McpServerStatelessAutoConfiguration does not pass mcpServerObjectMapper into McpServer.sync().jsonMapper()

2 participants