modelcontextprotocol / modelcontextprotocol/java-sdk
Allow disabling `structuredContent` duplication in McpAsyncServer
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 3.7k
- Forks
- 1.1k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 9
Description
Expected Behavior
Make io.modelcontextprotocol.server.McpAsyncServer.StructuredOutputCallToolHandler configurable to allow users to decide whether they want to duplicate the structuredContent in the content property.
This configuration could be introduced via a bean or another appropriate mechanism.
A possible solution implementation might look like this:
@Override
public Mono<CallToolResult> apply(McpAsyncServerExchange exchange, McpSchema.CallToolRequest request) {
return this.delegateCallToolResult.apply(exchange, request).map(result -> {
// Skipping some code for brevity
if (Utils.isEmpty(result.content()) && keepCompatibility()) { // <-- HERE keepCompatibility() METHOD IS NEW
// For backwards compatibility, a tool that returns structured
// content SHOULD also return functionally equivalent unstructured
// content. (For example, serialized JSON can be returned in a
// TextContent block.)
// https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content
return CallToolResult.builder()
.content(List.of(new McpSchema.TextContent(validation.jsonStructuredOutput())))
.isError(result.isError())
.structuredContent(result.structuredContent())
.build();
}
return result;
});
}
private boolean keepCompatibility() {
// Provide a way for users to specify whether to keep compatibility or not
}
Current Behavior
Currently, StructuredOutputCallToolHandler always duplicates structuredContent into the content property. This behavior is not mandated by the MCP specification.
Context
MCP tool users may be dissatisfied receiving duplicate content because:
- It causes unnecessary network traffic.
- It reduces performance.
- Most importantly, it consumes unnecessary space in the LLM context window on the client side.
There is no current way to prevent StructuredOutputCallToolHandler#apply() from copying structuredContent into content because the StructuredOutputCallToolHandler class is private and cannot be extended or customized externally.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading McpAsyncServer.StructuredOutputCallToolHandler and its apply() entry point, focusing on where structuredContent is copied into content. Determine the appropriate configuration mechanism and verify that users can enable or disable duplication while preserving the existing default behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100