modelcontextprotocol / modelcontextprotocol/java-sdk
SSE client rejects valid `retry:` field and ignores reconnection timing (Streamable HTTP)
まだ誰も着手していません。
- 主要言語
- Java
- スター
- 3.7k
- フォーク
- 1.1k
- 平均マージ
- 1日 15時間
- マージ済み PR(30日)
- 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 にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
ResponseSubscribers の SSE 行サブスクライバーとそのユニットテストから始め、最小限の retry: 500 のケースを再現します。次に、McpTransportStream SPI を含め、HttpClientStreamableHttpTransport と DefaultMcpTransportStream における再接続処理を追跡します。sse-retry 適合シナリオを実行します。retry フィールドのパースが失敗しなくなり、再接続がサーバーから提供された遅延を認識すれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- java
- 領域
- api, networking
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 静か
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 45/100