From 21a1a0f5e1e7da3eb5629102e550f10b93e456eb Mon Sep 17 00:00:00 2001 From: Azure SRE Agent Date: Wed, 3 Jun 2026 01:42:22 +0000 Subject: [PATCH 1/3] Fix MCP allowed_tools empty list handling When allowed_tools is set to an empty list [], the falsy check 'if not self.allowed_tools' incorrectly treats it as unconfigured (same as None), causing all tools to be exposed. Change to an explicit 'is None' check so that an empty list correctly results in no tools being allowed. Co-authored-by: Azure SRE Agent --- python/packages/core/agent_framework/_mcp.py | 2 +- python/packages/core/tests/core/test_mcp.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/python/packages/core/agent_framework/_mcp.py b/python/packages/core/agent_framework/_mcp.py index d872b2b92de..d4d5d515dd7 100644 --- a/python/packages/core/agent_framework/_mcp.py +++ b/python/packages/core/agent_framework/_mcp.py @@ -544,7 +544,7 @@ def _prepare_message_for_mcp( @property def functions(self) -> list[FunctionTool]: """Get the list of functions that are allowed.""" - if not self.allowed_tools: + if self.allowed_tools is None: return self._functions allowed_names = set(self.allowed_tools) filtered_functions: list[FunctionTool] = [] diff --git a/python/packages/core/tests/core/test_mcp.py b/python/packages/core/tests/core/test_mcp.py index 519d8e5db31..365c188a354 100644 --- a/python/packages/core/tests/core/test_mcp.py +++ b/python/packages/core/tests/core/test_mcp.py @@ -1465,6 +1465,7 @@ def test_mcp_tool_approval_mode_returns_none_for_unmatched_names() -> None: 3, ["tool_one", "tool_two", "tool_three"], ), # None means all tools are allowed + ([], 0, []), # Empty list means no tools are allowed (["tool_one"], 1, ["tool_one"]), # Only tool_one is allowed ( ["tool_one", "tool_three"], From 20b50ed050dc083c16a6aecea30f72816c63b3ce Mon Sep 17 00:00:00 2001 From: Chetan Toshniwal Date: Mon, 8 Jun 2026 19:13:26 -0700 Subject: [PATCH 2/3] Clarify allowed_tools docstring: None vs [] semantics Per Eduard's review on PR #6296: explicitly document that None exposes all tools and [] exposes none, across all four MCPTool / MCPStdioTool / MCPStreamableHTTPTool / MCPWebsocketTool docstrings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/packages/core/agent_framework/_mcp.py | 24 ++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/python/packages/core/agent_framework/_mcp.py b/python/packages/core/agent_framework/_mcp.py index d4d5d515dd7..88be517bf27 100644 --- a/python/packages/core/agent_framework/_mcp.py +++ b/python/packages/core/agent_framework/_mcp.py @@ -228,7 +228,11 @@ def __init__( name: The name of the MCP tool. description: A description of the MCP tool. approval_mode: Whether approval is required to run tools. - allowed_tools: A collection of tool names to allow. + allowed_tools: Optional allow-list of MCP tool names to expose as functions. + ``None`` (the default) exposes every tool advertised by the MCP server. + An empty collection (``[]``) exposes no tools, which is useful when the + server is being used only for prompts or other capabilities. A non-empty + collection exposes only the tools whose names appear in it. tool_name_prefix: Optional prefix to prepend to exposed MCP function names. load_tools: Whether to load tools from the MCP server. parse_tool_results: An optional callable with signature @@ -1592,7 +1596,11 @@ def __init__( - A dict with keys `always_require_approval` or `never_require_approval`, followed by a sequence of strings with the names of the relevant tools. A tool should not be listed in both, if so, it will require approval. - allowed_tools: A list of tools that are allowed to use this tool. + allowed_tools: Optional allow-list of MCP tool names to expose as functions. + ``None`` (the default) exposes every tool advertised by the MCP server. + An empty collection (``[]``) exposes no tools, which is useful when the + server is being used only for prompts or other capabilities. A non-empty + collection exposes only the tools whose names appear in it. additional_properties: Additional properties. args: The arguments to pass to the command. env: The environment variables to set for the command. @@ -1726,7 +1734,11 @@ def __init__( - A dict with keys `always_require_approval` or `never_require_approval`, followed by a sequence of strings with the names of the relevant tools. A tool should not be listed in both, if so, it will require approval. - allowed_tools: A list of tools that are allowed to use this tool. + allowed_tools: Optional allow-list of MCP tool names to expose as functions. + ``None`` (the default) exposes every tool advertised by the MCP server. + An empty collection (``[]``) exposes no tools, which is useful when the + server is being used only for prompts or other capabilities. A non-empty + collection exposes only the tools whose names appear in it. additional_properties: Additional properties. terminate_on_close: Close the transport when the MCP client is terminated. client: The chat client to use for sampling. @@ -1901,7 +1913,11 @@ def __init__( - A dict with keys `always_require_approval` or `never_require_approval`, followed by a sequence of strings with the names of the relevant tools. A tool should not be listed in both, if so, it will require approval. - allowed_tools: A list of tools that are allowed to use this tool. + allowed_tools: Optional allow-list of MCP tool names to expose as functions. + ``None`` (the default) exposes every tool advertised by the MCP server. + An empty collection (``[]``) exposes no tools, which is useful when the + server is being used only for prompts or other capabilities. A non-empty + collection exposes only the tools whose names appear in it. additional_properties: Additional properties. client: The chat client to use for sampling. kwargs: Any extra arguments to pass to the WebSocket client. From f83b940bb1fe18e7f2ab2396f1cc48ce39b5ed50 Mon Sep 17 00:00:00 2001 From: Chetan Toshniwal Date: Tue, 9 Jun 2026 17:08:15 -0700 Subject: [PATCH 3/3] allowed_tools docstring: recommend load_tools=False for full disable Per Eduard's follow-up on PR #6296: `load_tools=False` is the cleaner idiom when you don't want to expose any tools. Reframe `allowed_tools=[]` in the docstring as a runtime guard / inspection-only path and cross-reference `load_tools`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/packages/core/agent_framework/_mcp.py | 32 ++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/python/packages/core/agent_framework/_mcp.py b/python/packages/core/agent_framework/_mcp.py index 88be517bf27..cb8c5271cb3 100644 --- a/python/packages/core/agent_framework/_mcp.py +++ b/python/packages/core/agent_framework/_mcp.py @@ -230,9 +230,11 @@ def __init__( approval_mode: Whether approval is required to run tools. allowed_tools: Optional allow-list of MCP tool names to expose as functions. ``None`` (the default) exposes every tool advertised by the MCP server. - An empty collection (``[]``) exposes no tools, which is useful when the - server is being used only for prompts or other capabilities. A non-empty - collection exposes only the tools whose names appear in it. + A non-empty collection exposes only the tools whose names appear in it. + An empty collection (``[]``) exposes no tools — if you simply want to + disable tool execution, prefer ``load_tools=False`` instead. ``[]`` is + useful as a runtime guard or when you want to load tool metadata for + inspection without exposing the tools for invocation. tool_name_prefix: Optional prefix to prepend to exposed MCP function names. load_tools: Whether to load tools from the MCP server. parse_tool_results: An optional callable with signature @@ -1598,9 +1600,11 @@ def __init__( A tool should not be listed in both, if so, it will require approval. allowed_tools: Optional allow-list of MCP tool names to expose as functions. ``None`` (the default) exposes every tool advertised by the MCP server. - An empty collection (``[]``) exposes no tools, which is useful when the - server is being used only for prompts or other capabilities. A non-empty - collection exposes only the tools whose names appear in it. + A non-empty collection exposes only the tools whose names appear in it. + An empty collection (``[]``) exposes no tools — if you simply want to + disable tool execution, prefer ``load_tools=False`` instead. ``[]`` is + useful as a runtime guard or when you want to load tool metadata for + inspection without exposing the tools for invocation. additional_properties: Additional properties. args: The arguments to pass to the command. env: The environment variables to set for the command. @@ -1736,9 +1740,11 @@ def __init__( A tool should not be listed in both, if so, it will require approval. allowed_tools: Optional allow-list of MCP tool names to expose as functions. ``None`` (the default) exposes every tool advertised by the MCP server. - An empty collection (``[]``) exposes no tools, which is useful when the - server is being used only for prompts or other capabilities. A non-empty - collection exposes only the tools whose names appear in it. + A non-empty collection exposes only the tools whose names appear in it. + An empty collection (``[]``) exposes no tools — if you simply want to + disable tool execution, prefer ``load_tools=False`` instead. ``[]`` is + useful as a runtime guard or when you want to load tool metadata for + inspection without exposing the tools for invocation. additional_properties: Additional properties. terminate_on_close: Close the transport when the MCP client is terminated. client: The chat client to use for sampling. @@ -1915,9 +1921,11 @@ def __init__( A tool should not be listed in both, if so, it will require approval. allowed_tools: Optional allow-list of MCP tool names to expose as functions. ``None`` (the default) exposes every tool advertised by the MCP server. - An empty collection (``[]``) exposes no tools, which is useful when the - server is being used only for prompts or other capabilities. A non-empty - collection exposes only the tools whose names appear in it. + A non-empty collection exposes only the tools whose names appear in it. + An empty collection (``[]``) exposes no tools — if you simply want to + disable tool execution, prefer ``load_tools=False`` instead. ``[]`` is + useful as a runtime guard or when you want to load tool metadata for + inspection without exposing the tools for invocation. additional_properties: Additional properties. client: The chat client to use for sampling. kwargs: Any extra arguments to pass to the WebSocket client.