modelcontextprotocol / modelcontextprotocol/python-sdk

FastMCP: streamable_http_app() silently breaks when BaseHTTPMiddleware is added

Aperta
#2,702 5 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

bug needs repro P3 potentially close
Lingua principale
Python
Stelle
24.3k
Fork
4k
Merge medio
1g 1h
PR unite (30g)
31

Descrizione

Description

Adding a Starlette BaseHTTPMiddleware (e.g., for auth) to FastMCP.streamable_http_app() silently breaks the MCP server. Every request crashes with ClosedResourceError — the client sees "peer closed connection without sending complete message body."

Reproduction

from mcp.server.fastmcp import FastMCP
from starlette.middleware.base import BaseHTTPMiddleware

mcp = FastMCP("test")

# Any BaseHTTPMiddleware — even a no-op passthrough
class AuthMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        return await call_next(request)

mcp.streamable_http_app().add_middleware(BaseHTTPMiddleware, dispatch=AuthMiddleware)

Run the server, send any MCP initialize request → ClosedResourceError.

Root cause

BaseHTTPMiddleware wraps the ASGI receive/send channels in a way incompatible with SSE streaming. This is a known Starlette limitation (encode/starlette#919), but FastMCP users hit it naturally when they reach for the obvious auth pattern.

Expected behavior

At minimum: warn at startup when a BaseHTTPMiddleware subclass is detected on a streamable HTTP app. Ideally: document prominently that users should use FastMCP's own Middleware class (fastmcp.server.middleware.Middleware) instead of Starlette's BaseHTTPMiddleware.

Workaround (raw ASGI middleware)

from starlette.types import ASGIApp, Receive, Scope, Send

class RawAuthMiddleware:
    def __init__(self, app: ASGIApp):
        self.app = app

    async def __call__(self, scope: Scope, receive: Receive, send: Send):
        # auth check here — read headers from scope
        await self.app(scope, receive, send)

mcp.streamable_http_app().add_middleware(RawAuthMiddleware)

Environment

  • mcp / FastMCP from modelcontextprotocol/python-sdk
  • Starlette (any version — this is architectural, not a regression)
  • Python 3.12

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 FastMCP.streamable_http_app() e ispeziona come viene registrato il middleware intorno all’applicazione HTTP streamable. Riproduci il problema con l’esempio no-op di BaseHTTPMiddleware, quindi determina come dovrebbero funzionare il rilevamento all’avvio e il comportamento degli avvisi. Il lavoro è completato quando il problema viene segnalato chiaramente e gli utenti vengono indirizzati verso il Middleware di FastMCP o la soluzione alternativa ASGI grezza.

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

Valutazione

Stack tecnologico
python
Ambito
backend-api-design
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
64/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.