MCP permission rules: support argument matching (analogous to Bash(cmd *))

Resolved 💬 3 comments Opened Apr 15, 2026 by shalalalaw Closed Apr 18, 2026

Summary

Claude Code's MCP permission grammar currently supports only server/tool granularity:

  • mcp__<server>
  • mcp__<server>__*
  • mcp__<server>__<tool>

There is no way to match on tool arguments, analogous to Bash(cmd *) or WebFetch(domain:...). Requesting something like:

mcp__gateway__gateway_invoke_tool(name:gmail_*)
mcp__gateway__gateway_invoke_tool(name:*_delete_*)

Motivation

Gateway / meta-tool patterns — including Claude Code's own internal deferred-tools/ToolSearch design — collapse many underlying tools into one permission name, destroying per-tool approval UX.

Our use case: we run an MCP gateway that lazy-loads ~300 tools behind three meta-tools (gateway_list_tools, gateway_describe_tool, gateway_invoke_tool). After this collapse, every tool call shows up as gateway_invoke_tool regardless of whether the inner tool is gmail_search_messages or gmail_delete_message — so users can't grant fine-grained approvals.

Workaround

We've shipped a PreToolUse hook that reads tool_input.name and returns allow/ask/deny per inner tool, with prompt text like "Allow gateway_invoke_tool to call gmail_delete_message?". It works, but hooks are heavier than declarative permission rules and require us to reimplement prompt UX.

Proposal

Extend MCP permission rule grammar to accept a parenthesized specifier that matches structured tool_input fields, at minimum name:<glob>. Ideally the syntax mirrors existing tools (Bash(cmd *)), so:

mcp__gateway__gateway_invoke_tool(name:gmail_*)         # allow all gmail tools
mcp__gateway__gateway_invoke_tool(name:*_delete_*)      # ask before any delete-like tool

Docs reference

Current MCP permission rule grammar: https://code.claude.com/docs/en/permissions#mcp

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗