mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(mcp): resolve OAuth endpoints by server_id with IP access checks
The OAuth broker endpoints use get_mcp_server_by_name() to resolve the MCP server from the URL path. The LiteLLM UI sends server_id (hash) in the path, causing lookup failure and "authorization url is not set". Add get_mcp_server_by_id() as a fallback at all five call sites in discoverable_endpoints.py. Pass client_ip to the ID-based lookup and enforce _is_server_accessible_from_ip() so that external clients cannot bypass IP access controls by supplying a server_id directly. Fixes #30997
This commit is contained in:
parent
cdecfe24e1
commit
88a85f40d8
2 changed files with 16 additions and 7 deletions
|
|
@ -612,7 +612,7 @@ async def authorize(
|
|||
else None
|
||||
)
|
||||
if mcp_server is None and lookup_name:
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(lookup_name)
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(lookup_name, client_ip=client_ip)
|
||||
if mcp_server is None and mcp_server_name is None:
|
||||
mcp_server = _resolve_oauth2_server_for_root_endpoints(client_ip=client_ip)
|
||||
if mcp_server is None:
|
||||
|
|
@ -676,7 +676,7 @@ async def token_endpoint(
|
|||
lookup_name, client_ip=client_ip
|
||||
)
|
||||
if mcp_server is None and lookup_name:
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(lookup_name)
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(lookup_name, client_ip=client_ip)
|
||||
if mcp_server is None and mcp_server_name is None:
|
||||
mcp_server = _resolve_oauth2_server_for_root_endpoints(client_ip=client_ip)
|
||||
if mcp_server is None:
|
||||
|
|
@ -997,7 +997,7 @@ async def _build_oauth_protected_resource_response(
|
|||
)
|
||||
if mcp_server is None:
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(
|
||||
mcp_server_name
|
||||
mcp_server_name, client_ip=client_ip
|
||||
)
|
||||
|
||||
# Build resource URL based on the pattern
|
||||
|
|
@ -1154,7 +1154,7 @@ def _build_oauth_authorization_server_response(
|
|||
)
|
||||
if mcp_server is None:
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(
|
||||
mcp_server_name
|
||||
mcp_server_name, client_ip=client_ip
|
||||
)
|
||||
|
||||
return {
|
||||
|
|
@ -1324,7 +1324,7 @@ async def register_client(request: Request, mcp_server_name: Optional[str] = Non
|
|||
)
|
||||
if mcp_server is None:
|
||||
mcp_server = global_mcp_server_manager.get_mcp_server_by_id(
|
||||
mcp_server_name
|
||||
mcp_server_name, client_ip=client_ip
|
||||
)
|
||||
if mcp_server is None:
|
||||
return dummy_return
|
||||
|
|
|
|||
|
|
@ -4018,13 +4018,22 @@ class MCPServerManager:
|
|||
)
|
||||
return IPAddressUtils.is_internal_ip(client_ip, internal_networks)
|
||||
|
||||
def get_mcp_server_by_id(self, server_id: str) -> Optional[MCPServer]:
|
||||
def get_mcp_server_by_id(
|
||||
self, server_id: str, client_ip: Optional[str] = None
|
||||
) -> Optional[MCPServer]:
|
||||
"""
|
||||
Get the MCP Server from the server id
|
||||
Get the MCP Server from the server id.
|
||||
|
||||
Args:
|
||||
server_id: The server ID to look up.
|
||||
client_ip: Optional client IP for access control. When provided,
|
||||
non-public servers are hidden from external IPs.
|
||||
"""
|
||||
registry = self.get_registry()
|
||||
for server in registry.values():
|
||||
if server.server_id == server_id:
|
||||
if not self._is_server_accessible_from_ip(server, client_ip):
|
||||
return None
|
||||
return server
|
||||
return None
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue