Auto-approve MCP tools in Claude Code permissions: the mcp__ syntax and its wildcard limits

Claude Code Published:

Put mcp__server or mcp__server__tool in permissions.allow to stop the prompts, why an allow wildcard needs an mcp__<server>__ prefix, and why parenthesised mcp__ rules are skipped.

Verified on Sep 29, 2026 These tools change quickly. Please also check the latest official documentation.
Contents
  1. The three rule shapes
  2. Allow wildcards need an anchor
  3. Deny and ask follow different rules
  4. Where rules live, and what gets ignored
  5. Summary

Add an MCP server and Claude Code asks for approval every time one of its tools runs. Stopping for a read-only lookup on every call gets old fast.

In short: put mcp__<server> in permissions.allow to auto-approve every tool from that server, or mcp__<server>__<tool> for one tool. The catch is that an allow wildcard requires a literal mcp__<server>__ prefix — a pattern like mcp__* is skipped entirely.

For registering the servers themselves, see Adding MCP servers to Claude Code.

KEY POINT

What you will learn

  • The three rule shapes: whole server, wildcard, single tool
  • Why allow wildcards need an anchor, and how deny and ask differ
  • That mcp__ rules with parentheses are silently skipped from settings files

The three rule shapes

The docs put it this way: MCP rules use the server name as configured in Claude Code, optionally followed by the name of a tool from that server.

RuleWhat it matches
mcp__puppeteerAny tool provided by the puppeteer server
mcp__puppeteer__*The same set, written as a wildcard
mcp__puppeteer__puppeteer_navigateOnly the puppeteer_navigate tool from that server

In settings.json:

{
  "permissions": {
    "allow": [
      "mcp__puppeteer",
      "mcp__github__get_issue",
      "mcp__github__list_pull_requests"
    ]
  }
}

The server name is whatever you passed to claude mcp add, or the key in .mcp.json. The separator is two underscores, both between mcp and the server and between the server and the tool.

用語解説

Server name: the name you chose in claude mcp add <name> .... Rename the server and every rule for it changes too, so when a team shares .claude/settings.json, agree on the names in .mcp.json first.

Allow wildcards need an anchor

This is the part that catches people. The docs state that allow rules accept tool-name globs only after a literal mcp__<server>__ prefix, and that the server segment must be glob-free so the rule names a specific server you configured.

PatternResult in allow
mcp__puppeteer__*Works. Matches every tool from puppeteer
mcp__github__get_*Works. Matches that server's get_ tools
mcp__*Skipped with a warning; auto-approves nothing
* / B*Skipped, same as above

So there is no way to say "allow all MCP tools" in one allow rule. List each server.

{
  "permissions": {
    "allow": [
      "mcp__puppeteer__*",
      "mcp__github__get_*",
      "mcp__linear__*"
    ]
  }
}

Deny and ask follow different rules

Deny and ask rules do accept globs in the tool-name position. The pattern must match the full tool name: "*" matches every tool, and "mcp__*" matches every MCP tool across all servers.

{
  "permissions": {
    "deny": [
      "mcp__*"
    ]
  }
}

Rules are evaluated in order: deny, then ask, then allow. The first match in that order determines the outcome, and rule specificity doesn't change it. A broad deny wins over a narrower allow, and an allow rule can't carve an exception out of a deny.

GoalWhere and what
Allow a server's tools wholesaleallow: mcp__<server>
Block one dangerous tooldeny: mcp__<server>__<tool>
Block all MCP toolsdeny: mcp__*
Prompt every timeask: any of the same patterns

A deny rule that names a bare tool removes the tool from Claude's context, so Claude never sees it. A scoped rule leaves the tool available and blocks matching calls when Claude attempts them.

One thing to watch: a deny or ask rule whose tool name matches no known tool normally produces a startup warning to catch typos, but tool names containing _ or * are exempt from that check. Every mcp__ name qualifies, so a misspelled server name fails silently.

Where rules live, and what gets ignored

Write rules in settings.json and inspect them with /permissions. The dialog lists every rule and the settings.json file it came from. You can open it while Claude is working: adding or removing a rule applies from Claude's next tool call in the same turn (v2.1.234 or later). For the files and their precedence, see Configuring permissions in Claude Code's settings.json, and for driving the dialog, The /permissions command.

mcp__ rules with parentheses are skipped

The Bash(npm run build) style of narrowing by argument does not work for MCP tools. When Claude Code loads a settings file, it skips any mcp__ rule that has parentheses. Skipped rules are listed in the invalid-settings dialog when an interactive session starts, and in claude doctor output. To match a parameter on an MCP tool, pass a deny rule with --disallowedTools instead.

There is a second case where an allow rule has no effect. If your organization has set a claude.ai connector tool to ask and that setting reaches your session, allow rules for that tool don't apply: Claude Code prompts on every call, even in auto and bypassPermissions modes. In dontAsk mode, which never prompts, it denies the call instead. Tools from connectors Claude Code fetches itself appear as mcp__claude_ai_<server>__<tool>.

Summary

  • allow takes mcp__<server> for a whole server and mcp__<server>__<tool> for one tool
  • An allow wildcard only works after mcp__<server>__; mcp__* and * are skipped with a warning
  • Deny and ask accept full tool-name globs, so deny: ["mcp__*"] blocks every MCP tool
  • Evaluation is deny → ask → allow, first match wins, regardless of specificity
  • Parenthesised mcp__ rules are skipped from settings files; use --disallowedTools to match a parameter

FAQ

How do I allow every tool from one MCP server?
Put "mcp__<server>" in permissions.allow in settings.json. "mcp__<server>__*" means the same thing. The server name is the name you registered with Claude Code.
Why does "mcp__*" in allow do nothing?
Allow rules accept a tool-name wildcard only after a literal mcp__<server>__ prefix. An unanchored pattern such as "mcp__*" is skipped with a warning and auto-approves nothing.
Can I write mcp__github__create_issue(title:*)?
No. When Claude Code loads a settings file it skips any mcp__ rule that has parentheses. To match a parameter on an MCP tool, pass a deny rule with --disallowedTools.
How do I deny all MCP tools?
Put "mcp__*" in permissions.deny. Deny and ask rules do accept a glob in the tool-name position, so that pattern works there.

Primary sources

This article was drafted by AI from official documentation and reviewed by the site operator before publishing. Found a mistake? Let us know via the contact page.