From 6d47ffc77d3c1adacc79311280fc73f540ff10df Mon Sep 17 00:00:00 2001 From: Tin Chi Lo Date: Fri, 19 Jun 2026 18:08:47 -0700 Subject: [PATCH] feat(mcp/v2): wire aws_sigv4 through the egress override Map aws_sigv4 in _to_server_spec (reusing _to_aws_sigv4_config), so MCPServerManagerV2's override resolves it to the botocore SigV4 signer (an httpx.Auth) and lists tools through UpstreamConnection instead of the old aws_auth seam. AssumeRole-with-explicit-base-keys still defers to v1. Live-validated: the aws_sigv4 mode through the override against the harness (:9200) lists echo with an AWS4-HMAC-SHA256-signed request. --- .../mcp_server/v2_resolver_bridge.py | 9 +++++++ .../mcp_server/test_v2_resolver_bridge.py | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/litellm/proxy/_experimental/mcp_server/v2_resolver_bridge.py b/litellm/proxy/_experimental/mcp_server/v2_resolver_bridge.py index 1e02527f8bf..2cd223cc50f 100644 --- a/litellm/proxy/_experimental/mcp_server/v2_resolver_bridge.py +++ b/litellm/proxy/_experimental/mcp_server/v2_resolver_bridge.py @@ -146,6 +146,15 @@ def to_server_spec(server: MCPServer) -> Optional[ServerSpec]: key_source=SharedKey(value=SecretStr(token)), ), ) + if server.auth_type == MCPAuth.aws_sigv4: + # Reuse the SigV4 config builder; the resolver's aws_sigv4 arm turns it into the botocore + # signer (an httpx.Auth) that signs each upstream request. + aws_config = _to_aws_sigv4_config(server) + if aws_config is None: + return None # AssumeRole with explicit base keys: not representable yet, defer to v1 + return ServerSpec( + server_id=server.server_id, resource=resource, config=aws_config + ) if server.has_token_exchange_config: # token_exchange takes precedence over client_credentials (matches v1's cascade); the arm # binds the exchanged token to this resource (audience, RFC 8707). diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_v2_resolver_bridge.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_v2_resolver_bridge.py index 2b78b86af76..75faee637c5 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_v2_resolver_bridge.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_v2_resolver_bridge.py @@ -413,3 +413,28 @@ async def test_none_without_passthrough_maps_to_none(): spec = to_server_spec(server) assert spec is not None assert isinstance(spec.config, NoneConfig) + + +async def test_aws_sigv4_server_maps_to_config(): + from litellm.proxy._experimental.mcp_server.v2_resolver_bridge import to_server_spec + from litellm.proxy.gateway.mcp.outbound_credentials.types import ( + AwsSigV4Config, + StaticKeys, + ) + + server = MCPServer( + server_id="sig1", + name="sig1", + transport=MCPTransport.http, + url="https://up.example/mcp", + auth_type=MCPAuth.aws_sigv4, + aws_access_key_id="AKIA", + aws_secret_access_key="secret", + aws_region_name="us-west-2", + aws_service_name="bedrock-agentcore", + ) + spec = to_server_spec(server) + assert spec is not None + assert isinstance(spec.config, AwsSigV4Config) + assert isinstance(spec.config.credentials, StaticKeys) + assert spec.config.region == "us-west-2"