From 7c21e2d7a15db98dfee00a7146b753eb876a05c7 Mon Sep 17 00:00:00 2001 From: Abhi Date: Mon, 9 Mar 2026 00:25:18 -0400 Subject: [PATCH 1/2] docs: standardize mcp tool fqn documentation and add deprecations --- docs/cli/tutorials/mcp-setup.md | 2 +- docs/extensions/reference.md | 6 ++++-- docs/hooks/reference.md | 2 +- docs/reference/configuration.md | 14 +++++++------- docs/reference/policy-engine.md | 20 +++++++++++++------- docs/tools/mcp-server.md | 26 ++++++++++++++++---------- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/docs/cli/tutorials/mcp-setup.md b/docs/cli/tutorials/mcp-setup.md index 8723a65892e..76c2806f9d0 100644 --- a/docs/cli/tutorials/mcp-setup.md +++ b/docs/cli/tutorials/mcp-setup.md @@ -89,7 +89,7 @@ don't need to learn special commands; just ask in natural language. The agent will: 1. Recognize the request matches a GitHub tool. -2. Call `github_list_pull_requests`. +2. Call `mcp_github_list_pull_requests`. 3. Present the data to you. ### Scenario: Creating an issue diff --git a/docs/extensions/reference.md b/docs/extensions/reference.md index 46d43225b22..2b42384b1f3 100644 --- a/docs/extensions/reference.md +++ b/docs/extensions/reference.md @@ -258,12 +258,14 @@ but lower priority than user or admin policies. ```toml [[rule]] -toolName = "my_server__dangerous_tool" +mcpName = "my_server" +toolName = "dangerous_tool" decision = "ask_user" priority = 100 [[safety_checker]] -toolName = "my_server__write_data" +mcpName = "my_server" +toolName = "write_data" priority = 200 [safety_checker.checker] type = "in-process" diff --git a/docs/hooks/reference.md b/docs/hooks/reference.md index 445035b1aaf..a0fbd978acd 100644 --- a/docs/hooks/reference.md +++ b/docs/hooks/reference.md @@ -85,7 +85,7 @@ compared against the name of the tool being executed. `run_shell_command`). See the [Tools Reference](/docs/reference/tools) for a full list of available tool names. - **MCP Tools**: Tools from MCP servers follow the naming pattern - `mcp____`. + `mcp__`. - **Regex Support**: Matchers support regular expressions (e.g., `matcher: "read_.*"` matches all file reading tools). diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 9b89fe75a8a..23d69a062d2 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -1171,13 +1171,13 @@ their corresponding top-level category object in your `settings.json` file. Configures connections to one or more Model-Context Protocol (MCP) servers for discovering and using custom tools. Gemini CLI attempts to connect to each -configured MCP server to discover available tools. If multiple MCP servers -expose a tool with the same name, the tool names will be prefixed with the -server alias you defined in the configuration (e.g., -`serverAlias__actualToolName`) to avoid conflicts. Note that the system might -strip certain schema properties from MCP tool definitions for compatibility. At -least one of `command`, `url`, or `httpUrl` must be provided. If multiple are -specified, the order of precedence is `httpUrl`, then `url`, then `command`. +configured MCP server to discover available tools. Every discovered tool is +prepended with the `mcp_` prefix and its server alias to form a fully qualified +name (FQN) (e.g., `mcp_serverAlias_actualToolName`) to avoid conflicts. Note +that the system might strip certain schema properties from MCP tool definitions +for compatibility. At least one of `command`, `url`, or `httpUrl` must be +provided. If multiple are specified, the order of precedence is `httpUrl`, then +`url`, then `command`. - **`mcpServers.`** (object): The server parameters for the named server. diff --git a/docs/reference/policy-engine.md b/docs/reference/policy-engine.md index 17d958acd0a..18488189cd1 100644 --- a/docs/reference/policy-engine.md +++ b/docs/reference/policy-engine.md @@ -76,9 +76,13 @@ The `toolName` in the rule must match the name of the tool being called. - **Wildcards**: You can use wildcards to match multiple tools. - `*`: Matches **any tool** (built-in or MCP). - - `server__*`: Matches any tool from a specific MCP server. - - `*__toolName`: Matches a specific tool name across **all** MCP servers. - - `*__*`: Matches **any tool from any MCP server**. + - `mcp_server_*`: Matches any tool from a specific MCP server. + - `mcp_*_toolName`: Matches a specific tool name across **all** MCP servers. + - `mcp_*`: Matches **any tool from any MCP server**. + +> **Recommendation:** While FQN wildcards are supported, the recommended +> approach for MCP tools is to use the `mcpName` field in your TOML rules. See +> [Special syntax for MCP tools](#special-syntax-for-mcp-tools). #### Arguments pattern @@ -157,8 +161,8 @@ A rule matches a tool call if all of its conditions are met: 1. **Tool name**: The `toolName` in the rule must match the name of the tool being called. - - **Wildcards**: You can use wildcards like `*`, `server__*`, or - `*__toolName` to match multiple tools. See [Tool Name](#tool-name) for + - **Wildcards**: You can use wildcards like `*`, `mcp_server_*`, or + `mcp_*_toolName` to match multiple tools. See [Tool Name](#tool-name) for details. 2. **Arguments pattern**: If `argsPattern` is specified, the tool's arguments are converted to a stable JSON string, which is then tested against the @@ -213,7 +217,7 @@ Here is a breakdown of the fields available in a TOML policy rule: toolName = "run_shell_command" # (Optional) The name of an MCP server. Can be combined with toolName -# to form a composite name like "mcpName__toolName". +# to form a composite FQN internally like "mcp_mcpName_toolName". mcpName = "my-custom-server" # (Optional) Metadata hints provided by the tool. A rule matches if all @@ -290,7 +294,9 @@ priority = 100 ### Special syntax for MCP tools You can create rules that target tools from Model Context Protocol (MCP) servers -using the `mcpName` field or composite wildcard patterns. +using the `mcpName` field. **This is the recommended approach** for defining MCP +policies, as it is much more robust than manually writing Fully Qualified Names +(FQNs) or string wildcards. **1. Targeting a specific tool on a server** diff --git a/docs/tools/mcp-server.md b/docs/tools/mcp-server.md index 202325a83d9..5355108c60b 100644 --- a/docs/tools/mcp-server.md +++ b/docs/tools/mcp-server.md @@ -558,18 +558,24 @@ Upon successful connection: - Invalid characters (non-alphanumeric, underscore, dot, hyphen) are replaced with underscores - Names longer than 63 characters are truncated with middle replacement - (`___`) + (`...`) -### 3. Conflict resolution +### 3. Tool naming and namespaces -When multiple servers expose tools with the same name: +To prevent collisions across multiple servers or conflicting built-in tools, +every discovered MCP tool is assigned a strict namespace. -1. **First registration wins:** The first server to register a tool name gets - the unprefixed name -2. **Automatic prefixing:** Subsequent servers get prefixed names: - `serverName__toolName` -3. **Registry tracking:** The tool registry maintains mappings between server - names and their tools +1. **Automatic FQN:** All MCP tools are unconditionally assigned a fully + qualified name (FQN) using the format `mcp_{serverName}_{toolName}`. +2. **Registry tracking:** The tool registry maintains metadata mappings between + these FQNs and their original server identities. +3. **Overwrites:** If two servers share the exact same alias in your + configuration and provide tools with the exact same name, the last registered + tool overwrites the previous one. +4. **Policies:** To configure permissions (like auto-approval or denial) for MCP + tools, see + [Special syntax for MCP tools](../reference/policy-engine.md#special-syntax-for-mcp-tools) + in the Policy Engine documentation. ### 4. Schema processing @@ -695,7 +701,7 @@ MCP Servers Status: 🐳 dockerizedServer (CONNECTED) Command: docker run -i --rm -e API_KEY my-mcp-server:latest - Tools: docker__deploy, docker__status + Tools: mcp_dockerizedServer_docker_deploy, mcp_dockerizedServer_docker_status Discovery State: COMPLETED ``` From 341aa457fc1141f63af86b43d0212e34ee0979e7 Mon Sep 17 00:00:00 2001 From: Abhi Date: Mon, 9 Mar 2026 12:18:07 -0400 Subject: [PATCH 2/2] docs: improve underscore warnings regarding mcpName --- docs/reference/configuration.md | 7 +++++++ docs/reference/policy-engine.md | 7 +++++++ docs/tools/mcp-server.md | 11 +++++++++-- packages/core/src/policy/toml-loader.ts | 5 +++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 23d69a062d2..ce80b82782e 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -1179,6 +1179,13 @@ for compatibility. At least one of `command`, `url`, or `httpUrl` must be provided. If multiple are specified, the order of precedence is `httpUrl`, then `url`, then `command`. +> **Warning:** Avoid using underscores (`_`) in your server aliases (e.g., use +> `my-server` instead of `my_server`). The underlying policy engine parses Fully +> Qualified Names (`mcp_server_tool`) using the first underscore after the +> `mcp_` prefix. An underscore in your server alias will cause the parser to +> misidentify the server name, which can cause security policies to fail +> silently. + - **`mcpServers.`** (object): The server parameters for the named server. - `command` (string, optional): The command to execute to start the MCP server diff --git a/docs/reference/policy-engine.md b/docs/reference/policy-engine.md index 18488189cd1..0dfe2cf4273 100644 --- a/docs/reference/policy-engine.md +++ b/docs/reference/policy-engine.md @@ -298,6 +298,13 @@ using the `mcpName` field. **This is the recommended approach** for defining MCP policies, as it is much more robust than manually writing Fully Qualified Names (FQNs) or string wildcards. +> **Warning:** Do not use underscores (`_`) in your MCP server names (e.g., use +> `my-server` rather than `my_server`). The policy parser splits Fully Qualified +> Names (`mcp_server_tool`) on the _first_ underscore following the `mcp_` +> prefix. If your server name contains an underscore, the parser will +> misinterpret the server identity, which can cause wildcard rules and security +> policies to fail silently. + **1. Targeting a specific tool on a server** Combine `mcpName` and `toolName` to target a single operation. diff --git a/docs/tools/mcp-server.md b/docs/tools/mcp-server.md index 5355108c60b..3590ec98f0b 100644 --- a/docs/tools/mcp-server.md +++ b/docs/tools/mcp-server.md @@ -555,8 +555,8 @@ Upon successful connection: `excludeTools` configuration 4. **Name sanitization:** Tool names are cleaned to meet Gemini API requirements: - - Invalid characters (non-alphanumeric, underscore, dot, hyphen) are replaced - with underscores + - Characters other than letters, numbers, underscore (`_`), hyphen (`-`), dot + (`.`), and colon (`:`) are replaced with underscores - Names longer than 63 characters are truncated with middle replacement (`...`) @@ -577,6 +577,13 @@ every discovered MCP tool is assigned a strict namespace. [Special syntax for MCP tools](../reference/policy-engine.md#special-syntax-for-mcp-tools) in the Policy Engine documentation. +> **Warning:** Do not use underscores (`_`) in your MCP server names (e.g., use +> `my-server` rather than `my_server`). The policy parser splits Fully Qualified +> Names (`mcp_server_tool`) on the _first_ underscore following the `mcp_` +> prefix. If your server name contains an underscore, the parser will +> misinterpret the server identity, which can cause wildcard rules and security +> policies to fail silently. + ### 4. Schema processing Tool parameter schemas undergo sanitization for Gemini API compatibility: diff --git a/packages/core/src/policy/toml-loader.ts b/packages/core/src/policy/toml-loader.ts index c91930a21d2..0b6acbde07b 100644 --- a/packages/core/src/policy/toml-loader.ts +++ b/packages/core/src/policy/toml-loader.ts @@ -456,6 +456,11 @@ export async function loadPoliciesFromToml( const mcpName = rule.mcpName; if (mcpName) { + // TODO(mcp): Decouple mcpName rules from FQN string parsing + // to support underscores in server aliases natively. Leaving + // mcpName and toolName separate here and relying on metadata + // during policy evaluation will avoid underscore splitting bugs. + // See: https://github.com/google-gemini/gemini-cli/issues/21727 effectiveToolName = formatMcpToolName( mcpName, effectiveToolName,