Upstream: a cancellation defect that kills DataHub MCP sessions
Logging work that happened alongside this project and affects every DataHub MCP user, not only this one.
While measuring concurrent writers through mcp-server-datahub, sessions were dying rather than individual requests failing. The cause is in MCP Python SDK 1.x: when a client cancels an in-flight request, the server raises AssertionError: Request already responded to and the transport goes down with it.
With an async def handler that is a narrow race. With a def handler it is deterministic — the cancel scope has no checkpoint inside the handler, so the cancellation branch can never fire and the normal-completion path is always taken. mcp-server-datahub 0.6.0 has all-synchronous handlers, so every cancellation of an in-flight request ends in the assert.
Measured, four workers writing concurrently through separate stdio sessions, each write confirmed by a bounded read-after-write poll:
- cancelling on the wire: 5 of 18 writes lost, backend held 4 records
- bounding the caller's wait only: 1 of 18 writes lost, backend held 9 records
The losses concentrate in whichever worker happens to time out rather than spreading evenly — which is what distinguishes one failed request from progressive session-wide failure.
Guarding respond() alone turned out to be insufficient: cancel() is a second terminal path with the same duplicate-transition problem.
unpatched 3 of 3 fail
guard in respond() only repeated cancellation still fails
guard in respond() and cancel() 3 of 3 pass
End to end against a real stdio server with the guard in place: request 1 succeeds, request 2 times out as expected, request 3 succeeds — the session survives. Unpatched, request 3 is MCPError: Connection closed.
Discussion, repro and patch: modelcontextprotocol/python-sdk#2416 (labelled fix proposed). The fix applies to the 1.x line; main is now v2.0.0 and has been refactored past this code path.
Log in or sign up for Devpost to join the conversation.