From d429e845c9268a747f410358510cb824d8cc3201 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 20 May 2026 19:28:02 +0000 Subject: [PATCH] fix(mcp): skip JWT injection when extra_headers already has Authorization When a server uses per-user OAuth tokens, the resolved token is passed into _get_tools_from_server via extra_headers. The JWT injection guard only checked mcp_auth_header and the server's static headers, so the signer would silently overwrite the user's OAuth Authorization header. Add a check for an existing Authorization entry in extra_headers so caller-supplied per-user OAuth tokens take precedence over JWT signing. Co-authored-by: Yassin Kortam --- .../_experimental/mcp_server/mcp_server_manager.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py index a1ef47909db..4da24eca573 100644 --- a/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py +++ b/litellm/proxy/_experimental/mcp_server/mcp_server_manager.py @@ -1437,8 +1437,10 @@ class MCPServerManager: # MCPJWTSigner: inject signed JWT for tools/list (list path skips pre_call_hook). # Skip entirely when the signer is not configured (avoid an unnecessary # dict copy on every list call), when the server has its own static - # Authorization header, or when a per-user mcp_auth_header has already - # been resolved — admin-configured static auth and per-user OAuth must + # Authorization header, when a per-user mcp_auth_header has already + # been resolved, or when the caller already supplied an Authorization + # entry in extra_headers (e.g. a per-user OAuth token resolved + # upstream) — admin-configured static auth and per-user OAuth must # take precedence so the signer doesn't silently overwrite e.g. an # upstream API key or a user's OAuth token (MCPClient._get_auth_headers # applies extra_headers after writing Authorization from auth_value, so @@ -1454,11 +1456,16 @@ class MCPServerManager: isinstance(k, str) and k.lower() == "authorization" for k in static_headers.keys() ) + has_extra_authorization = bool(extra_headers) and any( + isinstance(k, str) and k.lower() == "authorization" + for k in (extra_headers or {}).keys() + ) if ( get_mcp_jwt_signer() is not None and not has_static_authorization and not mcp_auth_header + and not has_extra_authorization ): extra_headers = await inject_mcp_jwt_headers_for_upstream( user_api_key_dict=user_api_key_auth,