diff --git a/litellm/proxy/mcp_server/mcp_server_manager.py b/litellm/proxy/mcp_server/mcp_server_manager.py index eb6f29b36b4..a382722e3c7 100644 --- a/litellm/proxy/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/mcp_server/mcp_server_manager.py @@ -7903,6 +7903,9 @@ def _server_credential_occupies_authorization(server: MCPServer) -> bool: ``Authorization``; ``api_key`` sends it in ``X-API-Key``; ``upstream_token_header`` moves either. A signer-injected ``Authorization`` would replace such a credential upstream. """ + if server.is_byok: + # A BYOK server's stored authentication_token is never sent upstream; the caller's own credential is. + return False if not server.authentication_token or server.auth_type not in _STATIC_CREDENTIAL_AUTH_TYPES: return False default_slot: Final = "X-API-Key" if server.auth_type == MCPAuth.api_key else "Authorization" diff --git a/tests/unit/proxy/_experimental/mcp_server/test_mcp_jwt_signer_server_credential.py b/tests/unit/proxy/_experimental/mcp_server/test_mcp_jwt_signer_server_credential.py index b7b7e19e149..0132706da38 100644 --- a/tests/unit/proxy/_experimental/mcp_server/test_mcp_jwt_signer_server_credential.py +++ b/tests/unit/proxy/_experimental/mcp_server/test_mcp_jwt_signer_server_credential.py @@ -163,3 +163,9 @@ async def test_tools_call_keeps_hook_authorization_when_server_key_rides_x_api_k headers = await _call_tool_and_capture_extra_headers(_server(MCPAuth.api_key), {"Authorization": "Bearer hook-jwt"}) assert headers.get("Authorization") == "Bearer hook-jwt" + + +def test_byok_server_stored_secret_never_occupies_authorization(): + server = _server(MCPAuth.bearer_token).model_copy(update={"is_byok": True}) + + assert _server_credential_occupies_authorization(server) is False