On a Monday morning I sat with settings.json open and stopped on one line in the allow list: mcp__figma, and nothing after it.
I couldn't remember writing it. I did remember what it was meant to do — allow the tools of the figma MCP server as a group.
Rereading the official changelog, I found an entry in v2.1.299 (October 14) that touches exactly this style. What I'd like to say first is that you don't need to rewrite everything in a hurry. Start by counting which lines are affected.
What changed
The changelog entry is short. MCP allow rules now reach only the server they name. mcp__a no longer allows a server called a__b or a_, and you're pointed to write mcp__<server>__* using the server's whole normalized name.
So rules that leaned on prefix-style matching are read more narrowly than before. The change narrows permissions; it doesn't widen them, and that decides the order of the recheck.
When permissions narrow, tools you thought were allowed go back to asking for approval. In an unattended run, that is where things stop.
One related note: v2.1.300 fixed deny and ask rules for mcp__<server> not applying when the normalized server name contains a double underscore. That is about the deny side, so I'll keep it separate here.
Only three shapes to check
I sorted the MCP lines in settings.json into three shapes.
| Form | Meaning | From v2.1.299 |
|---|---|---|
| `mcp__github__*` | All tools of the github server | Keeps working |
| `mcp__figma__get_screenshot` | One specific tool | Keeps working |
| `mcp__figma` | Server name only | Recheck; candidate for `mcp__figma__*` |
The third shape is the one I had.
An audit script
Reading by eye misses lines, so I wrote a short script. It reads settings files and sorts only the MCP allow entries into those shapes.
#!/usr/bin/env python3
"""Audit MCP allow rules in settings.json against whole-server-name matching."""
import json, re, sys
from pathlib import Path
def rules(path):
try:
data = json.loads(Path(path).read_text(encoding="utf-8"))
except FileNotFoundError:
return [] # skip missing files quietly
return data.get("permissions", {}).get("allow", [])
def check(rule):
m = re.fullmatch(r"mcp__(.+)", rule)
if not m:
return None # not an MCP rule
rest = m.group(1)
if rest.endswith("__*"):
return ("OK", f"all tools of server '{rest[:-3]}'")
if "__" not in rest:
return ("CHECK", f"server name only; consider mcp__{rest}__*")
return ("OK", "tool name given")
for p in sys.argv[1:]:
for r in rules(p):
res = check(r)
if res:
print(f"{res[0]:6} {r:40} {res[1]} ({p})")Pass the settings files you want checked:
python3 audit_mcp_allow.py ~/.claude/settings.json .claude/settings.json .claude/settings.local.jsonI ran it on a test file containing mcp__notion, mcp__github__* and mcp__figma__get_screenshot. Only the mcp__notion line came back as CHECK. Missing files don't stop it, since not every project has all three.
Confirm the server name before rewriting
I nearly made a mistake here: replacing mcp__figma with mcp__figma__* mechanically.
The changelog asks for the server's whole normalized name, and the name I typed in config may not be the name that appears in tool names. Before rewriting, I look at a real tool name in an approval prompt or in /mcp, and copy the part between mcp__ and the next __.
- Copy the server part of the tool name from the prompt as shown
- Don't fill it in by guesswork; check line by line
- After the edit, call that tool once and confirm no approval prompt appears
Don't widen more than you must
mcp__<server>__* is convenient, but it allows every tool of that server. If a server only needs read access, turning it into a blanket allow defeats the point of this review.
Two earlier articles approach permissions for unattended runs from other angles:
- Narrowing the MCP tools you hand to an unattended agent — deny-by-default through policy enforcement
- You added an allow but the prompt won't go away — reading six layers to see which one decided
Pick the scope by server, and widen by tool. I try to recall that line each time I add a row.
If you do one thing, run the script once and count how many CHECK lines appear. If it's zero, you're done for today.