Commit graph

1090 commits

Author SHA1 Message Date
yuneng-jiang
f49e4bf299 Merge pull request #21503 from BerriAI/litellm_sso_role_map
fix(sso): preserve SSO role regardless of role_mappings config
2026-02-19 16:36:12 -08:00
shin-bot-litellm
1477b4b46b
fix(tests): Add missing mocks for MCP IP filtering and updated APIs (#20652)
Fixes 15 failing tests in the MCP test suite:

1. **OAuth discoverable endpoints** (test_discoverable_endpoints.py):
   - Added autouse fixture to mock IPAddressUtils.get_mcp_client_ip
   - This bypasses IP-based access control which was blocking server lookup
   - Fixes: test_authorize_*, test_token_*, test_oauth_*, test_register_*

2. **A2A endpoints** (test_a2a_endpoints.py):
   - Fixed mock path for add_litellm_data_to_request
   - Was patching litellm_pre_call_utils but function is called from common_request_processing

3. **MCP guardrail handler** (test_mcp_guardrail_handler.py):
   - Updated tests to match new handler behavior
   - Handler now passes tools (not texts) to guardrail
   - Handler checks for mcp_tool_name (not messages array)

4. **MCP path-based segregation** (test_user_api_key_auth_mcp.py):
   - Added client_ip to get_auth_context unpacking (7 values now)
   - get_auth_context was updated to include client_ip

5. **MCP registry** (test_mcp_management_endpoints.py):
   - Added mock for get_filtered_registry (not just get_registry)
   - Registry endpoint uses get_filtered_registry for IP filtering

Co-authored-by: Shin <shin@openclaw.ai>
2026-02-07 11:30:49 -08:00
Ishaan Jaffer
1780b1716f filter_server_ids_by_ip 2026-02-07 10:08:20 -08:00
yuneng-jiang
271877ffb5
Merge pull request #20623 from BerriAI/litellm_user_id_fix
[Fix] /key/list user_id Empty String Edge Case
2026-02-06 18:06:59 -08:00
yuneng-jiang
4d1b5d80ae fixing user_id 2026-02-06 17:55:45 -08:00
Ishaan Jaff
81146472cb
[Feat] MCP Gateway - Allow setting MCP Servers as Private/Public available on Internet (#20607)
* update MCPAuthenticatedUser

* add available_on_public_internet for MCPs

* update claude.md

* init IPAddressUtils

* init available_on_public_internet

* add on REST endpoints

* filter with IP

* TestIsInternalIp

* _extract_mcp_headers_from_request

* init get_mcp_client_ip

* _get_general_settings

* allowed_server_ids

* address PR comments

* get_mcp_server_by_name fix

* fix server

* fix review comments

* get_public_mcp_servers

* address _get_allowed_mcp_servers
2026-02-06 17:51:20 -08:00
michelligabriele
f4a0b80a25
fix(sso): extract user roles from JWT access token for Keycloak compatibility (#20591)
Keycloak (and similar OIDC providers) include role claims in the JWT
access token but not in the UserInfo endpoint response. Previously,
roles were only extracted from UserInfo, causing all SSO users to
default to internal_user_view_only regardless of their actual role.

Changes:
- Extract user roles from JWT access token in process_sso_jwt_access_token()
  when UserInfo doesn't provide them (tries role_mappings first, then
  GENERIC_USER_ROLE_ATTRIBUTE)
- Handle list-type role values in get_litellm_user_role() since Keycloak
  returns roles as arrays (e.g. ["proxy_admin"] instead of "proxy_admin")
- Add 9 new unit tests covering role extraction and list handling
- Update 3 existing tests for new JWT decode behavior

Closes #20407
2026-02-06 16:05:51 -08:00
yuneng-jiang
218373c427
Merge pull request #20205 from BerriAI/litellm_router_search_fix
[Re-issue: Fix] Keys and Teams Router Setting + Allow Override of Router Settings
2026-02-06 15:42:22 -08:00
yuneng-jiang
fd3ca081cc use cached keys and teams for router settings 2026-02-06 15:07:29 -08:00
michelligabriele
6a213fc3bc
fix(mcp): resolve OAuth2 'Capabilities: none' bug for upstream MCP servers (#20602)
- process_mcp_request() now falls back to OAuth2 passthrough when Authorization header contains a non-LiteLLM token (catches HTTPException and ProxyException 401/403)
- MCPClient._get_auth_headers() adds missing MCPAuth.oauth2 case
2026-02-06 15:00:35 -08:00
yuneng-jiang
400e560ee5 Merge remote-tracking branch 'origin' into litellm_router_search_fix 2026-02-06 14:08:55 -08:00
Alexsander Hamir
09fb6d0087
Warn when budget lookup fails; cache won't populate (#20545)
* Warn when budget lookup fails; cache won't populate

- Add _log_budget_lookup_failure helper in auth_checks.py
- Log at WARNING in get_user_object, get_team_object, get_key_object
  when DB lookups fail (schema mismatch, etc.)
- Add schema migration hint for prisma/db errors
- Add dry-run test for _log_budget_lookup_failure

* fix: skip budget lookup failure log for expected user-not-found case

Avoid logging 'cache will not be populated' when the user simply doesn't
exist - not caching is correct behavior in that case. Only log for
unexpected errors (schema, DB, etc.) where the message is meaningful.
2026-02-06 09:24:44 -08:00
Sameer Kankute
db8423b799 Fix: test_json_response_nested_json_schema 2026-02-06 18:52:04 +05:30
yuneng-jiang
523a36ed53
Merge pull request #20530 from BerriAI/litellm_ui_team_soft_budget
[Feature] Add soft_budget to Team Table + Create/Update Endpoints
2026-02-05 15:52:17 -08:00
yuneng-jiang
a17efa1c8e Add soft_budget to team table and create update endpoints 2026-02-05 14:43:48 -08:00
Ishaan Jaff
887a907e42
[Fix] Guardrails API - Ensure OpenAI Moderations Guard works with OpenAI Embeddings (#20523)
* init OpenAIEmbeddingsHandler

* init apply_guardrail

* use apply guardrails for OpenAI moderations

* test_embeddings_handler_string_input

* test_openai_moderation_guardrail_apply_guardrail

* fix typing

* test_openai_moderation_responses_api_input_field

* test fixes
2026-02-05 14:40:15 -08:00
Ishaan Jaff
d2bd029fa4
[Fix] 404 Not Found on /api/event_logging/batch endpoint (#20504)
* fix typing

* add event_logging_batch

* TestEventLoggingBatchEndpoint
2026-02-05 10:58:08 -08:00
Sameer Kankute
453d1bd5e1
Merge branch 'main' into litellm_oss_staging_02_04_2026 2026-02-05 12:19:03 +05:30
Sameer Kankute
5422a5962e Fix test_route_a2a_model_bypasses_router 2026-02-05 09:47:05 +05:30
Ishaan Jaff
6a73e5bd37
Revert "fix(a2a): use text/event-stream SSE format for message/stream endpoin…" (#20446)
This reverts commit 0209b214ac.
2026-02-04 16:08:22 -08:00
shin-bot-litellm
0209b214ac
fix(a2a): use text/event-stream SSE format for message/stream endpoint (#20365)
* fix(a2a): use text/event-stream SSE format for message/stream endpoint

The A2A gateway's streaming response was using application/x-ndjson
Content-Type and raw NDJSON body format. The A2A protocol spec requires
text/event-stream with SSE framing (data: ...\n\n).

The official a2a-sdk client validates the Content-Type header and raises
SSEError when it doesn't contain text/event-stream.

Changes:
- Changed media_type from application/x-ndjson to text/event-stream
- Updated response body to use SSE framing (data: prefix + \n\n suffix)
- Added tests validating Content-Type and SSE body format

Fixes #20278

* Potential fix for code scanning alert no. 4045: Information exposure through an exception

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* test(a2a): add manual SSE format validation script

Adds a manual test script that:
1. Starts a real A2A agent on port 10001
2. Starts LiteLLM proxy with the agent registered
3. Makes a streaming request to the proxy's A2A gateway
4. Validates Content-Type header is text/event-stream
5. Validates body uses SSE framing (data: ...\n\n)

Run: python tests/a2a_manual/test_a2a_sse_manual.py

---------

Co-authored-by: shin-bot-litellm <shin-bot-litellm@users.noreply.github.com>
Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-02-04 16:07:17 -08:00
yuneng-jiang
a16faa9e0a
Merge pull request #20394 from BerriAI/litellm_spend_fix_2
[Fix] Unique Constraint on Daily Tables + Logging When Updates Fail
2026-02-04 09:42:46 -08:00
Sameer Kankute
a86e501632
Merge pull request #20407 from BerriAI/litellm_key_mcp_permissions
Add Key info endpoint object permission data
2026-02-04 17:56:05 +05:30
Sameer Kankute
b2feedc469
Merge pull request #20318 from BerriAI/litellm_oss_staging_02_03_2026
feat(guardrails): implement team-based isolation guardrails mgmnt (#1…
2026-02-04 17:49:30 +05:30
Sameer Kankute
54b5c7d2cd Fix: litellm/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_grayswan.py 2026-02-04 17:35:26 +05:30
Sameer Kankute
fc873d8867 Fix mypy issues 2026-02-04 14:40:08 +05:30
Sameer Kankute
42561729ee Add Key info endpoint object permission data 2026-02-04 14:21:19 +05:30
akraines
774a015aad
fix: Preserve streaming content on guardrail-sampled chunks (#20027)
The unified guardrail's streaming iterator hook processes every Nth
chunk (sampling_rate, default 5). On each sampled chunk it calls
process_output_streaming_response, which combines all accumulated text
into the first chunk and clears all subsequent chunks to "".

The hook then yielded `processed_items[-1]` — the last item, whose
content had been cleared to "". This permanently lost every Nth
chunk's content, causing random missing words/tokens in the client
output (observed in Roo Code, Open WebUI, etc.).

Fix: deep-copy the current chunk before guardrail processing runs,
then yield the original (unmodified) chunk. The guardrail validation
still executes and can block if it detects a problem, but the stream
content is preserved.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 22:44:30 -08:00
Krish Dholakia
ca34b4ee13
Revert "feat(guardrails): implement team-based isolation guardrails mgmnt (#1…" (#20393)
This reverts commit 76a399ba69.
2026-02-03 20:55:46 -08:00
yuneng-jiang
9ce55057ab Adding logging for when batching fails 2026-02-03 20:54:40 -08:00
yuneng-jiang
30027d2928 save empty endpoint as string 2026-02-03 20:26:57 -08:00
yuneng-jiang
dc07a6922f
Merge pull request #20371 from BerriAI/litellm_config_search_tools
[Feature] Include Config Defined Search Tools in /search_tools/list
2026-02-03 20:00:21 -08:00
Sameer Kankute
25fa1ad4e7
Merge pull request #20386 from naaa760/fix/extra-head-chat-comp-brid
fix(proxy): forward extra headers in chat
2026-02-04 09:11:43 +05:30
Ishaan Jaff
66eadfabe4
[Bug] Ensure MCP permissions are enforced when using JWT Auth (#20383)
* fix: enforce team MCP permissions when using JWT authentication

Root cause: When JWT auth was used with teams in groups (via team_ids_jwt_field),
the team's MCP permissions were not being enforced because:

1. The default team_allowed_routes did not include mcp_routes
2. allowed_routes_check() failed for MCP endpoints like /mcp/tools/list
3. find_team_with_model_access() skipped the team due to failed route check
4. team_id was None in UserAPIKeyAuth
5. MCPRequestHandler._get_allowed_mcp_servers_for_team() returned empty list

Fix: Add 'mcp_routes' to the default team_allowed_routes in LiteLLM_JWTAuth.

This ensures that teams can access MCP endpoints by default, allowing the
team's MCP server permissions to be properly enforced.

Added tests:
- test_reproduce_jwt_mcp_enforcement_issue: Reproduces the exact bug scenario
- test_verify_mcp_routes_in_default_team_allowed_routes: Verifies fix
- test_mcp_route_check_passes_for_team: Verifies route check works

Co-authored-by: ishaan <ishaan@berri.ai>

* test: add comprehensive E2E tests for JWT + team MCP permission enforcement

Added tests:
- test_e2e_jwt_team_mcp_permissions_enforced: Full E2E test verifying JWT auth
  with teams in groups properly sets team_id and MCPRequestHandler returns
  the team's MCP servers
- test_e2e_jwt_without_team_no_mcp_servers: Verifies no MCP servers returned
  when JWT has no teams
- test_e2e_jwt_team_mcp_key_intersection: Verifies intersection logic when
  both key and team have MCP permissions (result = intersection)

These tests verify the complete flow:
1. JWT token with team in groups field
2. JWT auth properly sets team_id on UserAPIKeyAuth
3. MCPRequestHandler.get_allowed_mcp_servers() returns team's MCP servers
4. Key/team permission intersection works correctly

Co-authored-by: ishaan <ishaan@berri.ai>

* test: add simple tests for JWT + MCP permission enforcement

Simple, focused tests that validate:
1. test_simple_jwt_mcp_permissions_enforced: JWT user with team gets team's MCP servers
2. test_simple_jwt_no_team_no_mcp_servers: JWT user without team gets no MCP servers
3. test_simple_jwt_team_id_required_for_mcp_permissions: Verifies team_id is required
4. test_jwt_auth_sets_team_id_for_mcp_route: JWT auth sets team_id for MCP routes

These tests directly verify the core MCP permission enforcement logic works
when using JWT authentication with teams.

Co-authored-by: ishaan <ishaan@berri.ai>

* Add test: MCP route without model still returns team_id

Co-authored-by: ishaan <ishaan@berri.ai>

* Add 2 debug logs for JWT+MCP troubleshooting

- handle_jwt.py: Log team route check result (team_id, route, is_allowed)
- user_api_key_auth_mcp.py: Log team_id when looking up MCP permissions

Co-authored-by: ishaan <ishaan@berri.ai>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: ishaan <ishaan@berri.ai>
2026-02-03 19:13:13 -08:00
yuneng-jiang
cf256c742f allow max_budget reset 2026-02-03 16:32:21 -08:00
yuneng-jiang
3e3b21e6c3 masking sensitive values 2026-02-03 16:09:37 -08:00
yuneng-jiang
23d9a89793 search tools list includes config defined search tools 2026-02-03 15:57:13 -08:00
Ishaan Jaff
d267c69086
[Feat] Use A2A registered agents with /chat/completions (#20362)
* test_a2a_registry_integration

* fix: render agents on model dropdown on UI

* init append_agents_to_model_group

* route_a2a_agent_request

* is_a2a_agent_model

* route_a2a_agent_request

* fix: error handling

* docs A2A usage

* docs fix

* feat: working A2a streaming

* fix transform
2026-02-03 15:25:38 -08:00
Xiaohan Fu
2b25d03046
Fix fail-open for grayswan and pass metadata to cygnal api endpoint (#19837)
* fix fail-open for grayswan; pass metadata to cygnal api endpoint; update docs

* pass litellm_metadata to cygnal in payload

* switch error msg to const, and clean exception handling.

* update pyproject.toml as requested

* Revert "update pyproject.toml as requested"

This reverts commit 4eece154d0.
2026-02-03 14:41:31 -08:00
Sameer Kankute
b7f0d05dfd
Merge pull request #20337 from BerriAI/main
update 02 staging PR
2026-02-03 17:08:01 +05:30
Sameer Kankute
9a6bafe89e Fix litellm/tests/test_litellm/proxy/_experimental/mcp_server/test_semantic_tool_filter.py tests 2026-02-03 15:01:10 +05:30
Harshit Jain
76a399ba69
feat(guardrails): implement team-based isolation guardrails mgmnt (#19889)
* feat(guardrails): implement team-based isolation guardrails mgmnt

* fix lint errors

* add allow_team_guardrail_config for admin permissions
2026-02-02 19:14:55 -08:00
Ishaan Jaff
079f49ff6a
[Feat] - MCP Semantic Filtering Support (#20296)
* init: SemanticMCPToolFilter

* init: SemanticToolFilterHook

* test_e2e_semantic_filter

* mock tests: test_semantic_filter_basic_filtering

* Update litellm/proxy/_experimental/mcp_server/semantic_tool_filter.py

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

* refactor folder/file organization

* docs fix

* fix filter

* fix: filter_tools

* fix linting tool filrer

* initialize_from_config

* fix: _expand_mcp_tools

* _initialize_semantic_tool_filter

* working: async_post_call_response_headers_hook

* clean up semantic tool filter

* add _initialize_semantic_tool_filter

* build_router_from_mcp_registry

* _get_tools_by_names

* fiix config

* async_post_call_response_headers_hook

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-02 18:28:53 -08:00
yuneng-jiang
edfe2394b9 reset_spend endpoint 2026-02-02 15:52:30 -08:00
shin-bot-litellm
31241416d4
feat: add base /scim/v2 endpoint for SCIM resource discovery (#20301)
Add the following SCIM v2 discovery endpoints per RFC 7643/7644:

- GET /scim/v2 - Base resource discovery (ListResponse of ResourceTypes)
- GET /scim/v2/ResourceTypes - List all supported resource types
- GET /scim/v2/ResourceTypes/{id} - Get a specific resource type (User/Group)
- GET /scim/v2/Schemas - List all supported schemas
- GET /scim/v2/Schemas/{uri} - Get a specific schema by URI

These endpoints are required by identity providers (Okta, Azure AD, etc.)
for SCIM resource discovery. Previously, GET /scim/v2 returned 404.

Also adds SCIMResourceType, SCIMSchema, and SCIMSchemaAttribute Pydantic
models to the SCIM types module.

Fixes #20295
2026-02-02 14:27:00 -08:00
yuneng-jiang
f1227ce5a8
Merge pull request #20111 from BerriAI/litellm_sso_map_teams
[Feature] SSO Config Team Mappings
2026-02-02 14:18:25 -08:00
shin-bot-litellm
923b1cfd92
fix: MCP "Session not found" error on VSCode reconnect (#20298)
* fix: strip stale mcp-session-id header to prevent 'Session not found' error loop

When VSCode reconnects to LiteLLM's MCP endpoint after a reload, it sends
a stale mcp-session-id header. The session was already cleaned up, causing
a 404 'Session not found' error. VSCode retries with the same stale ID,
creating an infinite error loop.

Before forwarding requests to the StreamableHTTP session manager, check if
the mcp-session-id header references a valid session. If the session doesn't
exist, strip the header so a new session is created automatically.

Fixes #20292

* refactor: extract stale session handling into _strip_stale_mcp_session_header helper
2026-02-02 14:15:31 -08:00
yuneng-jiang
1f51f067eb Merge remote-tracking branch 'origin' into litellm_sso_map_teams 2026-02-02 12:40:12 -08:00
yuneng-jiang
b30c17c72d
Merge pull request #20210 from BerriAI/litellm_key_block_rev
[Fix] Remove Key Blocking on Login
2026-02-02 12:00:26 -08:00
Hi120ki
c9757cd0d7 fix(guardrails): populate applied_guardrails when Model Armor blocks content (#20034)
Previously, when Model Armor guardrail blocked a request/response,
the `applied_guardrails` field was not populated in the logs because
`add_guardrail_to_applied_guardrails_header()` was called after the
HTTPException was raised.

This fix moves the `add_guardrail_to_applied_guardrails_header()` call
to before the blocking check in all hooks:
- async_pre_call_hook (pre_call mode)
- async_moderation_hook (during_call mode)
- async_post_call_success_hook (post_call mode)
- async_post_call_streaming_iterator_hook (streaming)

This ensures that even when a guardrail blocks content, the guardrail
name is properly recorded in the logs for observability.

Added regression tests to verify applied_guardrails is populated when
content is blocked.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-02 18:21:44 +05:30