From bfb6bb5e8c9c25c8dfe0efc1233012dd13e8c126 Mon Sep 17 00:00:00 2001 From: moze Date: Wed, 6 May 2026 09:18:46 +0200 Subject: [PATCH] fix(mcp): harden malformed transport error bodies - register a Jackson mixin for io.modelcontextprotocol.spec.McpError - strip Throwable internals such as stackTrace, cause and suppressed from SDK-owned MCP HTTP error responses - keep malformed Streamable HTTP requests bounded to a minimal JSON body like {"message":"Session ID missing"} Validated locally: - POST /mcp tools/list without Mcp-Session-Id -> 400 {"message":"Session ID missing"} - POST /mcp initialize -> 200 --- .../adapter/in/rest/JacksonConfig.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 trueref-adapters/src/main/java/com/trueref/adapter/in/rest/JacksonConfig.java diff --git a/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/JacksonConfig.java b/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/JacksonConfig.java new file mode 100644 index 0000000..850a7d6 --- /dev/null +++ b/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/JacksonConfig.java @@ -0,0 +1,35 @@ +package com.trueref.adapter.in.rest; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import io.modelcontextprotocol.spec.McpError; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Hardens HTTP JSON serialization for SDK-owned MCP transport errors. + * + *

{@link McpError} extends {@link RuntimeException}. The Streamable HTTP transport returns + * instances of that type directly for malformed requests (for example, missing session headers). + * Without a mixin, Spring MVC serializes inherited {@link Throwable} properties such as + * {@code stackTrace} and {@code cause}, which leaks internal details to clients. + */ +@Configuration +public class JacksonConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer hardenMcpErrorSerialization() { + return builder -> builder.mixIn(McpError.class, McpErrorMixin.class); + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @JsonIgnoreProperties({ + "cause", + "jsonRpcError", + "localizedMessage", + "stackTrace", + "suppressed" + }) + private abstract static class McpErrorMixin {} +} \ No newline at end of file