Format the ported files, annotate mutable wire payloads, give the e2e
OAuth client the SDK 2 httpx2/AuthorizationCodeResult API, tighten the
transport-streams alias to the two-stream SDK 2 shape, and add a
test-quality reason for the MockTransport factory injection.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
New matrix job across Python 3.10-3.14 verifies uv.lock against the
declared floors, installs the locked mcp+proxy extras and runs the MCP
unit suites, then resolves the same extras with uv's lowest-direct
strategy into a clean venv and runs scripts/check_mcp_sdk_install.py to
prove the floor still imports the SDK 2 API surface.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Call handlers with ServerRequestContext and params models, seed the
litellm contextvar instead of the removed SDK request_ctx, forward
headers/auth through the httpx2 MockTransport factory, and add
regressions for handler registration, context propagation, and modern
protocol-version rejection.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Port the proxy MCP server off the removed SDK1 decorator API. Handlers now
take (ctx, params), are registered via add_request_handler, and return full
result models. Request-scoped session/context propagation moves to a
litellm-owned active_mcp_request_ctx_var ContextVar set at handler entry.
Reject MCP-Protocol-Version values outside the SDK2 handshake set with a
400 before session-manager delegation. Fold SDK2 MCPError-wrapped parse
and content-type failures into the existing connection diagnostics.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Rename McpError/isError/inputSchema-style references to the SDK 2
spellings, parse the JSONRPCMessage union with a TypeAdapter, and drive
the SDK transports off httpx2 MockTransport injection where respx can no
longer intercept. Adjust for SDK 2 behavior: the initialize handshake
negotiates handshake-era protocol versions only, an empty SSE stream
surfaces CONNECTION_CLOSED, non-2xx tool responses surface INTERNAL_ERROR
MCPError instead of HTTPStatusError, and the SDK read timeout carries the
JSON-RPC REQUEST_TIMEOUT code.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
McpError -> MCPError (new code/message/data constructor), camelCase model
attributes and constructor kwargs -> snake_case, RequestResponder ->
ClientSession message handler receiving ServerNotification | Exception,
RequestContext -> ClientRequestContext, read_timeout_seconds -> float,
server_capabilities property, JSONRPCMessage union parsed via TypeAdapter,
and httpx -> httpx2 for every object handed to the SDK transports
(MCPSigV4Auth, the httpx client factory, outbound_credentials auth
classes and resolver return types). Helpers that serve both litellm httpx
clients and the SDK's httpx2 transport accept both response types.
The SDK read-timeout code is now the JSON-RPC REQUEST_TIMEOUT (-32001)
instead of HTTP 408; as_mcp_read_timeout keeps the TimeoutError context
discriminator. Upstream transport exceptions and responses found in
exception trees are matched as httpx2 alongside httpx.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Replace the bespoke dependency-install CI gate with a real migration:
require mcp>=2.2.0,<3 alongside httpx2>=2.5.0,<3 and pydantic>=2.12.0,<3
in the proxy and mcp extras, drop langchain-mcp-adapters (pins mcp<2)
from the dev group, and remove the dependency-install workflow and
tests/mcp_dependency_tests that only exercised the old pins.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The Responses id security hook keeps the id a client addressed under
`_litellm_addressed_response_id` in the request body so internal retries can
re-authorize it. On a model without a native Responses config that body is
bridged into `completion()` kwargs, the key was treated as a provider param,
and providers rejected it, so every follow-up turn carrying
`previous_response_id` returned 400.
Register the key in `all_litellm_params` so it is dropped before any provider
request, and share one constant between the hook and the param list.
Forking a shared budget row rebuilt budget_reset_at from the duration, so editing
an unrelated limit restarted the member's window while their spend carried over:
a tpm bump quietly handed them a fresh period. The fork now inherits the source
row's deadline, and only recomputes when the patch actually sets budget_duration.
The bulk member budget route now writes one audit entry per call, a team-scoped
'updated' row carrying every written member's limits before and after, matching
what /team/member_add already records for membership changes. It honors the
litellm-changed-by header like the other audited team routes.
Log the underlying ImportError server side and send the client only the installed
version, the supported range and the install hint
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>