test(mcp): align trusted proxy fixtures

This commit is contained in:
gym-cmd 2026-05-15 17:16:47 +01:00
parent 1d731af5df
commit dee5d55a0b
3 changed files with 56 additions and 45 deletions

View file

@ -16,8 +16,11 @@ def set_request_from_trusted_proxy(mock_request):
@pytest.fixture
def trusted_proxy_origin_headers():
with patch(
"litellm.proxy._experimental.mcp_server.oauth_utils.get_mcp_trusted_proxy_ranges",
return_value=TRUSTED_PROXY_RANGES,
"litellm.proxy._experimental.mcp_server.discoverable_endpoints.IPAddressUtils.is_request_from_trusted_proxy",
return_value=True,
), patch(
"litellm.proxy._experimental.mcp_server.oauth_utils.IPAddressUtils.is_request_from_trusted_proxy",
return_value=True,
):
yield
@ -1193,8 +1196,12 @@ def test_get_request_base_url_ignores_forwarded_headers_from_untrusted_client():
mock_request.client.host = "203.0.113.10"
with patch(
"litellm.proxy._experimental.mcp_server.oauth_utils.get_mcp_trusted_proxy_ranges",
return_value=TRUSTED_PROXY_RANGES,
"litellm.proxy.proxy_server.general_settings",
{
"use_x_forwarded_for": True,
"mcp_trusted_proxy_ranges": TRUSTED_PROXY_RANGES,
},
create=True,
):
assert get_request_base_url(mock_request) == "https://gateway.example.com/mcp"
@ -1218,8 +1225,12 @@ def test_validate_trusted_redirect_uri_rejects_spoofed_forwarded_host():
mock_request.client.host = "203.0.113.10"
with patch(
"litellm.proxy._experimental.mcp_server.oauth_utils.get_mcp_trusted_proxy_ranges",
return_value=TRUSTED_PROXY_RANGES,
"litellm.proxy.proxy_server.general_settings",
{
"use_x_forwarded_for": True,
"mcp_trusted_proxy_ranges": TRUSTED_PROXY_RANGES,
},
create=True,
), pytest.raises(HTTPException):
validate_trusted_redirect_uri(
mock_request,

View file

@ -1707,8 +1707,8 @@ async def test_multi_issuer_jwt_validates_selected_issuer_and_maps_claims(
audience="audience-two",
kid=shared_kid,
extra_claims={
"repository_owner": "jet-ai-productivity",
"repository": "jet-ai-productivity/litellm-fork",
"repository_owner": "example-org",
"repository": "example-org/litellm-fork",
},
)
@ -1716,10 +1716,10 @@ async def test_multi_issuer_jwt_validates_selected_issuer_and_maps_claims(
assert claims[JWTHandler.LITELLM_JWT_ISSUER_CLAIM] == issuer_two
assert jwt_handler.get_user_id(token=claims, default_value=None) == (
"jet-ai-productivity"
"example-org"
)
assert jwt_handler.get_team_id(token=claims, default_value=None) == (
"jet-ai-productivity/litellm-fork"
"example-org/litellm-fork"
)
@ -1748,12 +1748,12 @@ async def test_multi_issuer_jwt_maps_kubernetes_namespace_claim(monkeypatch):
issuer=issuer,
audience="kubernetes.default.svc",
kid="k8s-key",
extra_claims={"kubernetes.io": {"namespace": "jet-namespace"}},
extra_claims={"kubernetes.io": {"namespace": "example-namespace"}},
)
claims = await jwt_handler.auth_jwt(token=token)
assert jwt_handler.get_user_id(token=claims, default_value=None) == "jet-namespace"
assert jwt_handler.get_user_id(token=claims, default_value=None) == "example-namespace"
@pytest.mark.asyncio

View file

@ -134,9 +134,9 @@ async def test_oauth_protected_resource_passthrough_proxies_upstream_metadata():
global_mcp_server_manager.registry.clear()
passthrough_server = MCPServer(
server_id="passthrough-1",
name="jet_knowledge_qa",
server_name="jet_knowledge_qa",
alias="jet_knowledge_qa",
name="knowledge_qa",
server_name="knowledge_qa",
alias="knowledge_qa",
url="https://upstream.example.com/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -163,7 +163,7 @@ async def test_oauth_protected_resource_passthrough_proxies_upstream_metadata():
):
result = await _build_oauth_protected_resource_response(
request=_make_request(),
mcp_server_name="jet_knowledge_qa",
mcp_server_name="knowledge_qa",
use_standard_pattern=True,
)
@ -171,7 +171,7 @@ async def test_oauth_protected_resource_passthrough_proxies_upstream_metadata():
"https://okta.example.com/oauth2/default"
]
# resource is normalized to the gateway URL so bearers are sent back to us
assert result["resource"].endswith("/mcp/jet_knowledge_qa")
assert result["resource"].endswith("/mcp/knowledge_qa")
assert result["scopes_supported"] == ["openid", "profile"]
@ -184,9 +184,9 @@ async def test_oauth_protected_resource_passthrough_cache_hit():
global_mcp_server_manager.registry.clear()
passthrough_server = MCPServer(
server_id="passthrough-2",
name="jet_knowledge_qa",
server_name="jet_knowledge_qa",
alias="jet_knowledge_qa",
name="knowledge_qa",
server_name="knowledge_qa",
alias="knowledge_qa",
url="https://upstream.example.com/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -209,12 +209,12 @@ async def test_oauth_protected_resource_passthrough_cache_hit():
):
await _build_oauth_protected_resource_response(
request=_make_request(),
mcp_server_name="jet_knowledge_qa",
mcp_server_name="knowledge_qa",
use_standard_pattern=True,
)
await _build_oauth_protected_resource_response(
request=_make_request(),
mcp_server_name="jet_knowledge_qa",
mcp_server_name="knowledge_qa",
use_standard_pattern=True,
)
@ -230,9 +230,9 @@ async def test_oauth_protected_resource_passthrough_network_error_returns_502():
global_mcp_server_manager.registry.clear()
passthrough_server = MCPServer(
server_id="passthrough-3",
name="jet_knowledge_qa",
server_name="jet_knowledge_qa",
alias="jet_knowledge_qa",
name="knowledge_qa",
server_name="knowledge_qa",
alias="knowledge_qa",
url="https://upstream.example.com/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -251,7 +251,7 @@ async def test_oauth_protected_resource_passthrough_network_error_returns_502():
with pytest.raises(HTTPException) as exc_info:
await _build_oauth_protected_resource_response(
request=_make_request(),
mcp_server_name="jet_knowledge_qa",
mcp_server_name="knowledge_qa",
use_standard_pattern=True,
)
@ -262,9 +262,9 @@ async def test_oauth_protected_resource_passthrough_network_error_returns_502():
async def test_fetch_upstream_metadata_returns_none_when_not_all_candidates_network_fail():
passthrough_server = MCPServer(
server_id="passthrough-partial-network",
name="jet_knowledge_qa",
server_name="jet_knowledge_qa",
alias="jet_knowledge_qa",
name="knowledge_qa",
server_name="knowledge_qa",
alias="knowledge_qa",
url="https://upstream.example.com/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -381,7 +381,7 @@ async def test_fetch_tools_from_passthrough_raises_on_upstream_401():
manager = MCPServerManager()
passthrough_server = MCPServer(
server_id="p1",
name="jet_knowledge_qa",
name="knowledge_qa",
url="https://upstream/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -409,7 +409,7 @@ async def test_fetch_tools_from_passthrough_raises_on_upstream_401():
assert exc_info.value.www_authenticate == (
'Bearer resource_metadata="https://upstream"'
)
assert exc_info.value.server_name == "jet_knowledge_qa"
assert exc_info.value.server_name == "knowledge_qa"
mock_client.list_tools.assert_awaited_with(raise_on_error=True)
@ -418,7 +418,7 @@ async def test_fetch_tools_from_passthrough_returns_tools_on_success():
manager = MCPServerManager()
passthrough_server = MCPServer(
server_id="p1",
name="jet_knowledge_qa",
name="knowledge_qa",
url="https://upstream/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -492,12 +492,12 @@ def _make_scope(path: str, headers: list = None) -> dict:
"route,expected_metadata_path",
[
(
"/mcp/jet_knowledge_qa",
"/.well-known/oauth-protected-resource/mcp/jet_knowledge_qa",
"/mcp/knowledge_qa",
"/.well-known/oauth-protected-resource/mcp/knowledge_qa",
),
(
"/jet_knowledge_qa/mcp",
"/.well-known/oauth-protected-resource/jet_knowledge_qa/mcp",
"/knowledge_qa/mcp",
"/.well-known/oauth-protected-resource/knowledge_qa/mcp",
),
],
)
@ -517,9 +517,9 @@ async def test_passthrough_cold_start_emits_401_with_matching_resource_metadata(
global_mcp_server_manager.registry.clear()
passthrough_server = MCPServer(
server_id="pt-cold-start",
name="jet_knowledge_qa",
server_name="jet_knowledge_qa",
alias="jet_knowledge_qa",
name="knowledge_qa",
server_name="knowledge_qa",
alias="knowledge_qa",
url="https://upstream.example.com/mcp",
transport=MCPTransport.http,
auth_type=MCPAuth.none,
@ -534,7 +534,7 @@ async def test_passthrough_cold_start_emits_401_with_matching_resource_metadata(
if route.startswith("/mcp/"):
scope = _make_scope(route)
else:
scope = _make_scope(f"/mcp/jet_knowledge_qa")
scope = _make_scope(f"/mcp/knowledge_qa")
scope["_original_path"] = route
# Verify cold-start detection fires for this path
@ -545,7 +545,7 @@ async def test_passthrough_cold_start_emits_401_with_matching_resource_metadata(
assert _is_mcp_passthrough_cold_start(scope, servers) is True
# Verify resource_metadata_url form selection
server_name = "jet_knowledge_qa"
server_name = "knowledge_qa"
base_url = "http://localhost:4000"
path = scope.get("_original_path") or scope.get("path", "") or ""
if path.startswith(f"/{server_name}/mcp"):
@ -617,10 +617,10 @@ def test_is_mcp_passthrough_cold_start_false_for_empty_servers():
@pytest.mark.parametrize(
"path,expected",
[
("/mcp/jet_knowledge_qa", ["jet_knowledge_qa"]),
("/mcp/jet_knowledge_qa/tools/list", ["jet_knowledge_qa"]),
("/jet_knowledge_qa/mcp", ["jet_knowledge_qa"]),
("/jet_knowledge_qa/mcp/tools/list", ["jet_knowledge_qa"]),
("/mcp/knowledge_qa", ["knowledge_qa"]),
("/mcp/knowledge_qa/tools/list", ["knowledge_qa"]),
("/knowledge_qa/mcp", ["knowledge_qa"]),
("/knowledge_qa/mcp/tools/list", ["knowledge_qa"]),
("/mcp", None),
("/mcp/", None),
("/other/path", None),