litellm/tests/test_litellm/proxy
Ishaan Jaff 19db79db17
fix(mcp): OAuth2 chat connect - tools fetch, auth, and status fixes (#23406)
* fix(mcp): OAuth2 chat connect - tools fetch, auth flow, and status fixes

- schema.prisma: add missing MCP table fields (approval_status, submitted_by, submitted_at, reviewed_at, review_notes) to prevent destructive migrations
- rest_endpoints.py: inject user OAuth token via extra_headers for OAuth2 servers so tools list is populated; add server name->UUID resolution so MCPConnectPicker name lookups work
- mcp_registry.json: fix Atlassian defaults (transport: http, url: .../v1/mcp)
- ChatPage.tsx: read mcpOauthReturn param to init sidebarView="apps" on OAuth return, clean up param after mount
- MCPAppsPanel.tsx: auto-add OAuth2 servers to selectedServers when credential detected; onConnect also enables server for chat; disconnect removes from selectedServers
- mcp_servers.tsx: sort servers by created_at DESC
- useUserMcpOAuthFlow.tsx: append mcpOauthReturn=apps to return URL so Apps panel is mounted on return

* address greptile review feedback (greploop iteration 1)

* fix(mcp): inject stored OAuth2 token when fetching tools via /responses API

When a user has connected an OAuth2 MCP server (e.g. Atlassian) and then
uses the /responses endpoint with that server, tool listing was failing
because the stored per-user OAuth token was never injected.

Two fixes:
1. server.py: add _get_user_oauth_extra_headers_from_db() helper; call it
   in _get_tools_from_mcp_servers when oauth2_headers is None for an OAuth2
   server, falling back to the user's stored token in LiteLLM_MCPUserCredentials
2. litellm_proxy_mcp_handler.py: also intercept MCP tools whose server_url
   matches */mcp/<server_name> (e.g. http://localhost:4000/mcp/atlassian_test)
   by rewriting them to litellm_proxy/mcp/<server_name> so they go through
   the internal handler (and get the OAuth token injected) instead of being
   forwarded to OpenAI raw where localhost is unreachable

* address greptile review feedback (greploop iteration 2)

* test(mcp): add unit test for OAuth2 token injection in _get_tools_from_mcp_servers

Verifies that when _get_tools_from_mcp_servers is called for an OAuth2 MCP
server without oauth2_headers in the request, the implementation:
- calls _prefetch_oauth_creds_for_user once (not per-server) to avoid N+1 queries
- passes the stored token as extra_headers={"Authorization": "Bearer ..."} to
  _get_tools_from_server so the upstream OAuth2 MCP server authenticates correctly

* address greptile review feedback (greploop iteration 3)

* address greptile review feedback (greploop iteration 4)

* address greptile review feedback (greploop iteration 5)

* redesign credentials table to use Tremor table layout matching Keys page

* fix: /server/oauth authorize 422 - make client_id optional, fall back to real DB server

* fix: mcp_token client_id optional, resolve from server record

* fix: look up real server by UUID (get_mcp_server_by_id) before falling back to name

* Update litellm/responses/mcp/litellm_proxy_mcp_handler.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* fix: address greptile feedback - client_id guards, dict spread, helper refactor, tests

- mcp_management_endpoints: raise 400 when resolved_client_id is empty in
  mcp_authorize and mcp_token instead of forwarding "" to upstream
- litellm_proxy_mcp_handler: use {**tool, "server_url": ...} spread instead
  of dict(tool) + mutation for shallow copy safety
- rest_endpoints: extract _oauth2_server_ids set comprehension to a named
  _get_oauth2_server_ids() helper for clarity; add Set to typing imports
- test_rest_endpoints: add tests for name→UUID resolution path,
  access-denied when resolved UUID not in allowed list, and OAuth2 user
  token injection for single-server requests; fix fake_get_tools signature
  to accept extra_headers kwarg

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-11 22:07:02 -07:00
..
_experimental/mcp_server fix(mcp): OAuth2 chat connect - tools fetch, auth, and status fixes (#23406) 2026-03-11 22:07:02 -07:00
agent_endpoints fix(tests): restore litellm_params=None on mock agent in a2a invoke test (#23125) 2026-03-09 07:16:02 -07:00
anthropic_endpoints
auth Allow proxy_admin_viewer to access audit log endpoints 2026-03-11 20:07:51 -07:00
client
common_utils Merge pull request #20688 from BerriAI/litellm_budget_tier_enforcement_for_keys 2026-03-06 20:44:58 -08:00
db Revert "feat(proxy): add Prisma DB pool and engine health metrics to Promethe…" 2026-03-09 14:55:11 -07:00
discovery_endpoints Support auto_redirect_ui_login_to_sso in config.yaml general_settings 2026-03-11 11:34:17 -07:00
experimental/mcp_server
google_endpoints
guardrails Merge branch 'main' into litellm_oss_staging_03_10_2026 2026-03-11 18:32:17 +05:30
health_endpoints Prisma DB Failure Detection and Self-Healing (#21059) 2026-03-05 13:44:49 -08:00
hooks Agents - add max budget + tpm/rpm limiting per agent AND per agent session (#22849) 2026-03-07 19:12:42 -08:00
image_endpoints
management_endpoints Merge pull request #23415 from BerriAI/litellm_style-created-by-not-uuid 2026-03-11 19:53:39 -07:00
management_helpers Fix mcp_tool_permissions JSON string deserialization in _resolve_team_allowed_mcp_servers 2026-03-11 00:23:40 -07:00
middleware feat: add in_flight_requests metric to /health/backlog + prometheus (#22319) 2026-02-27 18:00:50 -08:00
openai_files_endpoint CircleCI test stability (#23055) 2026-03-07 15:19:39 -08:00
pass_through_endpoints fix(proxy): preserve multipart/form-data boundary in passthrough endpoints 2026-03-11 16:52:02 +05:30
policy_engine
prompts
public_endpoints [Feature] Add /public/endpoints endpoint for provider endpoint support 2026-02-26 18:17:37 -08:00
rag_endpoints
response_api_endpoints
spend_tracking Fix TypeError in _is_master_key when api_key is None 2026-03-11 11:01:29 -07:00
test_configs
ui_crud_endpoints [Fix] PATCH /update/ui_settings now merges with existing record instead of overwriting 2026-03-05 15:49:40 -08:00
vector_store_endpoints
__init__.py
conftest.py
test_aiohttp_cleanup_closed.py
test_api_key_masking_in_errors.py
test_audio_speech_prometheus_hooks.py fix req changes 2026-02-28 21:32:57 +05:30
test_batch_expiry.py fix(proxy): improve team expiry enforcement validation 2026-03-03 17:29:39 -08:00
test_batch_metadata_none_fix.py
test_caching_routes.py
test_chat_completion_metadata.py
test_common_request_processing.py Bug Fix: auto-inject prompt caching support for Gemini models (#21881) 2026-03-03 20:25:35 -08:00
test_custom_proxy.py
test_empty_model_list.py [Release Fix] (#22411) 2026-02-28 09:46:35 -08:00
test_enforce_user_param.py
test_fallback_management_endpoints.py
test_fastapi_offline_routes.py
test_health_check_functions.py
test_health_check_max_tokens.py add docs and formatting 2026-02-28 14:08:09 +05:30
test_litellm_pre_call_utils.py Bug Fix: auto-inject prompt caching support for Gemini models (#21881) 2026-03-03 20:25:35 -08:00
test_model_dump_with_preserved_fields.py
test_model_id_header_propagation.py
test_prometheus_cleanup.py Add Prometheus child_exit cleanup for gunicorn workers 2026-02-27 16:11:15 -08:00
test_proxy_cli.py test: assert setup_database called with correct args 2026-03-10 18:31:04 +05:30
test_proxy_server.py Fix inflight mypy 2026-03-02 19:41:32 +05:30
test_proxy_types.py fix: Add PROXY_ADMIN role to system user for key rotation (#21896) 2026-02-27 19:11:29 -08:00
test_proxy_utils.py [Feat[ extends OAuth2 M2M authentication support to info routes (/key/info, /team/info, /user/info, /model/info) (#22713) 2026-03-06 17:29:25 -08:00
test_pyroscope.py
test_response_model_sanitization.py
test_route_a2a_models.py
test_route_llm_request.py
test_shared_health_check.py
test_spend_log_cleanup.py Fix spend log cleanup: lock tracking, integer retention, skip log level 2026-03-03 10:12:08 -08:00
test_swagger_chat_completions.py [Release Fix] (#22411) 2026-02-28 09:46:35 -08:00
test_team_member_update.py
test_tools_allowlist_enforcement.py Bug Fix: auto-inject prompt caching support for Gemini models (#21881) 2026-03-03 20:25:35 -08:00
test_update_llm_router_resilience.py fix(proxy): isolate get_config failures from model loading in sync loop 2026-02-26 17:49:44 -03:00