The official Java SDK for Model Context Protocol servers and clients. Maintained in collaboration with Spring AI
by modelcontextprotocolLast 12 weeks · 68 commits
5 of 6 standards met
Expected Behavior An opt-in configuration to return for JSON-RPC requests within the Streamable HTTP transport, even with active sessions. Example: When enabled, for would buffer the response from and return it as instead of opening an SSE stream. Server-initiated notifications would go through the standalone SSE stream (GET on the same endpoint, as defined in the Streamable HTTP spec). All other official MCP SDKs already support this as an opt-in option: Current Behavior In , session-bound messages always get : There is no way to get for session-bound requests. The request (line 461) and (line 173) already return - so the pattern exists in the codebase. Context The MCP Streamable HTTP spec (2025-06-18, §2.1.5) states: "If the input is a JSON-RPC request, the server MUST either return [...] or , to return one JSON object." This means session management does not require SSE for every response. There are scenarios where a server benefits from sessions (capability negotiation, logging, server-initiated notifications via GET) but its tool handlers produce simple single-message responses that don't need SSE framing. The existing mode () does return , but it removes session management entirely - no server-to-client notifications, no sampling, no capability tracking. This feature request is about supporting responses within** the Streamable transport, with sessions, as the spec allows and as the other SDKs already implement. In local benchmarks comparing MCP server implementations across different SDKs, we observed that switching from SSE-only to JSON responses for simple tool calls (single request-response, no intermediate notifications) resulted in significant performance improvements, primarily due to eliminating chunked transfer encoding, lifecycle overhead, and SSE framing/parsing on both server and client sides. Would it make sense to add this? Happy to contribute a PR if the maintainers agree.
I had mentioned this before in https://github.com/modelcontextprotocol/java-sdk/issues/562 but it seems that it wasn't addressed. mcp-spring-webmvc-0.18.1.jar has io.modelcontextprotocol.server.transport package and mcp-core-1.0.0.jar also has io.modelcontextprotocol.server.transport package In my particular application I need both transports so I am currently forced to copy the source of one of the transports into my code base which is not at all ideal. Ideally if a class is in a different jar it should have a different package to support osgi constructs. i.e: one of them should be changed to be io.modelcontextprotocol.server.webmvc.transport or io.modelcontextprotocol.server.core.transport
Repository: modelcontextprotocol/java-sdk. Description: The official Java SDK for Model Context Protocol servers and clients. Maintained in collaboration with Spring AI Stars: 3225, Forks: 830. Primary language: Java. Languages: Java (100%). License: MIT. Homepage: https://java.sdk.modelcontextprotocol.io/latest/ Latest release: v1.0.0 (1w ago). Open PRs: 100, open issues: 155. Last activity: 12h ago. Community health: 87%. Top contributors: tzolov, chemicL, Kehrlann, markpollack, LucaButBoring, sdelamo, CrazyHZM, jitokim, quaff, codeboyzhou and others.
Java
When building CallToolResult for tools that declare an outputSchema, the SDK 0.17.2 requires structuredContent to be included in the response. However, there is no clean public API to check whether a McpSchema.Tool has an outputSchema set. Currently, we are forced to use Java reflection to access the outputSchema field: This approach is: Fragile — breaks if the field is renamed or the class structure changes Incompatible with module system — setAccessible(true) may fail under strict Java module rules (Java 17+) Not idiomatic — McpSchema.Tool is a record, so it should already have an outputSchema() accessor Expected Behavior: McpSchema.Tool should expose a public outputSchema() method (or it already does as a record accessor, but it returns Map which may be null). The SDK should clearly document: How to check if a tool has an outputSchema Whether structuredContent is mandatory when outputSchema is present Provide a utility or builder pattern that auto-handles the structured vs text content decision Suggested Fix:** If Tool is a record, simply use tool.outputSchema() — document this clearly. If it's not exposed, add a public getter.
The Java MCP SDK throws an McpError: Invalid SSE response when receiving SSE comment lines (lines starting with :), which are valid per the SSE specification. This causes initialization failures with MCP servers that send keep-alive or ping comments. Environment SDK Version: Java SDK (latest) Protocol Version: 2025-03-26 Java Version: 17+ Affected Server: Tavily MCP Server (https://mcp.tavily.com/mcp/) Steps to Reproduce: String url = "https://mcp.tavily.com/mcp/"; McpClientTransport transport = HttpClientStreamableHttpTransport.builder(url).build(); SyncSpec clientBuilder = McpClient.sync(transport); McpSyncClient client = clientBuilder.build(); // This will fail during initialization client.initialize(); Symptoms** Initial Symptom (with default/short timeout) The initialization hangs and eventually times out: _INFO io.modelcontextprotocol.client.LifecycleInitializer -- Server response with Protocol: 2025-03-26, Capabilities: ServerCapabilities[...], Info: Implementation[name=tavily-mcp, title=null, version=1.17.0] and Instructions null WARN io.modelcontextprotocol.client.LifecycleInitializer -- Failed to initialize java.util.concurrent.TimeoutException: Did not observe any item or terminal signal within 3000ms in 'map' (and no fallback has been configured)_ This timeout occurs because the SSE parsing is failing silently in the background, preventing the initialization from completing. Root Cause Revealed (with increased timeout ~300 seconds) When the timeout is increased significantly, the actual error becomes visible: WARN io.modelcontextprotocol.client.LifecycleInitializer -- Handling exception _io.modelcontextprotocol.spec.McpError: Invalid SSE response. Status code: 200 Line: : ping - 2025-11-20 17:27:30.586492+00:00 at io.modelcontextprotocol.client.transport.ResponseSubscribers$SseLineSubscriber.hookOnNext(ResponseSubscribers.java:173)_
Bug description In version 0.12, there was a single "mcp" jar which happens to be a valid OSGi bundle having a valid OSGi manifest. Its dependencies all happen to be OSGi bundles as well. So, mcp and all its dependencies have been loading in OSGi without issue. In version 0.13, the "mcp" jar has been replaced with "mcp-core" and "mcp-json-jackson2". Although "mcp-core" is still an OSGi bundle, "mcp-json-jackson2" is not. Environment I have been using an Apache Felix Servlet Bridge setup but the OSGi container shouldn't matter. Steps to reproduce Building an McpServer from an OSGi container results in the following: Expected behavior The "mcp-json-jackson2" jar should have an OSGi manifest. The mcp bundles should have proper "Require-Capability" and "Provide-Capability" headers to support the OSGi Service Loader mechanism, like what's implemented by Apache SPI Fly: https://aries.apache.org/documentation/modules/spi-fly.html#specconf Minimal Complete Reproducible example The original Servlet Bridge example is here: https://github.com/apache/felix-dev/tree/8c10c79ff48b6a8938e9fc8088964a2facb42da1/http/samples/bridge You would need to add your own OSGi bundle with a bundle Activator that starts an MCP server and registers its transport using the OSGi HTTP service. Some detail: https://github.com/apache/felix-dev/blob/master/http/README.md#using-the-httpservice Workaround The workaround is to wrap the "mcp-json-jackson2" jar inside of a custom OSGi bundle and to explicitly call "Builder.jsonMapper" and "jsonSchemaValidator" methods on everything to avoid the broken service lookup.