modelcontextprotocol / modelcontextprotocol/java-sdk
SSE client rejects valid `retry:` field and ignores reconnection timing (Streamable HTTP)
还没有人认领这个 Issue。
- 主要语言
- Java
- 星标
- 3.7k
- 派生
- 1.1k
- 平均合并
- 1 天 15 小时
- 30 天内合并 PR
- 9
描述
Bug description
The client SSE line parser in ResponseSubscribers rejects the standard SSE retry: field, throwing:
io.modelcontextprotocol.spec.McpTransportException: Invalid SSE response. Status code: 200 Line: retry: 500
Per the SSE specification, retry: sets the stream's reconnection time, and unknown fields MUST be ignored (never error the stream). Because of this, the Streamable HTTP client:
- can error a live SSE stream when the server sends a
retry:line, and - does not honor the server-provided reconnection delay, reconnecting immediately.
This is the MUST-level client-sse-retry-timing failure already noted as a known limitation in conformance-tests/VALIDATION_RESULTS.md.
Environment
- java-sdk
main(2.0.1-SNAPSHOT) - Java 17+
- Transport:
HttpClientStreamableHttpTransport(client), SSE / Streamable HTTP
Steps to reproduce
Run the official MCP conformance sse-retry client scenario:
./mvnw clean package -DskipTests -pl conformance-tests/client-jdk-http-client -am
npx -y @modelcontextprotocol/conformance client \
--command "java -jar conformance-tests/client-jdk-http-client/target/client-jdk-http-client-2.0.1-SNAPSHOT.jar" \
--scenario sse-retry
Observed:
Error: Invalid SSE response. Status code: 200 Line: retry: 500
[client-sse-retry-timing ] FAILURE Client MUST respect the retry field (reconnected ~0ms instead of 500ms)
[client-sse-last-event-id] WARNING Client SHOULD send Last-Event-ID on reconnection
OVERALL: FAILED
Expected behavior
- The SSE parser parses/ignores
retry:(and any unknown SSE field) without erroring the stream. - On reconnection after a drop, the client waits the server-specified
retryinterval before reconnecting.
Minimal reproducible example
Feeding the SSE lines id: e1 / retry: 500 / data: hello / (blank) to the SSE line subscriber currently throws McpTransportException instead of yielding a single event.
Proposed scope (two parts)
- Parser robustness (small, self-contained): parse
retry:and ignore unknown fields inResponseSubscribers. (Implemented locally with unit tests.) - Reconnect timing: honor the parsed
retryvalue before reconnecting inHttpClientStreamableHttpTransport/DefaultMcpTransportStream. This touches theMcpTransportStreamSPI, so I'd like to confirm the preferred approach before opening a PR.
The related Last-Event-ID 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.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 ResponseSubscribers 中的 SSE 行订阅者及其单元测试开始,复现最小的 retry: 500 情况。然后跟踪通过 HttpClientStreamableHttpTransport 和 DefaultMcpTransportStream 进行的重连处理,包括 McpTransportStream SPI。运行 sse-retry 一致性场景;当 retry 字段解析不再失败,且重连遵循服务器提供的延迟时,即表示完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- java
- 领域
- api, networking
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 45/100