Task agent fails with 'tools: Tool names must be unique' when parent has many MCP tools

Resolved 💬 30 comments Opened Oct 31, 2025 by prefrontalsys Closed Oct 31, 2025
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Bug: Task agent fails with "tools: Tool names must be unique" when parent has many MCP tools

Environment

Claude Code Information:

  • Version: 2.0.30
  • Install method: Global
  • Node.js version: v24.10.0

System Information:

  • OS: macOS (Darwin Kernel 25.0.0)
  • Architecture: ARM64 (Apple Silicon)
  • Terminal: iTerm2
  • Shell: bash

MCP Configuration:

  • Total MCP servers: 13 servers
  • Total unique tools: 74 tools
  • Configuration scope: Mixed (12 project-level + 1 global)

MCP Server Inventory

Project-level servers (configured in /Users/sc/Documents/GitHub/.claude.json):

  1. arxiv-mcp-server - 4 tools (stdio, uv)
  2. claude-skills - 3 tools (stdio, uvx)
  3. clear-thought-mcp-server - 11 tools (stdio, npx/smithery)
  4. context7 - 2 tools (stdio, npx)
  5. lightpanda - 5 tools (stdio, local binary)
  6. mcp-deepwiki - 1 tool (stdio, npx)
  7. mnemex - 13 tools (stdio, local binary)
  8. playwright - 21 tools (stdio, npx)
  9. perplexity-search - 1 tool (stdio, npx/smithery)
  10. mcp-mermaid - 1 tool (stdio, npx)
  11. obsidian-mcp-server - 8 tools (stdio, npx)
  12. ai-humanizer - 1 tool (stdio, npx)

Global server (configured in root .claude.json):

  1. deepwiki - 3 tools (HTTP transport)

Description

Task agent subprocess launches fail with API error when the parent Claude Code process has many MCP servers configured. Commands that rely on the Task tool (like /sidequest) consistently fail to launch background agents.

Critical: This occurs despite:

  • All 74 tools being properly namespaced (mcp__<server>__<tool>)
  • No duplicate tool names in the main process
  • Valid MCP server configuration
  • Main Claude Code session working perfectly with all tools

Error Message

API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"tools: Tool names must be unique."}}

Steps to Reproduce

  1. Configure 12+ MCP servers in project .claude.json with mixed transports (stdio, HTTP)
  2. Configure 1+ global MCP server in root .claude.json
  3. Verify main process works: run any command that uses MCP tools directly
  4. Attempt to launch Task agent subprocess: run /sidequest <any query>
  5. Observe immediate failure with "tools must be unique" error

Expected Behavior

Task agent subprocess should:

  • Successfully launch with inherited tool configuration
  • Receive properly namespaced tools from parent process
  • Execute the requested task independently

Actual Behavior

Task agent subprocess:

  • Fails immediately during initialization
  • Returns 400 error about duplicate tool names
  • Never begins actual task execution
  • Forces fallback to direct execution in main process

Detailed Technical Analysis

Configuration Validation

I verified the configuration extensively:

# All 74 tools have unique names
$ python3 << 'PYTHON'
from collections import Counter
tools = [<all 74 tool names>]
counts = Counter(tools)
duplicates = {t: c for t, c in counts.items() if c > 1}
print(f"Duplicates: {duplicates}")  # Output: {}
print(f"Total: {len(tools)}, Unique: {len(set(tools))}")  # 74, 74
PYTHON

Result: Zero duplicate tool names in main process configuration.

Tool Namespacing

All tools follow proper MCP namespacing convention:

mcp__<server-name>__<tool-name>

Example:

  • mcp__arxiv-mcp-server__search_papers
  • mcp__mnemex__save_memory
  • mcp__playwright__browser_navigate

Even the potentially confusing servers are properly namespaced:

  • deepwiki (global) → mcp__deepwiki__read_wiki_contents
  • mcp-deepwiki (project) → mcp__mcp-deepwiki__deepwiki_fetch
Hypothesis: Subprocess Tool Inheritance Bug

The error occurs specifically during Task agent subprocess initialization:

  1. Parent process (main Claude Code session):
  • Loads 13 MCP servers successfully
  • Registers 74 unique tools
  • Functions normally with all tools
  1. Subprocess creation (Task agent launch):
  • Attempts to inherit tool configuration from parent
  • Something in serialization/deserialization creates duplicates
  • Anthropic API rejects request before agent starts

Possible causes:

  • Tools added twice during subprocess initialization
  • MCP server lifecycle issues when spawning subprocess
  • Tool configuration serialized incorrectly for API request
  • Parent process tool list merged incorrectly with subprocess defaults
Relation to v2.0.30 Changelog

The v2.0.30 changelog states:

"Fixed MCP tools not being available to sub-agents"

This suggests the Claude Code team attempted to fix tool availability in subprocesses. However, the fix may have introduced a regression where tools are now duplicated instead of being unavailable.

Timeline:

  • Pre-2.0.30: MCP tools unavailable to sub-agents (original bug)
  • v2.0.30: Attempted fix for tool availability
  • Post-2.0.30: Tools available but duplicated (new regression)

Impact

Affected functionality:

  • /sidequest command completely non-functional
  • Any custom agent that uses Task tool fails
  • Background research agents cannot be launched
  • Multi-agent workflows broken

Workarounds discovered:

  1. Temporarily disable MCP servers via /mcp before Task agent launch
  2. Create minimal workspace with subset of MCP servers
  3. Execute tasks directly in main process (defeats purpose of agents)

Related Issues

  • Issue #703 (closed): Similar error message but different cause (slash command collision with MCP). Fixed in v0.2.64.
  • No other reports found for this specific Task agent + MCP tool duplication bug

Reproduction Rate

100% reproducible with configuration of 74 MCP tools across 13 servers.

Unknown threshold - needs testing:

  • Does it occur with fewer tools? (e.g., 50 tools, 10 servers)
  • Is there a tool count limit for subprocesses?
  • Does it depend on transport type mix (stdio vs HTTP)?

Logs/Additional Context

Attempted Task launch (excerpt):

# First attempt
Task tool call → API Error 400 "tools must be unique"

# Immediate retry
Task tool call → API Error 400 "tools must be unique"

# Both attempts failed before agent could start

Main process continues to function normally with all tools after failed subprocess launch.

Request

Could the Claude Code team:

  1. Investigate subprocess tool inheritance mechanism in v2.0.30
  2. Add debug logging for tool registration during subprocess creation
  3. Consider tool count limits or configuration validation
  4. Test with large MCP configurations (10+ servers, 50+ tools)

This appears to be a regression introduced by the MCP sub-agent availability fix in v2.0.30.

View original on GitHub ↗

30 Comments

wehriam · 8 months ago

I am seeing this behavior with a single MCP server.

AmeliasCode · 8 months ago

Seeing the same error but I have zero MCP servers.

github-actions[bot] · 8 months ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/7296
  2. https://github.com/anthropics/claude-code/issues/5465

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

JaydenScholz · 8 months ago

It appears to be with the general Task agents: Explore/Plan/general-purpose (these all return "Done (0 tool uses · 0 tokens · 1s)") when any MCP server is enabled, whether project or user based.

Yet other custom agents (stored in .claude/agents/) seem to function as per normal with MCP servers enabled.

Deleted all MCP configurations and the 3 function as per normal.

Additional API Error Details (via Claude Code assistant testing):

When attempting to invoke any built-in subagent with MCP servers enabled, the following API error is consistently returned:

API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"tools: Tool names must be unique."},"request_id":"............."}

This error occurs for:

  • subagent_type: "Explore"
  • subagent_type: "Plan"
  • subagent_type: "general-purpose"

But NOT for custom agents defined in .claude/agents/*.md:

  • ✅ All custom agents work correctly

Root cause hypothesis: When MCP servers are enabled, the tool registration system appears to be duplicating tool names when constructing the built-in subagent tool configurations, causing the API to reject the request due to non-unique tool names in the tools array.

Environment: Claude Code v2.0.30+ with any MCP server configuration enabled (Context7 MCP server confirmed in testing).

Update: Inconsistent results with custom agents across multiple projects. Some execute correctly whilst others fail with similar issues.

nimoalr · 8 months ago

Can confirm, same issue on 2.0.30 - reverting to 2.0.29 makes my agents works again. Worth noting my project agents were also affected.

ariccio · 8 months ago

Me too. Feedback ID: 815421a5-d203-4745-9fad-a0d621fa0cc2

bannsec · 8 months ago

this issue for me on 2.0.30. however, i'm just trying to basic agent call with agents that have worked forever. the agents are defined in .claude/agents/* . none of them are doing subagents, this is just strait, normal agent call from the claude code terminal, and all of them fail. this is pretty problematic.

I've been reverting to 2.0.28 to continue working:

npm install -g @anthropic-ai/claude-code@2.0.28

2.0.30 should probably be retracted given how bad this bug is.

ariccio · 8 months ago

Rewinding doesn't work. BUT relaunching and resuming has worked a few times for me now. That indicates that reverting may not work much better than just relaunching. (though reverting will ensure it won't come back?)

bannsec · 8 months ago
Rewinding doesn't work. BUT relaunching and resuming has worked a few times for me now. That indicates that reverting may not work much better than just relaunching. (though reverting will ensure it won't come back?)

i have tried relaunching, it didn't fix the issue for me. only reverting to an older version fixed it. i've even started brand new claude code chats and agent was still broken on .30.

ariccio · 8 months ago

Some poor anthropic SRE must be having a CLAUDE_CODE_FORCE_HALLOWEEN of their own tonight!

I kid I kid. That is the name of a new env var tonight though.

ariccio · 8 months ago
> Rewinding doesn't work. BUT relaunching and resuming has worked a few times for me now. That indicates that reverting may not work much better than just relaunching. (though reverting will ensure it won't come back?) i have tried relaunching, it didn't fix the issue for me. only reverting to an older version fixed it. i've even started brand new claude code chats and agent was still broken on .30.

If you don't need to use an MCP for a subagent, try turning off the MCP with the new @, THEN restarting.

It's a teeny tiny bit of a pain for planning (where I use subagents for the most part!) but it works okay right now if I tell claude some variant of "the xcodebuildmcp is currently disabled, but I will enable it before we begin work, ensure that in the first step of the plan you propose, you will pause and wait for me to enable it before proceeding".

ariccio · 8 months ago

Curious discovery: even with @cameroncooke's XCodeBuildMCP disabled via the claude code UI, claude code is guessing the names of tools, e.g.:

 mcp__XcodeBuildMCP__boot_sim(simulatorName: "iPhone 17 Pro")
 mcp__XcodeBuildMCP__build_sim(projectPath: "...", scheme: "DeeDee Health")
 mcp__XcodeBuildMCP__install_app_sim(...)
 mcp__XcodeBuildMCP__launch_app_sim(bundleId: "...")

It may be very good at guessing things in general, but getting it that close indicates to me that maybe there are bits of it left in the context window, and it's echoing through the weird transformer brain far enough to reach the output. That would then explain the duplicate tool error, some code somewhere leaving it in the window and then dumping it in a second time later.

superkoh-nb · 8 months ago

meet exact the same problem in 2.0.30. using same prompts in 2.0.29 is ok.

anduinnn · 8 months ago

Temporarily using version 2.0.29

Perhaps the system prompt for 2.0.30 has changed; I think 30 is not as useful as 29
Ethirajulu · 8 months ago

Quick tip if anyone is looking to downgrade until a fix is available. You could use npx to work with 2.0.29 temporarily

npx @anthropic-ai/claude-code@2.0.29

galcianuk · 8 months ago

Getting this and many other issues in 2.0.30

geopopos · 8 months ago
Can confirm, same issue on 2.0.30 - reverting to 2.0.29 makes my agents works again. Worth noting my project agents were also affected.

This fixed the issue for me as well

Lukavyi · 8 months ago

Temp fix in .zshrc
alias claude="npx @anthropic-ai/claude-code@2.0.29" # temp fix until 2.0.30 is fixed

ackshaey · 8 months ago

Confirmed with no MCP tools but with subagents as well.

ackshaey · 8 months ago

Also confirmed using 2.0.29 fixed the issue from @Lukavyi 's comment above

ghost · 8 months ago

Investigation Report: Task Tool API Error

Root Cause Identified

Source: Claude Code CLI tool deduplication bug

Location: Claude Code CLI internals (not MCP, not macOS, not plugin issue)

What's Happening

When the Task tool tries to spawn a subagent:

  1. Task tool needs to pass tool definitions to the subagent
  2. Claude Code CLI combines tools from multiple sources:
  • Core tools (Read, Write, Edit, Bash, etc.)
  • MCP tools (~50 tools from 4 MCP servers: github, btcr-db, memory-bank, filesystem)
  • Plugin skills tools (general-purpose, Explore with "tools: *")
  1. Bug: Tool names are being duplicated somewhere in this merge process
  2. API validation rejects the request: "tools: Tool names must be unique"

Evidence

✅ Confirmed it's NOT:

  • MCP server issue (other MCP tools work fine: mcp__github__, mcp__filesystem__, etc.)
  • macOS issue (platform-agnostic API error)
  • Network issue (reproducible, consistent error)
  • User configuration issue (standard setup)

✅ Confirmed it IS:

  • Claude Code CLI bug in tool propagation logic
  • Only affects Task tool (subagent spawning)
  • Direct tool calls work perfectly
  • Error comes from Anthropic API validation (client sent duplicate tool names)

Technical Details

Error Response:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "tools: Tool names must be unique."
},
"request_id": "req_011CUfS5JpvanCFYUvqNJXdJ"
}

Tool Sources in Session:

  • Core Claude Code tools: ~15 tools
  • MCP github server: ~26 tools
  • MCP btcr-db server: 1 tool
  • MCP memory-bank server: ~9 tools
  • MCP filesystem server: ~15 tools
  • Plugin skills: 4 skills with wildcard access
  • Total: ~80+ tool definitions

Why Direct Tools Work

When I call tools directly (Read, Edit, Write, Bash), Claude Code CLI doesn't need to:

  • Merge tool definitions
  • Pass tools to a subagent
  • Deduplicate tool names

The bug only triggers when Task tool tries to create a subagent environment.

Workaround (Current)

✅ Use direct tool calls instead of Task tool subagents
✅ All other functionality works perfectly
✅ Implementation completed successfully despite this limitation

Fix Required

Claude Code CLI needs to implement proper tool deduplication when spawning Task tool subagents. This is a client-side bug that should be reported to
the Claude Code team.

Recommendation: File a GitHub issue at https://github.com/anthropics/claude-code/issues with this investigation report.

ashwin-ant collaborator · 8 months ago

Fix landing in 2.0.31 later today

genesiscz · 8 months ago
Fix landing in 2.0.31 later today

Is there a way to use this already with some "next" flag or something?

ariccio · 8 months ago
Investigation Report: Task Tool API Error Root Cause Identified Source: Claude Code CLI tool deduplication bug Location: Claude Code CLI internals (not MCP, not macOS, not plugin issue) What's Happening When the Task tool tries to spawn a subagent: 1. Task tool needs to pass tool definitions to the subagent 2. Claude Code CLI combines tools from multiple sources: - Core tools (Read, Write, Edit, Bash, etc.) - MCP tools (~50 tools from 4 MCP servers: github, btcr-db, memory-bank, filesystem) - Plugin skills tools (general-purpose, Explore with "tools: ") 3. Bug: Tool names are being duplicated somewhere in this merge process 4. API validation rejects the request: "tools: Tool names must be unique" Evidence ✅ Confirmed it's NOT: MCP server issue (other MCP tools work fine: mcp__github___, mcp__filesystem___, etc.) macOS issue (platform-agnostic API error) Network issue (reproducible, consistent error) User configuration issue (standard setup) ✅ Confirmed it IS: Claude Code CLI bug in tool propagation logic Only affects Task tool (subagent spawning) Direct tool calls work perfectly Error comes from Anthropic API validation (client sent duplicate tool names) Technical Details Error Response: { "type": "error", "error": { "type": "invalid_request_error", "message": "tools: Tool names must be unique." }, "request_id": "req_011CUfS5JpvanCFYUvqNJXdJ" } Tool Sources in Session: Core Claude Code tools: ~15 tools MCP github server: ~26 tools MCP btcr-db server: 1 tool MCP memory-bank server: ~9 tools MCP filesystem server: ~15 tools Plugin skills: 4 skills with wildcard access Total: ~80+ tool definitions Why Direct Tools Work When I call tools directly (Read, Edit, Write, Bash), Claude Code CLI doesn't need to: Merge tool definitions Pass tools to a subagent * Deduplicate tool names The bug only triggers when Task tool tries to create a subagent environment. Workaround (Current) ✅ Use direct tool calls instead of Task tool subagents ✅ All other functionality works perfectly ✅ Implementation completed successfully despite this limitation Fix Required Claude Code CLI needs to implement proper tool deduplication when spawning Task tool subagents. This is a client-side bug that should be reported to the Claude Code team. Recommendation: File a GitHub issue at https://github.com/anthropics/claude-code/issues with this investigation report.

You're going to get generally suboptimal bug report generation from an LLM like claude ("Only affects Task tool (subagent spawning)" is plain wrong) because claude doesn't have access to the original uncompiled and unpackaged claude code cli source code.

This affected Plan and Explore subagents too.

ariccio · 8 months ago
> Fix landing in 2.0.31 later today Is there a way to use this already with some "next" flag or something?

If you need to workaround this my workflow has been

  1. Turn off MCP servers, relaunch claude, resume the session
  2. Do whatever subagent tasks you need to do with claude that are currently blocked by this (this is much more workable nowadays than it was 5 months ago)
  3. Re-enable MCPs in claude
nickolay-kondratyev · 8 months ago

@ashwin-ant

Some suggestion to prevent such issues in the future:

1) Suggestion: Add separate braveheart releases with auto updates into versions that are not yet deemed stable. While updating the rest of us only into versions that have had some time to stabilize.

2) Monitor logging during integration tests, if there are any error logs fail the integration tests. So when you test core functionality and get failed to spawn an agent issue the tests break.

Jamie-BitFlight · 8 months ago

Start claude using npx @anthropic-ai/claude-code@2.0.29 instead of claude for now

ashwin-ant collaborator · 8 months ago

2.0.31 is out!

Connoropolous · 8 months ago

I am still seeing this as an issue, when using claude-agent-sdk 0.1.30 which has parity to 2.0.31.

https://github.com/ceedaragents/cyrus/blob/1c53bf7440a624a459e1a7b3756a8b74f4a27a62/pnpm-lock.yaml#L109

Update, per the changelog 0.1.30 of claude-agent-sdk was supposed to include 2.0.31, but in practice seems to still have 2.0.30. Here's some evidence of that:

 Bash(head -10
      /Users/x/code/cyrus/node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.30_zod@3.25.76/node_modules/@anthropic-ai/claude-agent-sdk/cli.js)
  ⎿ #!/usr/bin/env node
    // (c) Anthropic PBC. All rights reserved. Use is subject to the Legal Agreements outlined here: https://docs.claude.com/en/docs/claude-code/legal-and
    -compliance.
    … +205 lines (ctrl+o to expand)


⏺ Yes, I did find it! Line 4 of the cli.js file clearly states:

  // Version: 2.0.30

  So the bundled Claude CLI in the @anthropic-ai/claude-agent-sdk@0.1.30 package is indeed version 2.0.30. This is a comment embedded at the top of the
  minified/bundled CLI executable.

> show me the lines of code in question

⏺ Bash(head -6
      /Users/x/code/cyrus/node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.30_zod@3.25.76/node_modules/@anthropic-ai/claude-agent-sdk/cli.js)
  ⎿ #!/usr/bin/env node
    // (c) Anthropic PBC. All rights reserved. Use is subject to the Legal Agreements outlined here: https://docs.claude.com/en/docs/claude-code/legal-and
    -compliance.
    … +4 lines (ctrl+o to expand)


⏺ Here are the exact lines from the cli.js file:

  #!/usr/bin/env node
  // (c) Anthropic PBC. All rights reserved. Use is subject to the Legal Agreements outlined here:
  https://docs.claude.com/en/docs/claude-code/legal-and-compliance.

  // Version: 2.0.30

  // Want to see the unminified source? We're hiring!

  Line 4 contains the version comment: // Version: 2.0.30

  This is at the top of the bundled CLI file at:
  /Users/x/code/cyrus/node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.30_zod@3.25.76/node_modules/@anthropic-ai/claude-agent-sdk/cli.js

> does it then later pull from that version number to download a cli file?

⏺ Let me search for download logic in the SDK files:

⏺ Search(pattern: "download|fetch|github.*release|https://github|install.*cli", path: "cli.js", output_mode: "content", head_limit: 30)
  ⎿  Found 30 lines (ctrl+o to expand)

⏺ Search(pattern: "spawn|exec|download|github.*release|curl|wget|fetch.*cli", path: "sdk.mjs", output_mode: "content", head_limit: 50)
  ⎿  Found 28 lines (ctrl+o to expand)

⏺ Perfect! Now I can give you the definitive answer:

  No, it does NOT download anything. The cli.js file (9.6MB) IS the complete Claude CLI already bundled into the package.

  Looking at the SDK code (line 14771 in sdk.mjs):

  pathToClaudeCodeExecutable = join3(dirname2, "cli.js");

  The SDK simply spawns the bundled cli.js file using Node.js:

  this.child = spawn(spawnCommand, spawnArgs, {

  How it works:
  1. When you install @anthropic-ai/claude-agent-sdk@0.1.30, it comes with a pre-bundled 9.6MB cli.js file
  2. That file contains the complete Claude CLI v2.0.30 (minified/compiled)
  3. The SDK doesn't download anything - it just executes that bundled file using spawn("node", ["cli.js", ...args])
  4. The version comment // Version: 2.0.30 is just metadata embedded in the bundled code

  So to answer your original question: The CLI version is fixed to whatever comes bundled with that specific SDK version. To get a different Claude CLI
  version, you'd need to install a different version of the @anthropic-ai/claude-agent-sdk package.

> this here changelog: https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md#0130 says that 0.1.30 updated to 2.0.31 seems like
a lie.

⏺ You're absolutely right to call that out. Let me verify what we actually have installed:

⏺ Bash(cat
      /Users/x/code/cyrus/node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.30_zod@3.25.76/node_modules/@anthropic-ai/claude-agent-sdk/package.json
      | g…)
  ⎿    "version": "0.1.30",
       "main": "sdk.mjs",
       "types": "sdk.d.ts",

⏺ Bash(stat -f "Modified: %Sm" -t "%Y-%m-%d %H:%M:%S"
      /Users/x/code/cyrus/node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.1.30_zod@3.25.76/node_modules/@ant…)
  ⎿  Modified: 2025-10-31 00:06:06

⏺ Bash(npm view @anthropic-ai/claude-agent-sdk@0.1.30 --json 2>/dev/null | grep -E '"version"|"time"' | head -20)
  ⎿    "time": {
       "version": "0.1.30",

⏺ Fetch(https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md)
  ⎿  Received 218.5KB (200 OK)

⏺ You're absolutely right - there's a discrepancy. The changelog claims version 0.1.30 should have Claude CLI v2.0.31, but the actual bundled cli.js file
  in your node_modules shows v2.0.30.
github-actions[bot] · 8 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.