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:
Krrish Dholakia 2025-10-08 16:27:01 -07:00
parent 1c56a0d856
commit dd4249db78
3 changed files with 110 additions and 7 deletions

View file

@ -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,

View file

@ -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"]

View file

@ -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