mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
feat(mcp_server_manager.py): initial commit adding allowed params support
allow admin to specify which parameters to allow/disallow by MCP tool
This commit is contained in:
parent
1c56a0d856
commit
dd4249db78
3 changed files with 110 additions and 7 deletions
|
|
@ -215,6 +215,7 @@ class MCPServerManager:
|
|||
extra_headers=server_config.get("extra_headers", None),
|
||||
allowed_tools=server_config.get("allowed_tools", None),
|
||||
disallowed_tools=server_config.get("disallowed_tools", None),
|
||||
allowed_params=server_config.get("allowed_params", None),
|
||||
access_groups=server_config.get("access_groups", None),
|
||||
)
|
||||
self.config_mcp_servers[server_id] = new_server
|
||||
|
|
@ -602,6 +603,60 @@ class MCPServerManager:
|
|||
return tool_name not in server.disallowed_tools
|
||||
return True
|
||||
|
||||
def filter_allowed_params(
|
||||
self, tool_name: str, arguments: Dict[str, Any], server: MCPServer
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Filter arguments to only include allowed parameters for the given tool.
|
||||
|
||||
Args:
|
||||
tool_name: Name of the tool (with or without prefix)
|
||||
arguments: Dictionary of arguments to filter
|
||||
server: MCPServer configuration
|
||||
|
||||
Returns:
|
||||
Filtered dictionary containing only allowed parameters
|
||||
|
||||
Raises:
|
||||
HTTPException: If allowed_params is configured for this tool but arguments contain disallowed params
|
||||
"""
|
||||
from litellm.proxy._experimental.mcp_server.utils import (
|
||||
get_server_name_prefix_tool_mcp,
|
||||
)
|
||||
|
||||
# If no allowed_params configured, return all arguments
|
||||
if not server.allowed_params:
|
||||
return arguments
|
||||
|
||||
# Get the unprefixed tool name to match against config
|
||||
unprefixed_tool_name, _ = get_server_name_prefix_tool_mcp(tool_name)
|
||||
|
||||
# Check both prefixed and unprefixed tool names
|
||||
allowed_params_list = server.allowed_params.get(
|
||||
tool_name
|
||||
) or server.allowed_params.get(unprefixed_tool_name)
|
||||
|
||||
# If this tool doesn't have allowed_params specified, allow all params
|
||||
if allowed_params_list is None:
|
||||
return arguments
|
||||
|
||||
# Filter arguments to only include allowed parameters
|
||||
disallowed_params = [
|
||||
param for param in arguments.keys() if param not in allowed_params_list
|
||||
]
|
||||
|
||||
if disallowed_params:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail={
|
||||
"error": f"Parameters {disallowed_params} are not allowed for tool {tool_name}. "
|
||||
f"Allowed parameters: {allowed_params_list}. "
|
||||
f"Contact proxy admin to allow these parameters."
|
||||
},
|
||||
)
|
||||
|
||||
return {k: v for k, v in arguments.items() if k in allowed_params_list}
|
||||
|
||||
async def check_tool_permission_for_key_team(
|
||||
self,
|
||||
tool_name: str,
|
||||
|
|
@ -621,18 +676,20 @@ class MCPServerManager:
|
|||
Raises:
|
||||
HTTPException: If tool is not allowed for this key/team
|
||||
"""
|
||||
from litellm.proxy._experimental.mcp_server.auth.user_api_key_auth_mcp import MCPRequestHandler
|
||||
|
||||
from litellm.proxy._experimental.mcp_server.auth.user_api_key_auth_mcp import (
|
||||
MCPRequestHandler,
|
||||
)
|
||||
|
||||
if not user_api_key_auth:
|
||||
return
|
||||
|
||||
|
||||
# Check if tool is allowed
|
||||
is_allowed = await MCPRequestHandler.is_tool_allowed_for_server(
|
||||
tool_name=tool_name,
|
||||
server_id=server.server_id,
|
||||
user_api_key_auth=user_api_key_auth,
|
||||
)
|
||||
|
||||
|
||||
if not is_allowed:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
|
|
@ -667,6 +724,16 @@ class MCPServerManager:
|
|||
user_api_key_auth=user_api_key_auth,
|
||||
)
|
||||
|
||||
## filter parameters based on allowed_params configuration
|
||||
filtered_arguments = self.filter_allowed_params(
|
||||
tool_name=name,
|
||||
arguments=arguments,
|
||||
server=server,
|
||||
)
|
||||
# Update arguments with filtered version
|
||||
arguments.clear()
|
||||
arguments.update(filtered_arguments)
|
||||
|
||||
pre_hook_kwargs = {
|
||||
"name": name,
|
||||
"arguments": arguments,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,39 @@
|
|||
model_list:
|
||||
- model_name: gpt-5-mini
|
||||
litellm_params:
|
||||
model: azure/gpt-5-mini-2
|
||||
api_key: os.environ/AZURE_API_KEY_ALT
|
||||
api_base: os.environ/AZURE_API_BASE_ALT
|
||||
model: openai/gpt-4o-mini
|
||||
api_base: "https://webhook.site/2f385e05-00aa-402b-86d1-efc9261471a5"
|
||||
api_key: dummy
|
||||
- model_name: "byok-wildcard/*"
|
||||
litellm_params:
|
||||
model: openai/*
|
||||
- model_name: xai-grok-3
|
||||
litellm_params:
|
||||
model: xai/grok-3
|
||||
- model_name: hosted_vllm/whisper-v3
|
||||
litellm_params:
|
||||
model: hosted_vllm/whisper-v3
|
||||
api_base: "https://webhook.site/2f385e05-00aa-402b-86d1-efc9261471a5"
|
||||
api_key: dummy
|
||||
|
||||
mcp_servers:
|
||||
my_api_mcp:
|
||||
url: "http://0.0.0.0:8090"
|
||||
spec_path: "/Users/krrishdholakia/Documents/temp_py_folder/example_openapi.json"
|
||||
auth_type: none
|
||||
allowed_tools: ["getpetbyid", "my_api_mcp-findpetsbystatus"]
|
||||
# Configure allowed parameters per tool
|
||||
# Key: tool name (with or without prefix)
|
||||
# Value: list of allowed parameter names
|
||||
allowed_params:
|
||||
# Using unprefixed tool name
|
||||
"getpetbyid": ["petId"]
|
||||
# Using prefixed tool name (both formats work)
|
||||
"my_api_mcp-findpetsbystatus": ["status", "limit"]
|
||||
# Example: allow only specific params for another tool
|
||||
# "another_tool": ["param1", "param2"]
|
||||
|
||||
|
||||
litellm_settings:
|
||||
callbacks: ["prometheus"]
|
||||
custom_prometheus_metadata_labels: ["metadata.initiative", "metadata.business-unit"]
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ class MCPServer(BaseModel):
|
|||
)
|
||||
allowed_tools: Optional[List[str]] = None
|
||||
disallowed_tools: Optional[List[str]] = None
|
||||
allowed_params: Optional[Dict[str, List[str]]] = (
|
||||
None # map of tool names to allowed parameter lists
|
||||
)
|
||||
# OAuth-specific fields
|
||||
client_id: Optional[str] = None
|
||||
client_secret: Optional[str] = None
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue