[BUG] Exception occurs during client session disconnection
Describe the bug
When adding a middleware, the following exception always occurs during client session disconnection. While there is no issue with calling the tool, I'm curious if there is a way to prevent this exception from occurring.
[2025-06-13 12:15:28,591][DEBUG][sse_starlette.sse][line=230][49972] - Got event: http.disconnect. Stop streaming.
[2025-06-13 12:15:28,591][DEBUG][root][line=159][49972] - Client session disconnected 04bbc672-f124-4291-b1fa-3b8a923ffe35
ERROR Exception in ASGI application
+ Exception Group Traceback (most recent call last):
| File "C:\...\Lib\site-packages\starlette\_utils.py", line 76, in collapse_excgroups
| yield
| File "C:\...\Lib\site-packages\starlette\middleware\base.py", line 177, in __call__
| async with anyio.create_task_group() as task_group:
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\...\Lib\site-packages\anyio\_backends\_asyncio.py", line 772, in __aexit__
| raise BaseExceptionGroup(
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "C:\...\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 409, in run_asgi
| result = await app( # type: ignore[func-returns-value]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\...\Lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
| return await self.app(scope, receive, send)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "C:\...\Lib\site-packages\fastapi\applications.py", line 1054, in __call__
| await super().__call__(scope, receive, send)
| File "C:\...\Lib\site-packages\starlette\applications.py", line 112, in __call__
| await self.middleware_stack(scope, receive, send)
| File "C:\...\Lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
| raise exc
| File "C:\...\Lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
| await self.app(scope, receive, _send)
| File "C:\...\Lib\site-packages\starlette\middleware\base.py", line 176, in __call__
| with recv_stream, send_stream, collapse_excgroups():
| ^^^^^^^^^^^^^^^^^^^^
| File "C:\...\Lib\contextlib.py", line 158, in __exit__
| self.gen.throw(value)
| File "C:\...\Lib\site-packages\starlette\_utils.py", line 82, in collapse_excgroups
| raise exc
| File "C:\...\Lib\site-packages\starlette\middleware\base.py", line 179, in __call__
| await response(scope, wrapped_receive, send)
| File "C:\...\Lib\site-packages\starlette\middleware\base.py", line 216, in __call__
| async for chunk in self.body_iterator:
| File "C:\...\Lib\site-packages\starlette\middleware\base.py", line 163, in body_stream
| assert message["type"] == "http.response.body"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| AssertionError
+------------------------------------
To Reproduce
- After adding the middleware below to the code, start the server
- Run Cline and connect to the MCP server
- Terminate the Cline (VS Code)
@app.middleware("http")
async def some_middleware(request: Request, call_next):
return await call_next(request)
System Info
fastapi : 0.115.12 fastapi-mcp : 0.3.4 MCP host : Cline (VS Code)
This is also happening here. I commented out all the middleware in my application and it stopped giving this exception.
I had to rewrite my application's middlewares to be in the format of other Starlet middlewares (such as CORSMiddleware).
Previously, I created my middleware inheriting from BaseHTTPMiddleware. Now that I applied the standard, this error stopped happening.
In any case, I believe this error is related to the SSE return of the /mcp path.
I also encounter some problem.
I print message
{'type': 'http.response.body', 'body': b''}
{'type': 'http.response.body', 'body': b'{"message":"Accepted"}'}
{'type': 'http.response.body', 'body': b'{"message":"Accepted"}'}
{'type': 'http.response.body', 'body': b'event: message\r\ndata: {"jsonrpc":"2.0","id":1,"result":{"tools":[]}}\r\n\r\n', 'more_body': True}
{'type': 'http.response.start', 'status': 200, 'headers': [(b'content-length', b'4'), (b'content-type', b'application/json')]}
I noticed that something extra was added to the last line.
Does is still happen in 0.4.0, when using the new HTTP transport?
@shahar4499 I had this problem with middleware (GZipMiddleware) in 0.3.4. After trying 0.4.0 with the new HTTP transport (implementation of Streamable HTTP), there are now no more problems with middleware in my side.