Docs: plugin MCP tool namespacing + allowed-tools vs subagent tools: enforcement are under-documented

Resolved 💬 1 comment Opened Jun 6, 2026 by bekalpaslan Closed Jul 12, 2026

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-tools is not a boundary** — it only auto-approves the listed tools. Unlisted tools remain callable (they prompt in normal mode; run silently under bypassPermissions). Verified: a slash command whose allowed-tools did not include Bash still executed a Bash call under bypassPermissions.
  • **A subagent's tools: is effectively a hard boundary** — the subagent is spawned with exactly that toolset, so unlisted tools are genuinely uncallable, even under bypassPermissions. Verified: a subagent defined tools: Read, Grep, Glob could not create a file (no Write/Bash available) under bypassPermissions.

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).

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗