mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
The gateway acts as an MCP client toward upstream MCP servers, and the MCP authorization spec requires an MCP client to send the RFC 8707 resource parameter on both the authorization request and every token request. The gateway sent it on none of its upstream OAuth legs, so an authorization server that requires resource indicators rejected the exchange with invalid_target with no way to configure around it. Authorization servers disagree irreconcilably and nothing advertises which camp they are in, so this is a per-server opt-in rather than a default: most providers ignore the parameter, some hard-reject it and carry audience in scopes instead, and strict or MCP-native ones refuse to mint a correctly scoped token without it. The new upstream_resource setting is unset by default, which keeps today's requests byte-identical. Both outbound OAuth stacks resolve the value from the server exactly once and carry it structurally rather than attaching it per call site. In v1 every plain-OAuth2 token leg builds its body through one helper that resolves the resource in the same call as the mandatory client authentication; in v2 the adapter, the single place an MCPServer becomes an outbound config, resolves it onto the client_credentials config that the HTTP/SSE M2M path uses, and it joins the config's mint identity so retargeting a live server refreshes the token rather than serving the previous audience's. A leg cannot authenticate without also naming the resource its sibling legs named, which is what an attach-per-call-site approach kept getting wrong. The setting is non-secret admin config sharing a blob with real secrets, and the backend classifies which key is which rather than nulling the blob wholesale or gating on its truthiness: redaction returns admin config to an admin, session inheritance ignores it when deciding whether a real credential was supplied and carries it onto the derived server, and the edit form renders the same shared OAuth component as create so the field exists on both, an emptied field submitting an explicit null that the credential merge drops. |
||
|---|---|---|
| .. | ||
| auth | ||
| faults | ||
| guardrail_translation | ||
| outbound_credentials | ||
| conftest.py | ||
| test_byok_oauth_endpoints.py | ||
| test_callback_oauth_error_responses.py | ||
| test_db_credentials.py | ||
| test_discoverable_endpoints.py | ||
| test_gateway_dcr_flow.py | ||
| test_is_tool_name_prefixed.py | ||
| test_jwt_mcp_enforcement.py | ||
| test_jwt_mcp_simple.py | ||
| test_mcp_cost_calculator.py | ||
| test_mcp_custom_fields.py | ||
| test_mcp_debug.py | ||
| test_mcp_discovery.py | ||
| test_mcp_elicitation_handler.py | ||
| test_mcp_env_vars.py | ||
| test_mcp_header_alias_utils.py | ||
| test_mcp_hook_extra_headers.py | ||
| test_mcp_max_concurrent_requests.py | ||
| test_mcp_metadata_preservation.py | ||
| test_mcp_oauth_passthrough.py | ||
| test_mcp_oauth_passthrough_cold_start.py | ||
| test_mcp_oauth_passthrough_tools.py | ||
| test_mcp_partial_update.py | ||
| test_mcp_sampling_completion_flow.py | ||
| test_mcp_sampling_model_access.py | ||
| test_mcp_sampling_model_resolution.py | ||
| test_mcp_sampling_priority_selection.py | ||
| test_mcp_sampling_request_builder.py | ||
| test_mcp_sampling_response_conversion.py | ||
| test_mcp_sampling_tool_conversion.py | ||
| test_mcp_server.py | ||
| test_mcp_server_identity_env.py | ||
| test_mcp_server_manager.py | ||
| test_mcp_session_logging.py | ||
| test_mcp_sigv4_auth.py | ||
| test_mcp_stale_session.py | ||
| test_mcp_tool_search.py | ||
| test_mcp_toolset_scope.py | ||
| test_oauth2_flow_backfill.py | ||
| test_oauth2_token_cache.py | ||
| test_openapi_to_mcp_generator.py | ||
| test_openapi_tool_auth.py | ||
| test_rest_endpoints.py | ||
| test_semantic_tool_filter.py | ||
| test_short_mcp_tool_prefix.py | ||
| test_ui_session_utils.py | ||
| test_utils.py | ||