Skip to content

Commit 855bb6e

Browse files
committed
test: cover HTTP error branch for notifications
Add test for the case where a notification receives an HTTP error response, covering the branch where `isinstance(message, JSONRPCRequest)` is False in the `>= 400` handler. This fixes the coverage gap that caused CI to fail with 99.99% < 100%.
1 parent 032c187 commit 855bb6e

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

tests/client/test_notification_response.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ async def test_unexpected_content_type_sends_jsonrpc_error() -> None:
116116
await session.list_tools()
117117

118118

119-
def _create_http_error_app(error_status: int) -> Starlette:
119+
def _create_http_error_app(error_status: int, *, error_on_notifications: bool = False) -> Starlette:
120120
"""Create a server that returns an HTTP error for non-init requests."""
121121

122122
async def handle_mcp_request(request: Request) -> Response:
@@ -127,6 +127,8 @@ async def handle_mcp_request(request: Request) -> Response:
127127
return _init_json_response(data)
128128

129129
if "id" not in data:
130+
if error_on_notifications:
131+
return Response(status_code=error_status)
130132
return Response(status_code=202)
131133

132134
return Response(status_code=error_status)
@@ -150,6 +152,22 @@ async def test_http_error_status_sends_jsonrpc_error() -> None:
150152
await session.list_tools()
151153

152154

155+
async def test_http_error_on_notification_does_not_hang() -> None:
156+
"""Verify HTTP errors on notifications are silently ignored.
157+
158+
When a notification gets an HTTP error, there is no pending request to
159+
unblock, so the client should just return without sending a JSONRPCError.
160+
"""
161+
app = _create_http_error_app(500, error_on_notifications=True)
162+
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app)) as client:
163+
async with streamable_http_client("http://localhost/mcp", http_client=client) as (read_stream, write_stream):
164+
async with ClientSession(read_stream, write_stream) as session:
165+
await session.initialize()
166+
167+
# Should not raise or hang — the error is silently ignored for notifications
168+
await session.send_notification(RootsListChangedNotification(method="notifications/roots/list_changed"))
169+
170+
153171
def _create_invalid_json_response_app() -> Starlette:
154172
"""Create a server that returns invalid JSON for requests."""
155173

0 commit comments

Comments
 (0)