Initial Checks
Description
Every request will try an exception
use _handle_stateless_request > run_stateless_server > http_transport.connect() > for session_message in write_stream_reader
It will go in twice, and an exception(yio.ClosedResourceError) will be thrown when the second request has been closed
Example Code
app = Server("mcp-server")
def main(port: int, transport: str, dev: bool, limit_concurrency: int) -> int:
# Create the session manager with true stateless mode
from starlette.applications import Starlette
from starlette.routing import Mount, Route
session_manager = StreamableHTTPSessionManager(
app=app,
event_store=None,
json_response=True,
stateless=True,
)
@contextlib.asynccontextmanager
async def lifespan(app: Starlette) -> AsyncIterator[None]:
"""Context manager for managing session manager lifecycle."""
async with session_manager.run():
logger.info("Application started with StreamableHTTP session manager!")
try:
yield
finally:
logger.info("Application shutting down...")
async def handle_streamable_http(
scope: Scope, receive: Receive, send: Send
) -> None:
await session_manager.handle_request(scope, receive, send)
starlette_app = Starlette(
debug=dev,
routes=[
Mount("/message", app=handle_streamable_http),
],
lifespan=lifespan,
)
import uvicorn
uvicorn.run(starlette_app, host="0.0.0.0", port=port, http="httptools", limit_concurrency=limit_concurrency)
if __name__ == "__main__":
asyncio.run(main())
view logs:
[2025-07-31 15:10:41,884][MainThread:19320][task_id:mcp.server.streamable_http][streamable_http.py:630][INFO][Terminating session: None]
[2025-07-31 15:10:41,885][MainThread:19320][task_id:mcp.server.streamable_http][streamable_http.py:880][ERROR][Error in message router]
Traceback (most recent call last):
File "d:\project\bpaas\apihub-mcp-server\.venv\Lib\site-packages\mcp\server\streamable_http.py", line 831, in message_router
async for session_message in write_stream_reader:
...<46 lines>...
)
File "d:\project\bpaas\apihub-mcp-server\.venv\Lib\site-packages\anyio\abc\_streams.py", line 35, in __anext__
return await self.receive()
^^^^^^^^^^^^^^^^^^^^
File "d:\project\bpaas\apihub-mcp-server\.venv\Lib\site-packages\anyio\streams\memory.py", line 111, in receive
return self.receive_nowait()
~~~~~~~~~~~~~~~~~~~^^
File "d:\project\bpaas\apihub-mcp-server\.venv\Lib\site-packages\anyio\streams\memory.py", line 93, in receive_nowait
raise ClosedResourceError
anyio.ClosedResourceError
Terminating has already released memory first
debug for : first
debug for : second
And the log shows that Terminating should be executed first, followed by create_task_group
Python & MCP Python SDK
MCP version: 1.12.2
Python:3.13
Initial Checks
Description
Every request will try an exception
use
_handle_stateless_request>run_stateless_server>http_transport.connect()>for session_message in write_stream_readerIt will go in twice, and an exception(yio.ClosedResourceError) will be thrown when the second request has been closed
Example Code
view logs:
Terminating has already released memory first
debug for : first
debug for : second
And the log shows that
Terminatingshould be executed first, followed bycreate_task_groupPython & MCP Python SDK