Subagent MCP tools: one unresolvable name in a subagent tools: list silently voids the whole list (+ undocumented 3k subagent MCP output cap)

Open 💬 0 comments Opened Jul 7, 2026 by eyalcats

Subagent MCP tool handling in Claude Code 2.1.202 — two issues

Version: 2.1.202 · Platform: Windows 11 · first-party API (no proxy)

Both reproduce with a plugin-bundled HTTP MCP server (server key priority-dev, callable as
mcp__plugin_priority-dev_priority-dev__*). The main loop uses the tools fine; only
custom subagents (agents/*.md) are affected.

---

Issue 1 — one unresolvable name in a subagent tools: list silently voids the WHOLE list

An agent whose tools: allowlist contained a valid namespaced MCP name and an
unresolvable one:

tools:
  - mcp__priority-dev__priority_discover                     # NOT a real callable for a
                                                             # plugin-bundled server
  - mcp__plugin_priority-dev_priority-dev__priority_discover # the real callable

spawned with zero callable tools. The model emitted tool calls as plain assistant text
(the tool_use never fired) and fabricated tool results/errors — across runs it invented
"No connections configured…", "Tool not found: … Available tools: …", and "Unknown action:
search". Envelope showed tool_uses: 0.

Isolation test — agent with tools: [Bash, mcp__plugin_priority-dev_priority-dev__priority_discover]
(one native control + ONE valid namespaced MCP name, nothing invalid):

  • Bash → real call ✓
  • priority_discover → real call, live data ✓ (tool_uses: 3)

So scoped MCP allowlists work; the failure is triggered solely by an entry that doesn't
resolve in the current runtime. A single such entry drops the entire list. Expected: ignore an
unresolvable entry (as permission/skill contexts appear to), or at least warn — not silently
void the whole allowlist and leave the agent tool-less (which then hallucinates).

Trap this creates: a plugin can't list both the plugin-namespaced name and the bare
mcp__server__tool name to cover the CLI-plugin runtime and an SDK-mounted runtime at once —
whichever is invalid in a given runtime poisons the list there. There's no single frontmatter
that scopes tools correctly across both.

Issue 1b — disallowedTools also voids tool binding

Adding disallowedTools: Write, Edit, NotebookEdit (a native-tool denylist) to an
otherwise-inheriting agent made it spawn tool-less: any invocation returned
No such tool available: <name>. Removing the line restored all tools.

---

Issue 2 — subagent MCP responses capped at 3000 tokens (undocumented); env var raises it

A subagent MCP call failed with:

MCP tool "priority_discover" response (5387 tokens) exceeds maximum allowed
tokens (3000). Please use pagination, filtering, or limit parameters ...

Docs give the default as 25,000 via MAX_MCP_OUTPUT_TOKENS (warn at 10,000). The 3,000
seen inside a subagent is undocumented and far below that. Setting
MAX_MCP_OUTPUT_TOKENS=50000 (settings.json env) did raise the subagent cap — the same
5,387-token response then returned in full. So the env var governs subagents too, but the
undocumented 3,000 default and the docs/behavior gap are worth fixing.

---

Impact

The natural, least-privilege design (scope a subagent to just the MCP tools it needs) is a
landmine: any name that's invalid in the running context silently disables all of the agent's
tools and it fabricates output. Issue 2 additionally throttles legitimate subagent reads to an
undocumented 3k.

Repro assets

Public plugin eyalcats/priority-dev-plugin (agents under priority-dev/agents/); minimal
repro + native-control agent available on request.

View original on GitHub ↗