@@ -729,6 +729,68 @@ async def get_mcp_tools(
729729 return tools
730730
731731
732+ def apply_mcp_headers_to_explicit_tools (
733+ tools : list [InputTool ],
734+ token : Optional [str ] = None ,
735+ mcp_headers : Optional [McpHeaders ] = None ,
736+ request_headers : Optional [Mapping [str , str ]] = None ,
737+ ) -> list [InputTool ]:
738+ """Merge resolved MCP headers into explicit request MCP tools.
739+
740+ Args:
741+ tools: Tools from the request after BYOK translation.
742+ token: Optional bearer token for kubernetes MCP auth.
743+ mcp_headers: Per-request MCP-HEADERS map keyed by server name.
744+ request_headers: Incoming HTTP headers for allowlist propagation.
745+
746+ Returns:
747+ New tool list with MCP entries updated or omitted.
748+ """
749+ if not tools :
750+ return tools
751+
752+ complete_headers = build_mcp_headers (
753+ configuration , mcp_headers or {}, request_headers , token
754+ )
755+ servers_by_name = {s .name : s for s in configuration .mcp_servers }
756+
757+ out : list [InputTool ] = []
758+ for tool in tools :
759+ if tool .type != "mcp" :
760+ out .append (tool )
761+ continue
762+
763+ mcp_tool = cast (InputToolMCP , tool )
764+ mcp_server = servers_by_name .get (mcp_tool .server_label )
765+ if mcp_server is None :
766+ out .append (tool )
767+ continue
768+
769+ headers : dict [str , str ] = dict (complete_headers .get (mcp_server .name , {}))
770+ unresolved = find_unresolved_auth_headers (
771+ mcp_server .authorization_headers , headers
772+ )
773+ if unresolved :
774+ logger .warning (
775+ "Skipping explicit MCP tool %s: required %d auth headers but only resolved %d" ,
776+ mcp_server .name ,
777+ len (mcp_server .authorization_headers ),
778+ len (mcp_server .authorization_headers ) - len (unresolved ),
779+ )
780+ continue
781+
782+ authorization = headers .pop ("Authorization" , None )
783+ out .append (
784+ mcp_tool .model_copy (
785+ update = {
786+ "headers" : headers if headers else None ,
787+ "authorization" : authorization ,
788+ }
789+ )
790+ )
791+ return out
792+
793+
732794def parse_referenced_documents ( # pylint: disable=too-many-locals
733795 response : Optional [ResponseObject ],
734796 vector_store_ids : Optional [list [str ]] = None ,
@@ -1553,6 +1615,9 @@ async def resolve_tool_choice(
15531615 # Pass tools explicitly configured for this request
15541616 byok_rags = configuration .configuration .byok_rag
15551617 prepared_tools = translate_tools_vector_store_ids (tools , byok_rags )
1618+ prepared_tools = apply_mcp_headers_to_explicit_tools (
1619+ prepared_tools , token , mcp_headers , request_headers
1620+ )
15561621
15571622 if isinstance (tool_choice , AllowedTools ):
15581623 # Apply filters to tools if specified and overwrite tool choice mode
0 commit comments