Skip to content

fix(core): scope tools.core wildcard deny to built-in tools#28388

Open
vedhakoushik wants to merge 1 commit into
google-gemini:mainfrom
vedhakoushik:fix/core-tools-mcp-exclusion-v2
Open

fix(core): scope tools.core wildcard deny to built-in tools#28388
vedhakoushik wants to merge 1 commit into
google-gemini:mainfrom
vedhakoushik:fix/core-tools-mcp-exclusion-v2

Conversation

@vedhakoushik

Copy link
Copy Markdown

Summary

Fixes a bug where setting tools.core to any value — including [] — silently disabled every MCP tool, regardless of trust settings, because a wildcard DENY rule had no way to exclude MCP tools from matching it.

Details

  • Added an opt-in builtinOnly field to PolicyRule (types.ts). When set, the rule never matches MCP tool calls, regardless of its toolName pattern.
  • ruleMatches() now short-circuits builtinOnly rules for any tool call with a serverName (i.e. an MCP tool), falling back to isMcpToolName(toolCall.name) (the mcp_ prefix) when serverName metadata is missing or incomplete.
  • The Core Tools Allowlist Enforcement rule in config.ts now sets builtinOnly: true, so tools.core matches its documented scope ("Restrict the set of built-in tools") without also silently excluding MCP tools from mcpServers.<name>.trust, mcp.allowed, and mcp.autoAllowInHeadless.
  • Because PolicyEngine.getExcludedTools() (which drives which tool declarations reach the model) shares the same ruleMatches() used for call-time checks, this one change fixes both the declaration-level exclusion and the call-time deny.
  • Clarified tools.core in docs/reference/configuration.md to state explicitly that it does not affect MCP tools.

Related Issues

Fixes #28361

How to Validate

  1. settings.json:
    {
      "mcpServers": {
        "github": {
          "command": "github-mcp-server",
          "args": ["stdio"],
          "trust": true
        }
      },
      "tools": {
        "core": []
      }
    }
  2. Run: gemini --approval-mode yolo -p "Call any tool from the github MCP server"
  3. Before this fix: the model gets no tool declarations for the github MCP server and any attempted call fails with Tool "<name>" not found. After this fix: the MCP tool is discoverable and callable.
  4. Run the regression tests: npm test -w @google/gemini-cli-core -- src/policy/config.test.ts src/policy/policy-engine.test.ts

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
    • Linux
      • npm run
      • npx
      • Docker

Supersedes #28365, opened as a clean re-submission — the original PR's commits carried a Co-Authored-By trailer that blocked the CLA check from resolving. Same fix, same tests, no code changes; only the commit metadata differs.

Setting settings.tools.core to any value, including [], added a wildcard
'*' DENY rule with no way to exclude MCP tools from matching it. That DENY
(priority 4.24) outranked every MCP-specific allow mechanism —
mcpServers.<name>.trust (4.2), mcp.allowed, and mcp.autoAllowInHeadless
(4.1) — so all MCP tools were silently denied regardless of trust
settings. Because PolicyEngine.getExcludedTools() (which drives which
tools are removed from the model's declarations) reuses the same rule
matching as call-time checks, the tools weren't just denied at call time —
their declarations never reached the model, so it blind-guessed tool
names until exhausting maxSessionTurns. This also contradicted
tools.core's documented scope: "Restrict the set of built-in tools."

Add an opt-in builtinOnly field to PolicyRule. When set, the rule never
matches MCP tools, regardless of its toolName pattern — including the
wildcard '*'. All MCP tools are structurally guaranteed to carry the
mcp_ prefix (MCP_TOOL_PREFIX / isMcpToolName()), independent of any
metadata being correctly populated, so builtinOnly checks serverName OR
isMcpToolName(toolCall.name) to stay reliable even when metadata is
missing or incomplete. Set builtinOnly: true on the Core Tools Allowlist
Enforcement rule in config.ts, so it stays scoped to built-in tools as
documented while leaving MCP tools governed by their own trust/allow
mechanisms.

Because getExcludedTools() and the real-time check() share the same
ruleMatches() function, this one change fixes both the declaration-level
exclusion and the call-time deny.

Added regression tests: builtinOnly matching in ruleMatches() and
getExcludedTools(), a priority-ordering test reproducing the exact issue
scenario, and end-to-end tests through createPolicyEngineConfig +
PolicyEngine reproducing the issue's minimal repro. Also clarified the
tools.core docs to state explicitly that it does not affect MCP tools.

Fixes google-gemini#28361

Signed-off-by: Bellam vedha kousik <bellam.vedhakoushik@gmail.com>
@vedhakoushik vedhakoushik requested review from a team as code owners July 13, 2026 07:43
@github-actions github-actions Bot added the size/l A large sized PR label Jul 13, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/L

  • Lines changed: 259
  • Additions: +258
  • Deletions: -1
  • Files changed: 6

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a bug where the tools.core configuration setting inadvertently disabled all MCP tools by applying a global wildcard deny rule. By introducing a builtinOnly property to policy rules, the system can now distinguish between built-in tools and MCP tools, ensuring that global restrictions on built-in tools do not override explicit MCP trust and allowlist configurations. This change improves the robustness of the tool policy engine and aligns behavior with documented expectations.

Highlights

  • Policy Rule Scoping: Introduced a builtinOnly flag to PolicyRule to ensure wildcard deny rules only affect built-in tools, preventing them from unintentionally blocking MCP tools.
  • Policy Engine Logic: Updated ruleMatches to short-circuit builtinOnly rules when an MCP tool is detected, using both server metadata and the mcp_ prefix as a fallback.
  • Configuration Fix: Applied builtinOnly: true to the Core Tools Allowlist Enforcement rule, ensuring tools.core settings correctly restrict only built-in tools as documented.
  • Documentation: Clarified in configuration.md that tools.core does not affect MCP tools, which are managed via separate trust and allowlist settings.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a bug where configuring the core tools allowlist (tools.core) would inadvertently block Model Context Protocol (MCP) tools. To fix this, a new builtinOnly flag has been introduced to the PolicyRule interface, allowing wildcard DENY rules to be scoped exclusively to built-in tools. The policy engine has been updated to respect this flag, and comprehensive unit tests have been added to prevent regressions. Additionally, the configuration documentation has been updated to clarify the scope of tools.core. I have no further feedback to provide as the implementation is robust and well-tested.

@gemini-cli gemini-cli Bot added priority/p1 Important and should be addressed in the near term. area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality priority/p1 Important and should be addressed in the near term. size/l A large sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Any settings.tools.core value (even []) emits a wildcard DENY that silently excludes all MCP tools – breaks run-gemini-cli's shipped pr-review example

1 participant