modelcontextprotocol / modelcontextprotocol/python-sdk

Streamable HTTP client stays closed after an interrupted response and raises ExceptionGroup on cleanup

Aperta
#3,522 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

v1 v2
Lingua principale
Python
Stelle
24.3k
Fork
4k
Merge medio
1g 1h
PR unite (30g)
31

Descrizione

Description

With the current 2.x release, one interrupted Streamable HTTP tool response permanently closes the Python client session. The failing request is reported, but a subsequent normal request on the same client fails with MCPError: Connection closed. Exiting streamable_http_client(...) then raises an unhandled ExceptionGroup from its background task group.

The same MCP server remains healthy. Under the identical sequence, @modelcontextprotocol/sdk@1.30.0 reports the interrupted request and successfully completes the next ping on the same client.

Expected behavior

The interrupted request should fail, while a subsequent request should be able to use a fresh HTTP connection and succeed. Transport cleanup should not raise an additional ExceptionGroup.

Actual behavior
  1. disconnect interrupts its active HTTP response.
  2. Python reports the request failure.
  3. A following ping fails immediately with MCPError: Connection closed.
  4. Context cleanup raises ExceptionGroup: unhandled errors in a TaskGroup whose nested cause is httpx2.RemoteProtocolError: Server disconnected without sending a response.
Comparison

The official TypeScript client 1.30.0 receives TypeError: fetch failed for the deliberately interrupted request, then successfully sends ping through the same client. This suggests the server remains available and the problem is in Python client recovery/cleanup.

I also searched the existing issues. #3494 concerns a server-side incomplete SSE body during initialize, and #3441 concerns an unresolved 1.x request; neither appears to cover this v2 same-client recovery failure.

Minimal reproduction
# Terminal 1
npx mcp-failure-lab@0.9.0 serve --transport http --host 127.0.0.1 --port 43118 --path /mcp

# Terminal 2: save as repro.py, then run: python repro.py
import anyio
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client

URL = "http://127.0.0.1:43118/mcp"

async def main():
    try:
        async with streamable_http_client(URL) as streams:
            async with ClientSession(
                streams[0], streams[1], read_timeout_seconds=1.0
            ) as session:
                await session.initialize()
                try:
                    await session.call_tool(
                        "disconnect", {}, read_timeout_seconds=0.6
                    )
                except BaseException as error:
                    print("disconnect:", type(error).__name__, error)

                # Expected: succeeds. Actual: MCPError: Connection closed
                print("ping:", await session.call_tool("ping", {}))
    except BaseException as error:
        # Actual: ExceptionGroup from streamable_http_client cleanup
        print("cleanup:", type(error).__name__, error)

anyio.run(main)
Environment

Python 3.12.14; mcp 2.2.0; macOS arm64. Server: mcp-failure-lab 0.9.0; protocol 2026-07-28.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia dal punto di ingresso streamable_http_client in mcp.client.streamable_http ed esegui il repro.py fornito contro mcp-failure-lab. Traccia in che modo la risposta di disconnessione interrotta influisce sul client e sulla pulizia del gruppo di task; il lavoro è completato quando l’errore di disconnessione viene segnalato, un ping successivo ha esito positivo sullo stesso client e l’uscita dal contesto non solleva alcuna ExceptionGroup.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
api
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Attiva
Chiarezza
Specificata chiaramente
Idoneità per principianti
72/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.