Replace httpx and httpx-sse with httpx2 (#2972)
Some checks failed
CI / checks (push) Has been cancelled
CI / all-green (push) Has been cancelled

Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
This commit is contained in:
Marcelo Trylesinski 2026-07-14 18:05:08 +02:00 • committed by GitHub
commit 2713b53b12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -12,7 +12,7 @@ from collections.abc import Callable
from typing import Any, Literal
import anyio
import httpx
import httpx2
import pytest
from inline_snapshot import snapshot
from mcp_types import (
@ -77,7 +77,7 @@ def _meta_envelope() -> dict[str, object]:
def _server(*, on_meta: Callable[[dict[str, Any]], None] | None = None) -> Server:
"""A low-level server with one ``add`` tool for the raw-httpx tests below."""
"""A low-level server with one ``add`` tool for the raw-httpx2 tests below."""
async def list_tools(ctx: ServerRequestContext, params: PaginatedRequestParams | None) -> ListToolsResult:
tool = Tool(name="add", input_schema={"type": "object"})
@ -311,7 +311,7 @@ async def test_pinned_client_stateless_tools_call_round_trips_against_the_modern
plus the three-key ``io.modelcontextprotocol/*`` ``_meta`` envelope. The caller passes a
``custom-key`` under ``meta=`` and the server handler captures the incoming ``ctx.meta``,
proving the envelope merge is additive: the caller's key sits alongside the three envelope keys
on the wire and inside the handler. Asserted at the wire via the ``mounted_app`` httpx event
on the wire and inside the handler. Asserted at the wire via the ``mounted_app`` httpx2 event
hooks because none of the headers, the envelope, or the handshake-absence is observable through
the public client API. The recorded log shows two POSTs: the ``tools/call`` itself and the
client's implicit ``tools/list`` output-schema fetch (see ``client:output-schema:auto-list``),
@ -320,13 +320,13 @@ async def test_pinned_client_stateless_tools_call_round_trips_against_the_modern
observed_metas: list[dict[str, Any]] = []
server = _server(on_meta=observed_metas.append)
requests: list[httpx.Request] = []
responses: list[httpx.Response] = []
requests: list[httpx2.Request] = []
responses: list[httpx2.Response] = []
async def on_request(request: httpx.Request) -> None:
async def on_request(request: httpx2.Request) -> None:
requests.append(request)
async def on_response(response: httpx.Response) -> None:
async def on_response(response: httpx2.Response) -> None:
responses.append(response)
client_info = Implementation(name="e2e-client", version="1.0.0")
@ -432,9 +432,9 @@ async def test_modern_client_mirrors_x_mcp_header_args_into_mcp_param_headers()
`verbose`-sibling stay out of the headers, and every mirrored value remains in the request body. Asserted
at the wire because the client never surfaces the outgoing headers.
"""
requests: list[httpx.Request] = []
requests: list[httpx2.Request] = []
async def on_request(request: httpx.Request) -> None:
async def on_request(request: httpx2.Request) -> None:
requests.append(request)
discover = DiscoverResult(
@ -479,9 +479,9 @@ async def test_modern_client_emits_no_param_headers_for_an_unlisted_tool() -> No
The server validates `Mcp-Param-*` against its own catalog and rejects as the spec's scenario table
requires for an omitted header (the relist-and-retry recovery is a SHOULD the client does not implement yet).
"""
requests: list[httpx.Request] = []
requests: list[httpx2.Request] = []
async def on_request(request: httpx.Request) -> None:
async def on_request(request: httpx2.Request) -> None:
requests.append(request)
discover = DiscoverResult(
@ -532,9 +532,9 @@ async def test_modern_client_stops_mirroring_after_a_re_list_drops_the_tool() ->
server = Server("evict", on_list_tools=list_tools, on_call_tool=call_tool)
tool_calls: list[httpx.Request] = []
tool_calls: list[httpx2.Request] = []
async def on_request(request: httpx.Request) -> None:
async def on_request(request: httpx2.Request) -> None:
if json.loads(request.content)["method"] == "tools/call":
tool_calls.append(request)
@ -588,9 +588,9 @@ async def test_vendor_request_with_name_param_carries_mcp_name_on_the_wire() ->
server = _server()
server.add_request_handler("com.example/jobs.status", _JobParams, job_status)
requests: list[httpx.Request] = []
requests: list[httpx2.Request] = []
async def on_request(request: httpx.Request) -> None:
async def on_request(request: httpx2.Request) -> None:
requests.append(request)
discover = DiscoverResult(