mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
* feat(mcp): discover the OBO token endpoint via RFC 9728 to RFC 8414 (no IdP guessing) An oauth2_token_exchange server can now have its token endpoint discovered the same way the oauth2 (authorization_code) flow already does, instead of always requiring token_exchange_endpoint/token_url to be configured by hand. The existing _descovery_metadata chain (RFC 9728 protected-resource metadata -> RFC 8414 authorization-server metadata -> token_endpoint, SSRF-guarded via async_safe_get) is reused; both the config-load and DB-build paths gate on a new _obo_needs_endpoint_discovery so discovery runs only when no endpoint is configured, and an explicitly configured endpoint still wins and skips the round-trip. The discovered token endpoint lands on token_url, which _token_exchange_spec already reads, so no resolver change is needed. _resolve_oauth2_flow returns None for any non-oauth2 auth_type, so a discovered token_url on an OBO server is never mis-inferred as the M2M client_credentials flow. Discovery for OBO is authoritative only: the resolution order is explicitly configured endpoint, then RFC 9728 -> RFC 8414 advertisement, then fail closed (412, on the parent commit). The gateway never guesses the IdP. _descovery_metadata grows an allow_origin_fallback flag, kept True for the browser oauth2 flow (a human sees the redirect) but set False for token_exchange so the last-resort guess that treats the resource server's own origin as its authorization server is skipped; a subject token is never exchanged against an inferred endpoint. * fix(mcp): surface a failed OBO exchange at connect instead of an empty tool list A token_exchange server whose exchange fails with a subject present used to open the MCP session anyway and mask the failure as an empty tools/list. Single-server routes now run the exchange preemptively at the transport edge, where a rejected subject raises the RFC 9728 challenge and a gateway fault its public status; the multi-server aggregate keeps absorbing per-server auth failures. The exchanger caches the preflight result, so the session's list/call reuses it with no extra IdP round-trip. Discovery now also debug-logs the authorization server's advertised issuer, grant types, and client auth methods * fix(mcp): persist the discovered OBO token endpoint to the DB row A DB-backed oauth2_token_exchange server with no configured endpoint had its token_url resolved via RFC 9728 -> RFC 8414 only on the in-memory object returned from build_mcp_server_from_table; the row kept token_url=None, so every rebuild re-ran discovery and a transient upstream outage during a rebuild left the server with no endpoint until the next successful discovery. Write the discovered token_url back onto the row so the guard sees it on the next build. Best-effort and scoped to DB servers: config servers already persist in-memory, and the write-back never fires from a user connect (only from add/update/reload, all admin or system driven). Adds DB-path coverage for discovery firing when unset, skipping when the credentials endpoint is configured, the write-back, and its negative guards |
||
|---|---|---|
| .. | ||
| auth | ||
| guardrail_translation | ||
| outbound_credentials | ||
| test_byok_oauth_endpoints.py | ||
| test_callback_oauth_error_responses.py | ||
| test_db_credentials.py | ||
| test_discoverable_endpoints.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_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 | ||