Flip default tool discovery setting to disabled (#7452)

This commit is contained in:
Theodore Aptekarev
2026-04-03 08:39:20 +03:00
committed by GitHub
parent b6e05bab02
commit 18d1696243
10 changed files with 34 additions and 39 deletions

View File

@@ -67,8 +67,8 @@ Enter `openbb-mcp --help` to see the docstring from the command line.
A comma-separated list of tool categories to be enabled by default.
Defaults to 'all'.
--no-tool-discovery
If set, tool discovery will be disabled.
--tool-discovery
If set, tool discovery will be enabled.
--system-prompt <path>
Path to a TXT file with the system prompt.
@@ -221,7 +221,7 @@ All settings in the `MCPSettings` model can be configured via the `mcp_settings.
| `instructions` | `OPENBB_MCP_INSTRUCTIONS` | string | `None` | Server instructions sent during the MCP `initialize` handshake. Auto-populated from system prompt if not set. |
| `default_tool_categories` | `OPENBB_MCP_DEFAULT_TOOL_CATEGORIES` | list[string] | `["all"]` | Default active tool categories on startup. |
| `allowed_tool_categories` | `OPENBB_MCP_ALLOWED_TOOL_CATEGORIES` | list[string] | `None` | Restricts available tool categories to this list. |
| `enable_tool_discovery` | `OPENBB_MCP_ENABLE_TOOL_DISCOVERY` | boolean | `True` | Enable per-session tool discovery (admin tools for browse/activate/deactivate). |
| `enable_tool_discovery` | `OPENBB_MCP_ENABLE_TOOL_DISCOVERY` | boolean | `False` | Enable per-session tool discovery (admin tools for browse/activate/deactivate). |
| `list_page_size` | `OPENBB_MCP_LIST_PAGE_SIZE` | integer | `None` | Max items per page in MCP list responses. `None` disables pagination. |
| `describe_responses` | `OPENBB_MCP_DESCRIBE_RESPONSES` | boolean | `False` | Include response types in tool descriptions. |
| `system_prompt_file` | `OPENBB_MCP_SYSTEM_PROMPT_FILE` | string | `None` | Path to a text file for the system prompt. |
@@ -294,7 +294,7 @@ An additional set of tools are tagged as "admin", or "prompt".
## Tool Discovery
When `enable_tool_discovery` is enabled (default), the server registers a small set of admin tools that let agents progressively discover and activate what they need:
When `enable_tool_discovery` is enabled, the server registers a small set of admin tools that let agents progressively discover and activate what they need:
1. **Browse** — `available_categories` returns the category tree with tool counts.
2. **Inspect** — `available_tools` lists every tool in a category with its active/inactive state and a short description.
@@ -305,7 +305,7 @@ All visibility changes are **per-session** — each client maintains its own act
To take full advantage of minimal startup tools, set `--default-categories admin` so only the discovery tools are active on connect.
For scenarios where you want a completely fixed toolset (no discovery overhead), disable it with `--no-tool-discovery` and control the available tools via `allowed_tool_categories` and `default_tool_categories`.
For scenarios where you want discovery available, enable it with `--tool-discovery`. Otherwise the server runs with a fixed toolset and you can control the available tools via `allowed_tool_categories` and `default_tool_categories`.
## System Prompt
@@ -612,8 +612,8 @@ openbb-mcp --default-categories equity,news --host 0.0.0.0 --port 8080
# Start with allowed categories restriction
openbb-mcp --allowed-categories equity,crypto,news
# Disable tool discovery for multi-client usage
openbb-mcp --no-tool-discovery
# Enable tool discovery for per-session activation
openbb-mcp --tool-discovery
```
### Claude Desktop:

View File

@@ -97,6 +97,7 @@ def _get_mcp_config_from_route(fa_route: APIRoute | None) -> dict:
def _strip_api_prefix(path: str, api_prefix: str) -> str:
"""Strip the exact api_prefix (from SystemService) from an absolute path.
Returns the remainder without a leading slash.
"""
if not path:
@@ -242,7 +243,7 @@ def _add_prompts_from_json(mcp: FastMCP, settings: MCPSettings) -> None:
continue
prompt_tags = prompt_def.get("tags", [])
tags = set(prompt_tags) if isinstance(prompt_tags, (list, set)) else set()
tags = set(prompt_tags) if isinstance(prompt_tags, list | set) else set()
tags.add("server")
mcp.add_prompt(
StaticPrompt(
@@ -271,7 +272,7 @@ def _add_inline_prompts(mcp: FastMCP, prompt_definitions: list) -> None:
prompt_tags = prompt_def.get("tags", [])
tool = prompt_def.get("tool", "")
tags = set(prompt_tags) if isinstance(prompt_tags, (list, set)) else set()
tags = set(prompt_tags) if isinstance(prompt_tags, list | set) else set()
tags.add("route-specific")
tags.add(tool)
@@ -369,7 +370,7 @@ def create_mcp_server(
The configured FastMCP server instance.
"""
auth_provider = None
if auth and isinstance(auth, (list, tuple)) and len(auth) == 2 and all(auth):
if auth and isinstance(auth, list | tuple) and len(auth) == 2 and all(auth):
# pylint: disable=import-outside-toplevel
from .auth import get_auth_provider
@@ -405,7 +406,6 @@ def create_mcp_server(
component: OpenAPITool | OpenAPIResource | OpenAPIResourceTemplate,
) -> None:
"""Apply naming, tags, enable/disable, and resource mime type using per-route config."""
# Map back to FastAPI route to read openapi_extra
fa_route = route_lookup.get((route.path, route.method.upper()))
mcp_cfg = _get_mcp_config_from_route(fa_route)
@@ -962,8 +962,8 @@ def main():
if hasattr(args, "default_categories") and args.default_categories:
cli_overrides["default_categories"] = args.default_categories
if hasattr(args, "no_tool_discovery") and args.no_tool_discovery:
cli_overrides["no_tool_discovery"] = args.no_tool_discovery
if hasattr(args, "tool_discovery") and args.tool_discovery:
cli_overrides["tool_discovery"] = args.tool_discovery
if hasattr(args, "system_prompt") and args.system_prompt:
cli_overrides["system_prompt"] = args.system_prompt

View File

@@ -60,7 +60,7 @@ the exact same operations available to REST clients.""",
# Tool discovery configuration
enable_tool_discovery: bool = Field(
default=True,
default=False,
description="""
Enable tool discovery, allowing the agent to hot-swap tools at runtime.
Disable for multi-client or fixed toolset deployments.

View File

@@ -199,7 +199,7 @@ class MCPService(metaclass=SingletonMeta):
cli_to_settings_map = {
"allowed_categories": "allowed_tool_categories",
"default_categories": "default_tool_categories",
"no_tool_discovery": "enable_tool_discovery",
"tool_discovery": "enable_tool_discovery",
"system_prompt": "system_prompt_file",
"system-prompt": "system_prompt_file",
"server_prompts": "server_prompts_file",
@@ -251,10 +251,7 @@ class MCPService(metaclass=SingletonMeta):
uvicorn_config[key] = value
elif key in cli_to_settings_map:
mapped_key = cli_to_settings_map[key]
if mapped_key == "enable_tool_discovery":
settings_overrides[mapped_key] = not value
else:
settings_overrides[mapped_key] = value
settings_overrides[mapped_key] = value
elif key in mcp_settings_fields:
settings_overrides[key] = value
else:

View File

@@ -79,7 +79,7 @@ openbb-mcp --app ./my_app.py:create_app --factory
| `--transport <type>` | `streamable-http`, `sse`, or `stdio` | `streamable-http` |
| `--default-categories <csv>` | Comma-separated default active tool categories | `all` |
| `--allowed-categories <csv>` | Restrict available categories to this list | All categories |
| `--no-tool-discovery` | Disable runtime tool activation/deactivation | Discovery enabled |
| `--tool-discovery` | Enable runtime tool activation/deactivation | Discovery disabled |
| `--system-prompt <path>` | Path to a `.txt` system prompt file | None |
| `--server-prompts <path>` | Path to a `.json` server prompts file | None |
@@ -104,7 +104,7 @@ Create `~/.openbb_platform/mcp_settings.json`:
{
"name": "My MCP Server",
"default_tool_categories": ["equity", "economy"],
"enable_tool_discovery": true,
"enable_tool_discovery": false,
"describe_responses": false,
"system_prompt_file": "/path/to/system_prompt.txt",
"server_prompts_file": "/path/to/prompts.json"
@@ -141,7 +141,7 @@ OPENBB_MCP_SERVER_PROMPTS_FILE="/path/to/prompts.json"
|---|---|---|---|
| `default_tool_categories` | `OPENBB_MCP_DEFAULT_TOOL_CATEGORIES` | `list[str]` | `["all"]` |
| `allowed_tool_categories` | `OPENBB_MCP_ALLOWED_TOOL_CATEGORIES` | `list[str] \| None` | `None` |
| `enable_tool_discovery` | `OPENBB_MCP_ENABLE_TOOL_DISCOVERY` | `bool` | `true` |
| `enable_tool_discovery` | `OPENBB_MCP_ENABLE_TOOL_DISCOVERY` | `bool` | `false` |
| `list_page_size` | `OPENBB_MCP_LIST_PAGE_SIZE` | `int \| None` | `None` |
| `describe_responses` | `OPENBB_MCP_DESCRIBE_RESPONSES` | `bool` | `false` |
| `api_prefix` | `OPENBB_MCP_API_PREFIX` | `str \| None` | `None` |
@@ -241,7 +241,7 @@ mcp = create_mcp_server(settings, my_fastapi_app, auth=my_auth_provider)
## Tool Discovery
When `enable_tool_discovery` is `true` (the default), five admin tools are
When `enable_tool_discovery` is `true`, five admin tools are
available to the agent:
| Tool | Description |
@@ -281,14 +281,14 @@ openbb-mcp --allowed-categories equity,economy,crypto
Categories not in this list cannot be activated even via discovery tools.
### Disabling Discovery
### Enabling Discovery
```
openbb-mcp --no-tool-discovery
openbb-mcp --tool-discovery
```
All tools in `default_tool_categories` are active and the admin tools are
not registered.
not registered unless discovery is enabled.
---
@@ -644,7 +644,7 @@ async def hello():
settings = MCPSettings(
name="My Custom MCP",
default_tool_categories=["all"],
enable_tool_discovery=True,
enable_tool_discovery=False,
)
mcp = create_mcp_server(settings, app)

View File

@@ -115,7 +115,7 @@ This reduces noise in the active tool list and can improve context efficiency.
### When Discovery Is Disabled
If the server was started with `--no-tool-discovery`, the admin tools are not
If the server was started without `--tool-discovery`, the admin tools are not
available. All tools in `default_tool_categories` are permanently active.
---

View File

@@ -155,8 +155,8 @@ Options:
A comma-separated list of tool categories to be enabled by default.
Defaults to 'all'.
--no-tool-discovery
If set, tool discovery will be disabled.
--tool-discovery
If set, tool discovery will be enabled.
--system-prompt <path>
Path to a TXT file with the system prompt.
@@ -234,7 +234,7 @@ def parse_args():
transport = _kwargs.pop("transport", "streamable-http")
allowed_categories = _kwargs.pop("allowed_categories", None)
default_categories = _kwargs.pop("default_categories", "all")
no_tool_discovery = _kwargs.pop("no_tool_discovery", False)
tool_discovery = _kwargs.pop("tool_discovery", False)
system_prompt = _kwargs.pop("system_prompt", None)
server_prompts = _kwargs.pop("server_prompts", None)
@@ -247,7 +247,7 @@ def parse_args():
self.transport = transport
self.allowed_categories = allowed_categories
self.default_categories = default_categories
self.no_tool_discovery = no_tool_discovery
self.tool_discovery = tool_discovery
self.system_prompt = system_prompt
self.server_prompts = server_prompts
self.uvicorn_config = _kwargs # All remaining kwargs go to uvicorn

View File

@@ -9,7 +9,7 @@ def test_mcp_settings_defaults():
assert settings.name == "OpenBB MCP"
assert settings.default_tool_categories == ["all"]
assert settings.allowed_tool_categories is None
assert settings.enable_tool_discovery is True
assert settings.enable_tool_discovery is False
assert settings.describe_responses is False

View File

@@ -149,7 +149,7 @@ def test_map_cli_args_to_settings(service: MCPService):
"host": "10.10.10.10",
"port": 9000,
"allowed_categories": "stocks,crypto",
"no_tool_discovery": True,
"tool_discovery": True,
"httpx_timeout": 30,
"unknown_param": "some_value",
}
@@ -159,7 +159,7 @@ def test_map_cli_args_to_settings(service: MCPService):
assert mapped["uvicorn_config"]["host"] == "10.10.10.10"
assert mapped["uvicorn_config"]["port"] == 9000
assert mapped["allowed_tool_categories"] == "stocks,crypto"
assert mapped["enable_tool_discovery"] is False
assert mapped["enable_tool_discovery"] is True
assert mapped["httpx_client_kwargs"]["timeout"] == 30
assert mapped["uvicorn_config"]["unknown_param"] == "some_value"

View File

@@ -99,14 +99,14 @@ def test_parse_args_simple():
"test_transport",
"--allowed_categories",
"cat1,cat2",
"--no-tool-discovery",
"--tool-discovery",
"true",
]
with patch.object(sys, "argv", test_args):
args = parse_args()
assert args.transport == "test_transport"
assert args.allowed_categories == "cat1,cat2"
assert args.no_tool_discovery is True
assert args.tool_discovery is True
assert args.imported_app is None
@@ -365,8 +365,6 @@ class TestModuleColonNotationHelper:
def test_simple_module_notation(self):
"""Test simple module:name notation is detected correctly."""
# These should be recognized as module colon notation
from openbb_mcp_server.utils.app_import import import_app
# We test the behavior indirectly through import_app
# Module notation without file should try import first
with pytest.raises((ImportError, FileNotFoundError)):