Skip to content

FastMCP: streamable_http_app() silently breaks when BaseHTTPMiddleware is added #2702

Description

@hognek

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 (Kludex/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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Nice to haves, rare edge casesbugSomething isn't workingneeds reproneeds additional information to be able to reproduce bugpotentially closeBot recommends closing — needs maintainer review

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions