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>
Add cheap .get() guards in should_run_callback() to short-circuit
the expensive EnterpriseCallbackControls.is_callback_disabled_dynamically()
call. When neither litellm_disabled_callbacks nor x-litellm-disable-callbacks
header is set (the common case), the enterprise function is never entered,
reducing should_run_callback from ~485ms to ~93-165ms across 54k calls.
CallTypes(call_type) was constructing an enum from string on every call,
taking ~4.6µs/call (69.6% of function time). Replace with a frozenset
membership test for ~0.8µs/call (8.3x faster).
* perf: Optimize get_litellm_params with sparse kwargs extraction
- Add _OPTIONAL_KWARGS_KEYS frozenset for O(1) lookups
- Replace 28 unconditional kwargs.get() calls with sparse extraction
- Only add kwargs keys that are actually present in the dict
- Simplify _get_base_model_from_litellm_call_metadata by removing redundant None checks
This reduces get_litellm_params() time by ~31% (743ms → 509ms across 6000 calls)
and Logging.__init__ total time by ~24% (1.61s → 1.23s).
* test: add unit tests for get_litellm_params sparse kwargs extraction
* perf: add early-exit guards in completion_cost for unused features
Skip function calls to get_cost_for_built_in_tools, _apply_cost_discount,
_apply_cost_margin, and _store_cost_breakdown_in_logging_obj when their
respective features are not configured. Reduces completion_cost() time
by ~20% (4.39s → 3.53s over 6K requests) for the common case where
built-in tools, discounts, margins, and logging object are not active.
* fix: always call get_cost_for_built_in_tools regardless of standard_built_in_tools_params
The function can detect web search usage from the usage object (e.g.
server_tool_use.web_search_requests, prompt_tokens_details.web_search_requests)
even when standard_built_in_tools_params is None, so guarding on it can
under-count cost for providers like Vertex AI and Anthropic.
Adds regression test for completion_cost with web search in usage but
no standard_built_in_tools_params.
* fix(tests): Mock async_container_create_handler for async router test
The test was mocking container_create_handler (sync), but
router.acreate_container uses _is_async=True which calls
async_container_create_handler. This caused the test to hit
the real OpenAI API.
Fixed by using AsyncMock on async_container_create_handler.
* fix(tests): Use uuid for unique model name in scientific notation test
The test was using a static "unique" model name which could cause
conflicts when running tests in parallel (-n 16 in CI). Using uuid
ensures truly unique names to prevent test pollution.
---------
Co-authored-by: Shin <shin@openclaw.ai>
* perf: Optimize get_standard_logging_metadata with set intersection
- Cache StandardLoggingMetadata.__annotations__.keys() as module-level frozenset
- Use set intersection to iterate only keys present in both metadata and supported keys
- Single lookup for user_api_key instead of 3 separate .get() calls
Results:
- get_standard_logging_metadata: 1.55s → 1.41s (9.2% faster)
* test: add unit tests for get_standard_logging_metadata non-string user_api_key handling
* fix(tests): Fix sendgrid email tests to properly mock httpx client
The tests were potentially hitting the real SendGrid API because the mock
was patching get_async_httpx_client() but the actual client could be cached
or the mock timing could be off.
Fix by directly replacing logger.async_httpx_client after instantiation,
which guarantees the mock is used regardless of caching or initialization
timing issues.
Changes:
- Replace mock_httpx_client fixture with simpler mock_async_client fixture
- Directly inject mock client into logger instance after creation
- Remove respx decorator (no longer needed with direct injection)
- Simplify test structure while maintaining same assertions
* fix(lint): remove unused imports from SendGrid test
Replace text-embedding-004 with gemini-embedding-001.
The old model was deprecated and returns 404:
'models/text-embedding-004 is not found for API version v1beta'
Co-authored-by: Shin <shin@openclaw.ai>
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
- 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
* 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.
Create fresh mock objects within the test instead of reusing mocks
from setUp that have side_effect configured. The setUp's side_effect
on mock_langfuse_client.trace can interfere with return_value settings
when tests try to reset and reconfigure mocks.
Using dedicated mock objects for this test avoids state pollution
from setUp's side_effect configuration and makes the test more
deterministic in parallel execution environments.
Set cached tokenizer config directly and mock both sync and async
tokenizer functions to avoid race conditions when running with
parallel test execution (-n 16).
The issue was that parallel tests could populate the
litellm.known_tokenizer_config cache between clearing it and
when the code checked it. This caused the sync code path to be
used instead of the async path, bypassing the mocked async functions.
Fix:
1. Set cache directly instead of clearing it
2. Also mock sync versions _get_tokenizer_config and _get_chat_template_file
This ensures the test is deterministic regardless of test execution order.
Unify follow-up fixes for Opus 4.6 pricing and routing metadata into
a single changeset.
Set long-context-capable Opus 4.6 entries to 1M input tokens where
>200K pricing is defined, align alias and dated capability metadata,
and add Bedrock Converse v1 IDs with and without :0 suffixes.
Keep regional endpoint pricing at a 10% premium over global entries
and mirror all cost-map changes in the backup file used for local
loading and offline fallback behavior.
Extend Opus 4.6 regression tests to verify metadata parity, Bedrock
regional pricing parity across :0 and non-:0 IDs, and converse model
registration in constants and runtime model sets.
Add Claude Opus 4.6 entries for Anthropic, Bedrock Converse, and Vertex AI.
Align pricing and capability metadata with Anthropic docs, including
long-context rates, above-200k prompt-caching rates, prefill removal,
and tool-use system prompt token counts.
Register the Bedrock Converse model ID in constants and add targeted
tests to validate model map values and converse registration.