The official Java SDK for Model Context Protocol servers and clients. Maintained in collaboration with Spring AI
by modelcontextprotocolJava
Last 12 weeks · 37 commits
5 of 6 standards met
Bug description The client SSE line parser in rejects the standard SSE field, throwing: Per the SSE specification, sets the stream's reconnection time, and unknown fields MUST be ignored (never error the stream). Because of this, the Streamable HTTP client: 1. can error a live SSE stream when the server sends a line, and 2. does not honor the server-provided reconnection delay, reconnecting immediately. This is the MUST-level failure already noted as a known limitation in . Environment java-sdk (2.0.1-SNAPSHOT) Java 17+ Transport: (client), SSE / Streamable HTTP Steps to reproduce Run the official MCP conformance client scenario: Observed: Expected behavior The SSE parser parses/ignores (and any unknown SSE field) without erroring the stream. On reconnection after a drop, the client waits the server-specified interval before reconnecting. Minimal reproducible example Feeding the SSE lines / / / (blank) to the SSE line subscriber currently throws instead of yielding a single event. Proposed scope (two parts) 1. Parser robustness (small, self-contained): parse and ignore unknown fields in . (Implemented locally with unit tests.) 2. Reconnect timing: honor the parsed value before reconnecting in / . This touches the SPI, so I'd like to confirm the preferred approach before opening a PR. The related SHOULD warning appears covered by #830, so I would keep it out of scope here. Happy to open a PR for part 1 immediately and follow up on part 2 per maintainer guidance.
The MCP specification defines as a valid field on every request, including , via the base type: in the Java SDK correctly models this (the field was added in #344). However, / always constructs the request with the 3-arg convenience constructor, hardwiring to . There is no API to populate it. Impact Servers that rely on of the request will always receive metadata when called from a Java client, even though the spec explicitly allows it. This is inconsistent with , where is fully caller-controlled. Workaround (current) The only workaround is to wrap the and intercept the outgoing in , rebuilding it with populated. This works but couples application code to internal wire-format details (, record structure) that should be opaque to callers. Proposed solution Expose on the builder, consistent with the pattern used in PR #906 for paginated list methods: Related #344 — added field to classes (schema layer, no client API) #907 / PR #906 — added to paginated list client methods (, etc.) MCP spec — General fields: MCP spec schema (2025-11-25)
This issue is closely related to #273 and could be considered as a follow up to that, but I decided to split it for convenience and readability. Consider an MCP server written with this SDK and using the StreamableHttp transport. We deploy two replicas ( and ) of this server, with a load balancer in front. 1. A new client application initiates a session by sending an message, followed by a notifications. 2. Let's say that the Load Balancer routed both messages to replica 3. As a result, replica generated a new session which Id is communicated back to the client 4. Replica now has an instance properly initialized with all the necessary client information Problem: 1. Next the client sends a message with the obtain sessionId, but this time the load balancer routes the message to replica 2. Even though I believe it should be the server's responsibility to share the session id across replicas, the instance that lives in replica has never received (and will never receive) the initialize message and notifications 3. Although it's possible to distribute all that state and that handshake in replica (I actually did it), I think this SDK should have an OOTB support for that, or at the very least, SessionFactory methods that make it easier to generate "ready to use" Sessions based on previous initializations.
Implemented SSE resumability/redelivery support for Streamable HTTP by introducing an event-store abstraction, adding in-memory event persistence/replay, wiring Last-Event-ID handling through server session/transport layers, and adding comprehensive unit/integration tests. I haven't discussed this PR enough, so I haven't created enough Java doc documentation and tests. If there's a chance this PR will be merged, I'll try to improve it. Motivation and Context Implementation of MCP documentation. How Has This Been Tested? I worte some tests, and also i play it on my device. Breaking Changes nop Types of changes [ ] Bug fix (non-breaking change which fixes an issue) [x] New feature (non-breaking change which adds functionality) [ ] Breaking change (fix or feature that would cause existing functionality to change) [ ] Documentation update Checklist [x] I have read the MCP Documentation [x] My code follows the repository's style guidelines [x] New and existing tests pass locally [x] I have added appropriate error handling [ ] I have added or updated documentation as needed Additional context
Repository: modelcontextprotocol/java-sdk. Description: The official Java SDK for Model Context Protocol servers and clients. Maintained in collaboration with Spring AI Stars: 3506, Forks: 911. Primary language: Java. Languages: Java (100%). License: MIT. Homepage: https://java.sdk.modelcontextprotocol.io/latest/ Latest release: v2.0.0 (2w ago). Open PRs: 100, open issues: 173. Last activity: 1d ago. Community health: 87%. Top contributors: tzolov, chemicL, Kehrlann, markpollack, LucaButBoring, sdelamo, CrazyHZM, jitokim, quaff, codeboyzhou and others.