modelcontextprotocol / modelcontextprotocol/java-sdk

SSE client rejects valid `retry:` field and ignores reconnection timing (Streamable HTTP)

Ouverte
#1,047 2 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

area/client area/transport P2 waiting for user
Langage dominant
Java
Étoiles
3.7k
Forks
1.1k
Merge moyen
1 j 15 h
PR mergées (30 j)
9

Description

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:

  1. can error a live SSE stream when the server sends a retry: line, and
  2. 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 retry interval 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)

  1. Parser robustness (small, self-contained): parse retry: and ignore unknown fields in ResponseSubscribers. (Implemented locally with unit tests.)
  2. Reconnect timing: honor the parsed retry value before reconnecting in HttpClientStreamableHttpTransport / DefaultMcpTransportStream. This touches the McpTransportStream SPI, 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.

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par l’abonné de lignes SSE dans ResponseSubscribers et ses tests unitaires, en reproduisant le cas minimal de retry : 500. Suivez ensuite la gestion de la reconnexion à travers HttpClientStreamableHttpTransport et DefaultMcpTransportStream, y compris le SPI McpTransportStream. Exécutez le scénario de conformité sse-retry ; c’est terminé lorsque les champs de retry n’échouent plus lors de l’analyse et que la reconnexion respecte le délai fourni par le serveur.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
java
Domaine
api, networking
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Calme
Clarté
Plutôt claire
Accessibilité débutants
45/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.