mirror of
https://github.com/open-webui/mcpo.git
synced 2026-07-01 21:04:00 -04:00
Merge pull request #246 from druellan/disabledTools
Feat: Tools can be filtered out using the `disabledTools` configuration option in the server declaration
This commit is contained in:
@@ -12,6 +12,12 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on Keep a Changelog,
|
||||
and this project adheres to Semantic Versioning.
|
||||
|
||||
## [0.0.18] - 2025-09-07
|
||||
|
||||
### Added
|
||||
|
||||
- 🔧 **Support for disabling specific tools**: Tools can be filtered out using the `disabledTools` configuration option in the server declaration.
|
||||
|
||||
## [0.0.17] - 2025-07-22
|
||||
|
||||
### Added
|
||||
|
||||
@@ -103,7 +103,8 @@ Example config.json:
|
||||
},
|
||||
"time": {
|
||||
"command": "uvx",
|
||||
"args": ["mcp-server-time", "--local-timezone=America/New_York"]
|
||||
"args": ["mcp-server-time", "--local-timezone=America/New_York"],
|
||||
"disabledTools": ["convert_time"] // Disable specific tools if needed
|
||||
},
|
||||
"mcp_sse": {
|
||||
"type": "sse", // Explicitly define type
|
||||
|
||||
@@ -71,6 +71,16 @@ def validate_server_config(server_name: str, server_cfg: Dict[str, Any]) -> None
|
||||
# Fallback for old SSE config without explicit type
|
||||
pass
|
||||
else:
|
||||
raise ValueError(f"Server '{server_name}' must have either 'command' for stdio or 'type' and 'url' for remote servers")
|
||||
|
||||
# Validate disabledTools
|
||||
disabled_tools = server_cfg.get("disabled_tools")
|
||||
if disabled_tools is not None:
|
||||
if not isinstance(disabled_tools, list):
|
||||
raise ValueError(f"Server '{server_name}' 'disabledTools' must be a list")
|
||||
for tool_name in disabled_tools:
|
||||
if not isinstance(tool_name, str):
|
||||
raise ValueError(f"Server '{server_name}' 'disabledTools' must contain only strings")
|
||||
raise ValueError(
|
||||
f"Server '{server_name}' must have either 'command' for stdio or 'type' and 'url' for remote servers"
|
||||
)
|
||||
@@ -167,6 +177,10 @@ def create_sub_app(
|
||||
sub_app.state.api_dependency = api_dependency
|
||||
sub_app.state.connection_timeout = connection_timeout
|
||||
|
||||
# Store list of tools to be disabled, if present
|
||||
sub_app.state.disabled_tools = server_cfg.get("disabled_tools", [])
|
||||
|
||||
|
||||
# Store client header forwarding configuration
|
||||
sub_app.state.client_header_forwarding = server_cfg.get(
|
||||
"client_header_forwarding", {"enabled": False}
|
||||
@@ -175,6 +189,7 @@ def create_sub_app(
|
||||
# Store OAuth configuration if present
|
||||
sub_app.state.oauth_config = server_cfg.get("oauth")
|
||||
|
||||
|
||||
return sub_app
|
||||
|
||||
|
||||
@@ -346,6 +361,15 @@ async def create_dynamic_endpoints(app: FastAPI, api_dependency=None):
|
||||
|
||||
tools_result = await session.list_tools()
|
||||
tools = tools_result.tools
|
||||
|
||||
# Filter out disabled tools
|
||||
disabled_tools = getattr(app.state, "disabled_tools", [])
|
||||
if disabled_tools:
|
||||
original_count = len(tools)
|
||||
tools = [tool for tool in tools if tool.name not in disabled_tools]
|
||||
filtered_count = original_count - len(tools)
|
||||
if filtered_count > 0:
|
||||
logger.info(f"Filtered out {filtered_count} tool(s) for server '{app.title}': {disabled_tools}")
|
||||
|
||||
for tool in tools:
|
||||
endpoint_name = tool.name
|
||||
|
||||
@@ -42,6 +42,19 @@ def test_validate_server_config_missing_url():
|
||||
validate_server_config("test_server", config)
|
||||
|
||||
|
||||
def test_validate_server_config_disabled_tools_valid():
|
||||
"""Test validation of server configuration with a valid disabledTools."""
|
||||
config = {"command": "echo", "args": ["hello"], "disabledTools": ["search-web"]}
|
||||
validate_server_config("test_server", config)
|
||||
|
||||
|
||||
def test_validate_server_config_disabled_tools_invalid():
|
||||
"""Test validation fails for an invalid disabledTools."""
|
||||
config = {"command": "echo", "args": ["hello"], "disabledTools": "not-a-list"}
|
||||
with pytest.raises(ValueError, match="'disabledTools' must be a list"):
|
||||
validate_server_config("test_server", config)
|
||||
|
||||
|
||||
def test_load_config_valid():
|
||||
"""Test loading a valid config file."""
|
||||
config_data = {
|
||||
|
||||
Reference in New Issue
Block a user