Skip to content

Commit fa012d4

Browse files
committed
coverage: remove stale no-cover pragmas for in-process transport code
The previous commit migrated test servers from subprocess to in-thread, which means coverage now tracks transport code that was previously invisible. The `# pragma: no cover` markers on these paths are now stale and fail strict-no-cover. Removed function-level pragmas and added targeted `no cover` / `lax no cover` / `no branch` only where specific lines remain unreachable or timing-dependent.
1 parent 5ab3d9b commit fa012d4

File tree

13 files changed

+107
-117
lines changed

13 files changed

+107
-117
lines changed

src/mcp/server/mcpserver/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ def sse_app(
926926

927927
sse = SseServerTransport(message_path, security_settings=transport_security)
928928

929-
async def handle_sse(scope: Scope, receive: Receive, send: Send): # pragma: no cover
929+
async def handle_sse(scope: Scope, receive: Receive, send: Send):
930930
# Add client ID from auth context into request context if available
931931

932932
async with sse.connect_sse(scope, receive, send) as streams:
@@ -998,7 +998,7 @@ async def handle_sse(scope: Scope, receive: Receive, send: Send): # pragma: no
998998
else:
999999
# Auth is disabled, no need for RequireAuthMiddleware
10001000
# Since handle_sse is an ASGI app, we need to create a compatible endpoint
1001-
async def sse_endpoint(request: Request) -> Response: # pragma: no cover
1001+
async def sse_endpoint(request: Request) -> Response:
10021002
# Convert the Starlette request to ASGI parameters
10031003
return await handle_sse(request.scope, request.receive, request._send) # type: ignore[reportPrivateUsage]
10041004

src/mcp/server/session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ async def send_log_message(
222222
related_request_id,
223223
)
224224

225-
async def send_resource_updated(self, uri: str | AnyUrl) -> None: # pragma: no cover
225+
async def send_resource_updated(self, uri: str | AnyUrl) -> None:
226226
"""Send a resource updated notification."""
227227
await self.send_notification(
228228
types.ResourceUpdatedNotification(
@@ -474,7 +474,7 @@ async def send_progress_notification(
474474
related_request_id,
475475
)
476476

477-
async def send_resource_list_changed(self) -> None: # pragma: no cover
477+
async def send_resource_list_changed(self) -> None:
478478
"""Send a resource list changed notification."""
479479
await self.send_notification(types.ResourceListChangedNotification())
480480

src/mcp/server/sse.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ def __init__(self, endpoint: str, security_settings: TransportSecuritySettings |
116116
logger.debug(f"SseServerTransport initialized with endpoint: {endpoint}")
117117

118118
@asynccontextmanager
119-
async def connect_sse(self, scope: Scope, receive: Receive, send: Send): # pragma: no cover
120-
if scope["type"] != "http":
119+
async def connect_sse(self, scope: Scope, receive: Receive, send: Send):
120+
if scope["type"] != "http": # pragma: no cover
121121
logger.error("connect_sse received non-HTTP request")
122122
raise ValueError("connect_sse can only handle HTTP requests")
123123

@@ -201,7 +201,7 @@ async def response_wrapper(scope: Scope, receive: Receive, send: Send):
201201
logger.debug("Yielding read and write streams")
202202
yield (read_stream, write_stream)
203203

204-
async def handle_post_message(self, scope: Scope, receive: Receive, send: Send) -> None: # pragma: no cover
204+
async def handle_post_message(self, scope: Scope, receive: Receive, send: Send) -> None:
205205
logger.debug("Handling POST message")
206206
request = Request(scope, receive)
207207

@@ -211,15 +211,15 @@ async def handle_post_message(self, scope: Scope, receive: Receive, send: Send)
211211
return await error_response(scope, receive, send)
212212

213213
session_id_param = request.query_params.get("session_id")
214-
if session_id_param is None:
214+
if session_id_param is None: # pragma: no cover
215215
logger.warning("Received request without session_id")
216216
response = Response("session_id is required", status_code=400)
217217
return await response(scope, receive, send)
218218

219219
try:
220220
session_id = UUID(hex=session_id_param)
221221
logger.debug(f"Parsed session ID: {session_id}")
222-
except ValueError:
222+
except ValueError: # pragma: no cover
223223
logger.warning(f"Received invalid session ID: {session_id_param}")
224224
response = Response("Invalid session ID", status_code=400)
225225
return await response(scope, receive, send)
@@ -236,7 +236,7 @@ async def handle_post_message(self, scope: Scope, receive: Receive, send: Send)
236236
try:
237237
message = types.jsonrpc_message_adapter.validate_json(body, by_name=False)
238238
logger.debug(f"Validated client message: {message}")
239-
except ValidationError as err:
239+
except ValidationError as err: # pragma: no cover
240240
logger.exception("Failed to parse message")
241241
response = Response("Could not parse message", status_code=400)
242242
await response(scope, receive, send)

src/mcp/server/streamable_http.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def is_terminated(self) -> bool:
177177
"""Check if this transport has been explicitly terminated."""
178178
return self._terminated
179179

180-
def close_sse_stream(self, request_id: RequestId) -> None: # pragma: no cover
180+
def close_sse_stream(self, request_id: RequestId) -> None:
181181
"""Close SSE connection for a specific request without terminating the stream.
182182
183183
This method closes the HTTP connection for the specified request, triggering
@@ -200,12 +200,12 @@ def close_sse_stream(self, request_id: RequestId) -> None: # pragma: no cover
200200
writer.close()
201201

202202
# Also close and remove request streams
203-
if request_id in self._request_streams:
203+
if request_id in self._request_streams: # pragma: no branch
204204
send_stream, receive_stream = self._request_streams.pop(request_id)
205205
send_stream.close()
206206
receive_stream.close()
207207

208-
def close_standalone_sse_stream(self) -> None: # pragma: no cover
208+
def close_standalone_sse_stream(self) -> None:
209209
"""Close the standalone GET SSE stream, triggering client reconnection.
210210
211211
This method closes the HTTP connection for the standalone GET stream used
@@ -240,10 +240,10 @@ def _create_session_message(
240240
# Only provide close callbacks when client supports resumability
241241
if self._event_store and protocol_version >= "2025-11-25":
242242

243-
async def close_stream_callback() -> None: # pragma: no cover
243+
async def close_stream_callback() -> None:
244244
self.close_sse_stream(request_id)
245245

246-
async def close_standalone_stream_callback() -> None: # pragma: no cover
246+
async def close_standalone_stream_callback() -> None:
247247
self.close_standalone_sse_stream()
248248

249249
metadata = ServerMessageMetadata(
@@ -291,7 +291,7 @@ def _create_error_response(
291291
) -> Response:
292292
"""Create an error response with a simple string message."""
293293
response_headers = {"Content-Type": CONTENT_TYPE_JSON}
294-
if headers: # pragma: no cover
294+
if headers:
295295
response_headers.update(headers)
296296

297297
if self.mcp_session_id:
@@ -342,7 +342,7 @@ def _create_event_data(self, event_message: EventMessage) -> dict[str, str]:
342342
}
343343

344344
# If an event ID was provided, include it
345-
if event_message.event_id: # pragma: no cover
345+
if event_message.event_id:
346346
event_data["id"] = event_message.event_id
347347

348348
return event_data
@@ -372,7 +372,7 @@ async def handle_request(self, scope: Scope, receive: Receive, send: Send) -> No
372372
await error_response(scope, receive, send)
373373
return
374374

375-
if self._terminated: # pragma: no cover
375+
if self._terminated:
376376
# If the session has been terminated, return 404 Not Found
377377
response = self._create_error_response(
378378
"Not Found: Session has been terminated",
@@ -387,7 +387,7 @@ async def handle_request(self, scope: Scope, receive: Receive, send: Send) -> No
387387
await self._handle_get_request(request, send)
388388
elif request.method == "DELETE":
389389
await self._handle_delete_request(request, send)
390-
else: # pragma: no cover
390+
else:
391391
await self._handle_unsupported_request(request, send)
392392

393393
def _check_accept_headers(self, request: Request) -> tuple[bool, bool]:
@@ -467,7 +467,7 @@ async def _handle_post_request(self, scope: Scope, request: Request, receive: Re
467467

468468
try:
469469
message = jsonrpc_message_adapter.validate_python(raw_message, by_name=False)
470-
except ValidationError as e: # pragma: no cover
470+
except ValidationError as e:
471471
response = self._create_error_response(
472472
f"Validation error: {str(e)}",
473473
HTTPStatus.BAD_REQUEST,
@@ -493,7 +493,7 @@ async def _handle_post_request(self, scope: Scope, request: Request, receive: Re
493493
)
494494
await response(scope, receive, send)
495495
return
496-
elif not await self._validate_request_headers(request, send): # pragma: no cover
496+
elif not await self._validate_request_headers(request, send):
497497
return
498498

499499
# For notifications and responses only, return 202 Accepted
@@ -659,19 +659,19 @@ async def _handle_get_request(self, request: Request, send: Send) -> None:
659659
# Validate Accept header - must include text/event-stream
660660
_, has_sse = self._check_accept_headers(request)
661661

662-
if not has_sse: # pragma: no cover
662+
if not has_sse:
663663
response = self._create_error_response(
664664
"Not Acceptable: Client must accept text/event-stream",
665665
HTTPStatus.NOT_ACCEPTABLE,
666666
)
667667
await response(request.scope, request.receive, send)
668668
return
669669

670-
if not await self._validate_request_headers(request, send): # pragma: no cover
670+
if not await self._validate_request_headers(request, send):
671671
return
672672

673673
# Handle resumability: check for Last-Event-ID header
674-
if last_event_id := request.headers.get(LAST_EVENT_ID_HEADER): # pragma: no cover
674+
if last_event_id := request.headers.get(LAST_EVENT_ID_HEADER):
675675
await self._replay_events(last_event_id, request, send)
676676
return
677677

@@ -681,11 +681,11 @@ async def _handle_get_request(self, request: Request, send: Send) -> None:
681681
"Content-Type": CONTENT_TYPE_SSE,
682682
}
683683

684-
if self.mcp_session_id:
684+
if self.mcp_session_id: # pragma: no branch
685685
headers[MCP_SESSION_ID_HEADER] = self.mcp_session_id
686686

687687
# Check if we already have an active GET stream
688-
if GET_STREAM_KEY in self._request_streams: # pragma: no cover
688+
if GET_STREAM_KEY in self._request_streams:
689689
response = self._create_error_response(
690690
"Conflict: Only one SSE stream is allowed per session",
691691
HTTPStatus.CONFLICT,
@@ -714,7 +714,7 @@ async def standalone_sse_writer():
714714
# Send the message via SSE
715715
event_data = self._create_event_data(event_message)
716716
await sse_stream_writer.send(event_data)
717-
except Exception: # pragma: no cover
717+
except Exception: # pragma: lax no cover
718718
logger.exception("Error in standalone SSE writer")
719719
finally:
720720
logger.debug("Closing standalone SSE writer")
@@ -791,13 +791,13 @@ async def terminate(self) -> None:
791791
# During cleanup, we catch all exceptions since streams might be in various states
792792
logger.debug(f"Error closing streams: {e}")
793793

794-
async def _handle_unsupported_request(self, request: Request, send: Send) -> None: # pragma: no cover
794+
async def _handle_unsupported_request(self, request: Request, send: Send) -> None:
795795
"""Handle unsupported HTTP methods."""
796796
headers = {
797797
"Content-Type": CONTENT_TYPE_JSON,
798798
"Allow": "GET, POST, DELETE",
799799
}
800-
if self.mcp_session_id:
800+
if self.mcp_session_id: # pragma: no branch
801801
headers[MCP_SESSION_ID_HEADER] = self.mcp_session_id
802802

803803
response = self._create_error_response(
@@ -824,7 +824,7 @@ async def _validate_session(self, request: Request, send: Send) -> bool:
824824
request_session_id = self._get_session_id(request)
825825

826826
# If no session ID provided but required, return error
827-
if not request_session_id: # pragma: no cover
827+
if not request_session_id:
828828
response = self._create_error_response(
829829
"Bad Request: Missing session ID",
830830
HTTPStatus.BAD_REQUEST,
@@ -849,11 +849,11 @@ async def _validate_protocol_version(self, request: Request, send: Send) -> bool
849849
protocol_version = request.headers.get(MCP_PROTOCOL_VERSION_HEADER)
850850

851851
# If no protocol version provided, assume default version
852-
if protocol_version is None: # pragma: no cover
852+
if protocol_version is None:
853853
protocol_version = DEFAULT_NEGOTIATED_VERSION
854854

855855
# Check if the protocol version is supported
856-
if protocol_version not in SUPPORTED_PROTOCOL_VERSIONS: # pragma: no cover
856+
if protocol_version not in SUPPORTED_PROTOCOL_VERSIONS:
857857
supported_versions = ", ".join(SUPPORTED_PROTOCOL_VERSIONS)
858858
response = self._create_error_response(
859859
f"Bad Request: Unsupported protocol version: {protocol_version}. "
@@ -865,13 +865,13 @@ async def _validate_protocol_version(self, request: Request, send: Send) -> bool
865865

866866
return True
867867

868-
async def _replay_events(self, last_event_id: str, request: Request, send: Send) -> None: # pragma: no cover
868+
async def _replay_events(self, last_event_id: str, request: Request, send: Send) -> None:
869869
"""Replays events that would have been sent after the specified event ID.
870870
871871
Only used when resumability is enabled.
872872
"""
873873
event_store = self._event_store
874-
if not event_store:
874+
if not event_store: # pragma: no cover
875875
return
876876

877877
try:
@@ -881,7 +881,7 @@ async def _replay_events(self, last_event_id: str, request: Request, send: Send)
881881
"Content-Type": CONTENT_TYPE_SSE,
882882
}
883883

884-
if self.mcp_session_id:
884+
if self.mcp_session_id: # pragma: no branch
885885
headers[MCP_SESSION_ID_HEADER] = self.mcp_session_id
886886

887887
# Get protocol version from header (already validated in _validate_protocol_version)
@@ -902,7 +902,7 @@ async def send_event(event_message: EventMessage) -> None:
902902
stream_id = await event_store.replay_events_after(last_event_id, send_event)
903903

904904
# If stream ID not in mapping, create it
905-
if stream_id and stream_id not in self._request_streams:
905+
if stream_id and stream_id not in self._request_streams: # pragma: no branch
906906
# Register SSE writer so close_sse_stream() can close it
907907
self._sse_stream_writers[stream_id] = sse_stream_writer
908908

@@ -919,10 +919,10 @@ async def send_event(event_message: EventMessage) -> None:
919919
event_data = self._create_event_data(event_message)
920920

921921
await sse_stream_writer.send(event_data)
922-
except anyio.ClosedResourceError:
922+
except anyio.ClosedResourceError: # pragma: lax no cover
923923
# Expected when close_sse_stream() is called
924924
logger.debug("Replay SSE stream closed by close_sse_stream()")
925-
except Exception:
925+
except Exception: # pragma: lax no cover
926926
logger.exception("Error in replay sender")
927927

928928
# Create and start EventSourceResponse
@@ -934,13 +934,13 @@ async def send_event(event_message: EventMessage) -> None:
934934

935935
try:
936936
await response(request.scope, request.receive, send)
937-
except Exception:
937+
except Exception: # pragma: no cover
938938
logger.exception("Error in replay response")
939939
finally:
940940
await sse_stream_writer.aclose()
941941
await sse_stream_reader.aclose()
942942

943-
except Exception:
943+
except Exception: # pragma: no cover
944944
logger.exception("Error replaying events")
945945
response = self._create_error_response(
946946
"Error replaying events",
@@ -991,7 +991,7 @@ async def message_router():
991991
if isinstance(message, JSONRPCResponse | JSONRPCError) and message.id is not None:
992992
target_request_id = str(message.id)
993993
# Extract related_request_id from meta if it exists
994-
elif ( # pragma: no cover
994+
elif (
995995
session_message.metadata is not None
996996
and isinstance(
997997
session_message.metadata,
@@ -1015,10 +1015,10 @@ async def message_router():
10151015
try:
10161016
# Send both the message and the event ID
10171017
await self._request_streams[request_stream_id][0].send(EventMessage(message, event_id))
1018-
except (anyio.BrokenResourceError, anyio.ClosedResourceError): # pragma: no cover
1018+
except (anyio.BrokenResourceError, anyio.ClosedResourceError): # pragma: lax no cover
10191019
# Stream might be closed, remove from registry
10201020
self._request_streams.pop(request_stream_id, None)
1021-
else: # pragma: no cover
1021+
else:
10221022
logger.debug(
10231023
f"""Request stream {request_stream_id} not found
10241024
for message. Still processing message as the client

0 commit comments

Comments
 (0)