FIX: Ensure ASGI Compliance in mcpm.router.app.py SSE Handling
#163
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR addresses potential ASGI compliance issues in
mcpm.router.app.pywhen it's run as a standalone ASGI application, specifically concerning its SSE (Server-Sent Events) route handling. This complements the fixes made separately formcpm.router.transport.py.Problem:
If
mcpm.router.app.pyis used to serve the MCPM router directly, its SSE endpoint (/sse) needed to ensure full ASGI compliance to preventTypeError: 'NoneType' object is not callableorRuntimeError: No response returned.issues, similar to those observed in other parts of the MCPM routing logic. Specifically, the SSE handler could implicitly returnNoneupon normal stream completion.Solution:
The
mcpm.router.app.pyhas been updated as follows:MCPRouterinstance, andRouterSseTransportinstance for clarity when run directly.NoOpsResponseClass: ANoOpsResponseclass (returning HTTP 204) has been included. This is used as a compliant placeholder response when an SSE stream handler concludes but Starlette requires aResponseobject to be returned.handle_sse:handle_ssefunction is implemented for the/sseroute.try...finallyblock to ensureNoOpsResponse()is always returned upon completion, satisfying Starlette's requirements.while not await request.is_disconnected(): await asyncio.sleep(0.1)loop has been added within thetryblock. This ensures the handler remains active and correctly manages the SSE connection lifecycle until the client explicitly disconnects.asyncioand variousstarlettecomponents have been added to support these changes.Impact:
These changes ensure that if
mcpm.router.app.pyis run as the main application, its/sseendpoint is stable, robust, and adheres to ASGI specifications. This prevents unexpected errors and contributes to the overall reliability of the MCPM server.Context:
This PR builds upon the fixes in commit
27dc4d6(which addressedtransport.py). The related ASGI compliance formcpm.router.router.py(specificallyhandle_sseinget_sse_server_app) was already addressed inupstream/mainvia commit076a6bf.