Skip to content

fix(tests): Add missing mocks for MCP IP filtering and updated APIs#20652

Merged
ishaan-jaff merged 1 commit intomainfrom
litellm_fix_mcp_oauth_tests
Feb 7, 2026
Merged

fix(tests): Add missing mocks for MCP IP filtering and updated APIs#20652
ishaan-jaff merged 1 commit intomainfrom
litellm_fix_mcp_oauth_tests

Conversation

@shin-bot-litellm
Copy link
Collaborator

Summary

Fixes 15 failing tests in the MCP test suite after the IP-based access control feature was added (#20620, #20607).

Failing Tests Fixed

OAuth Discoverable Endpoints (test_discoverable_endpoints.py)

  • test_authorize_endpoint_forwards_pkce_parameters
  • test_authorize_endpoint_includes_response_type
  • test_authorize_endpoint_respects_x_forwarded_host
  • test_authorize_endpoint_respects_x_forwarded_proto
  • test_oauth_authorization_server_respects_x_forwarded_proto
  • test_oauth_protected_resource_respects_x_forwarded_proto
  • test_register_client_remote_registration_success
  • test_token_endpoint_forwards_code_verifier
  • test_token_endpoint_respects_x_forwarded_host
  • test_token_endpoint_respects_x_forwarded_proto

Fix: Added autouse fixture to mock IPAddressUtils.get_mcp_client_ip to return None, bypassing IP-based access control in tests.

A2A Endpoints (test_a2a_endpoints.py)

  • test_invoke_agent_a2a_adds_litellm_data

Fix: Changed mock path from litellm.proxy.litellm_pre_call_utils.add_litellm_data_to_request to litellm.proxy.common_request_processing.add_litellm_data_to_request (where it's actually called).

MCP Guardrail Handler (test_mcp_guardrail_handler.py)

  • test_process_input_messages_skips_when_no_messages
  • test_process_input_messages_updates_content

Fix: Updated tests to match new handler behavior - handler now checks for mcp_tool_name (not messages array) and passes tools (not texts) to guardrail.

MCP Path-Based Segregation (test_user_api_key_auth_mcp.py)

  • test_mcp_path_based_server_segregation

Fix: Added client_ip to get_auth_context() unpacking (now returns 7 values instead of 6).

MCP Registry (test_mcp_management_endpoints.py)

  • test_registry_returns_entries_when_enabled

Fix: Added mock for get_filtered_registry() (not just get_registry()) since the registry endpoint uses get_filtered_registry for IP filtering.

Root Cause

The IP-based access control feature (#20620) added a new client_ip parameter throughout the MCP codebase. Tests were not updated to:

  1. Mock the IP address extraction
  2. Handle the new return value from get_auth_context()
  3. Mock get_filtered_registry() instead of just get_registry()

Tests verified locally - all 15 previously failing tests now pass

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
@vercel
Copy link

vercel bot commented Feb 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Feb 7, 2026 7:07pm

Request Review

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Shin seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 7, 2026

Greptile Overview

Greptile Summary

This PR updates the MCP-related test suite to match the recent IP-based access control change and a few API surface shifts. It:

  • Adds a global (autouse) mock for MCP client IP detection in the discoverable OAuth endpoint tests to avoid IP filtering interfering with unit tests.
  • Fixes the A2A endpoint test to patch add_litellm_data_to_request at the actual call site (common_request_processing).
  • Updates guardrail translation tests to assert the handler now sends tool definitions to the guardrail when mcp_tool_name is present.
  • Updates MCP path-based segregation tests to unpack the newly added client_ip return value.
  • Updates the MCP registry endpoint test to mock get_filtered_registry() since the endpoint now filters by client IP.

Overall, these are test-only adjustments intended to restore stability after the MCP IP filtering feature landed, with the main concern being that the new IP mock currently patches a single call site rather than the source symbol used across modules.

Confidence Score: 4/5

  • This PR is likely safe to merge after fixing a brittle test mock that patches an overly specific import path.
  • Changes are limited to tests and mostly align mocks with updated call sites/APIs. The main remaining issue is the autouse IP mock patching discoverable_endpoints’ reference instead of the source IPAddressUtils.get_mcp_client_ip, which can re-break tests if other modules/paths are exercised or imports change. Guardrail tests also lost some behavioral coverage but that’s lower severity if MCP tools are intentionally non-modifiable.
  • tests/test_litellm/proxy/_experimental/mcp_server/test_discoverable_endpoints.py

Important Files Changed

Filename Overview
tests/test_litellm/proxy/_experimental/mcp_server/auth/test_user_api_key_auth_mcp.py Updates MCP path-based segregation test to unpack new client_ip value from get_auth_context().
tests/test_litellm/proxy/_experimental/mcp_server/guardrail_translation/test_mcp_guardrail_handler.py Reworks guardrail handler tests to assert tool-based inputs; drops coverage of guardrail text-modification behavior.
tests/test_litellm/proxy/_experimental/mcp_server/test_discoverable_endpoints.py Adds autouse fixture patching get_mcp_client_ip at a single import path; may not bypass IP filtering if other modules call the source function directly.
tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py Fixes mock patch target for add_litellm_data_to_request to match actual call site in common_request_processing.
tests/test_litellm/proxy/management_endpoints/test_mcp_management_endpoints.py Adds missing mock for get_filtered_registry to match management endpoint behavior that filters registry by client IP.

Sequence Diagram

sequenceDiagram
    participant T as Tests
    participant DE as discoverable_endpoints
    participant MEP as mcp_management_endpoints
    participant IPU as IPAddressUtils
    participant MSM as MCPServerManager

    T->>DE: authorize()/token_endpoint()/register_client()
    DE->>IPU: get_mcp_client_ip(request)
    Note over T,IPU: PR adds autouse patch returning None (in DE module)
    DE->>DE: build redirect/perform token exchange

    T->>MEP: GET /v1/mcp/registry.json
    MEP->>IPU: get_mcp_client_ip(request)
    MEP->>MSM: get_filtered_registry(client_ip)
    MSM-->>MEP: filtered servers
    MEP-->>T: {servers: builtin + filtered entries}
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +8 to +20
@pytest.fixture(autouse=True)
def mock_mcp_client_ip():
"""Mock IPAddressUtils.get_mcp_client_ip to return None for all tests.

This bypasses IP-based access control in tests, since the MCP server's
available_on_public_internet defaults to False and mock requests don't
have proper client IP context.
"""
with patch(
"litellm.proxy._experimental.mcp_server.discoverable_endpoints.IPAddressUtils.get_mcp_client_ip",
return_value=None,
):
yield
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Autouse patch targets wrong symbol

This fixture patches IPAddressUtils.get_mcp_client_ip only at litellm.proxy._experimental.mcp_server.discoverable_endpoints..., so any code under test that calls the source litellm.proxy.auth.ip_address_utils.IPAddressUtils.get_mcp_client_ip (or other modules’ imported references) won’t be affected. That makes the “bypass IP-based access control in tests” brittle across refactors and can re-break tests.

Consider patching the source symbol (litellm.proxy.auth.ip_address_utils.IPAddressUtils.get_mcp_client_ip) instead of a single call site.

Comment on lines 20 to +24
async def apply_guardrail(self, inputs, request_data, input_type, **kwargs):
self.call_count += 1
self.last_inputs = inputs

if self.return_texts is not None:
return {"texts": self.return_texts}

texts = inputs.get("texts", [])
return {"texts": [f"{text} [SAFE]" for text in texts]}
self.last_request_data = request_data
return None # Guardrail doesn't modify for MCP tools
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lost behavior coverage

MockGuardrail.apply_guardrail() now always returns None and the tests only assert the handler returns data unchanged, which removes coverage for the handler’s behavior when a guardrail returns a modification payload. If MCPGuardrailTranslationHandler.process_input_messages() still supports applying updates from guardrail output, it’d be good to keep at least one test asserting those updates are handled (adapted to the new tool-based shape).

@ishaan-jaff ishaan-jaff merged commit 1477b4b into main Feb 7, 2026
31 of 57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants