Docs: plugin MCP tool namespacing + allowed-tools vs subagent tools: enforcement are under-documented
Two small but concrete documentation-accuracy issues found while building a Claude Code plugin (verified on 2.1.166 via headless --output-format stream-json runs). Grouping them since both are doc/clarity fixes in the same area. Related: #65768.
---
1. Plugin-provided MCP tools are double-namespaced — undocumented
The docs describe MCP tool names as mcp__<server>__<tool>. But for a tool from a plugin's bundled MCP server, the actual name is:
mcp__plugin_<pluginName>_<serverName>__<tool>
— both the plugin name and the .mcp.json server key appear. For example, a server keyed myserver (in .mcp.json) inside plugin myplugin produces:
mcp__plugin_myplugin_myserver__some_tool
not the documented mcp__myserver__some_tool.
Impact: this silently broke our command allowed-tools entries and in-prompt tool references until we read the real tool_use names off a stream-json transcript. The plugin-MCP naming form isn't stated in the plugins or MCP docs.
Ask: document the mcp__plugin_<plugin>_<server>__<tool> form for plugin-bundled MCP servers, and ideally surface the exact callable name in /mcp.
---
2. Command allowed-tools and subagent tools: are both called "allowlists" but enforce differently
Both fields are described as allowlists, but they behave differently at runtime, and the difference is security-relevant:
- **A command's
allowed-toolsis not a boundary** — it only auto-approves the listed tools. Unlisted tools remain callable (they prompt in normal mode; run silently underbypassPermissions). Verified: a slash command whoseallowed-toolsdid not includeBashstill executed aBashcall underbypassPermissions. - **A subagent's
tools:is effectively a hard boundary** — the subagent is spawned with exactly that toolset, so unlisted tools are genuinely uncallable, even underbypassPermissions. Verified: a subagent definedtools: Read, Grep, Globcould not create a file (noWrite/Bashavailable) underbypassPermissions.
The mechanism difference appears to be: a command runs in the already-loaded session (the list only gates prompting), whereas a subagent is constructed fresh with a chosen toolset (unlisted tools are never added).
Impact: the subagents docs read as if tools: is the same soft allowlist as command allowed-tools. People will reasonably treat per-subagent tools: as a capability boundary (correct) and command allowed-tools the same way (incorrect, a security footgun).
Ask: state explicitly that (a) command/skill allowed-tools is auto-approval, not a capability boundary, and a real boundary needs a deny permission rule; and (b) subagent tools: is a capability restriction (unlisted tools are unavailable to the subagent).
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗