mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
* fix(mcp): drop caller host and configured upstream headers from logged metadata The synthetic request that carries MCP client headers into add_litellm_data_to_request forwarded the caller's Host header, and Request.url is built from it, so a caller chose the proxy_server_request url and the metadata endpoint that every logging callback records. _upstream_credential_headers also only knew the configured client side auth header and the x-mcp- prefix family, so a header name declared in mcp_servers.<name>.extra_headers reached logging metadata in cleartext. Those names are admin chosen, so no prefix rule can recognize them; read them off the server registry instead. The header is still forwarded upstream, which is what extra_headers is for. authorization is left out because clean_headers already strips it and claiming it here would move authenticated_with_header on the oauth passthrough config. The Responses bridge tests stub the server manager, so their fakes gain the registry accessor the sanitizer now reads. * fix(mcp): drop caller host from the sanitized header mapping too The synthetic request stopped forwarding host, but the parallel sanitizer did not, so a forged hostname still reached the guardrail payload and the list_tools spend row. Drop it there as well. Exempt the configured identity headers from the upstream credential set. get_user_from_headers resolves end user attribution off the same request this module reconstructs, and it only fills end_user_id when auth left it unset, so claiming user_header_name or a user_header_mappings name would lose attribution on the MCP paths that authenticate upstream. Drop the isinstance guard on extra_headers entries: the field is typed list[str], so the check is dead and basedpyright scores it. * fix(mcp): accept a bare user_header_mappings entry when exempting identity headers get_internal_user_header_from_mapping and get_customer_user_header_from_mapping both normalize a single mapping to a one element list, and config_settings.md documents the key as a dict. Iterating the bare form yields its keys instead, so the exemption silently matched nothing and an identity header also named in an MCP server's extra_headers was dropped after all. |
||
|---|---|---|
| .. | ||
| test_chat_completions_handler.py | ||
| test_litellm_proxy_mcp_handler.py | ||
| test_mcp_streaming_iterator.py | ||