fix(mcp): harden malformed transport error bodies
All checks were successful
Build and publish Docker image / Build and push CPU image (push) Successful in 2m16s
Build and publish Docker image / Build and push GPU image (push) Successful in 3m4s

- 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
This commit is contained in:
moze
2026-05-06 09:18:46 +02:00
parent e54e1dd33b
commit bfb6bb5e8c

View File

@@ -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.
*
* <p>{@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 {}
}