Custom Subagents Cannot Access Project-Scoped MCP Servers (Hallucinate Instead)
Summary
Custom subagents defined in .claude/agents/ cannot call MCP tools from locally-configured MCP servers (project-level .mcp.json). Instead of making actual MCP calls, subagents hallucinate plausible-looking results. Globally-configured MCP servers (~/.claude/mcp.json) work correctly in the same subagents.
Environment
- Claude Code Version: 2.0.68
- OS: macOS Darwin 24.6.0
- Shell: zsh
Steps to Reproduce
1. Set up a local MCP server
Create .mcp.json in project root:
{
"mcpServers": {
"padc-validator": {
"command": "uv",
"args": ["run", "--directory", "/path/to/project/mcp-servers/validator", "server.py"]
}
}
}
2. Create a custom subagent
Create .claude/agents/test-validator.md:
---
name: test-validator
model: haiku
description: Test agent for MCP validation
tools:
- mcp__padc-validator__validate_python_syntax
---
# Test Validator
When asked to validate Python code, call `mcp__padc-validator__validate_python_syntax` with the provided code and report the exact result.
3. Verify MCP server works from main thread
From the main Claude Code session, call the MCP tool directly:
Call: mcp__padc-validator__validate_python_syntax
Args: {"code": "def broken(\n return 42"}
Expected result: {"valid": false, "error": "'(' was never closed", "line": 1, "column": 11}
4. Test the same call via custom subagent
Spawn the custom subagent and ask it to validate the same code:
Task tool with subagent_type="test-validator"
Prompt: "Validate this Python code: def broken(\n return 42"
Expected result: Same error as main thread ('(' was never closed, line 1, column 11)
Actual result: Subagent returns a hallucinated error like invalid syntax (<unknown>, line 2) - different error message, different line number
5. Verify built-in subagent works correctly
Test the same MCP call using the built-in general-purpose subagent:
Task tool with subagent_type="general-purpose"
Prompt: "Call mcp__padc-validator__validate_python_syntax with code 'def broken(\n return 42' and report the exact result"
Result: Returns correct error ('(' was never closed, line 1, column 11)
6. Verify global MCP servers work in custom subagents
If you have a globally-configured MCP server (e.g., Playwright in ~/.claude/mcp.json), test it via a custom subagent:
Result: Works correctly - returns real data, not hallucinated
Evidence from Investigation
Test Matrix
| Subagent Type | MCP Server Location | Result |
|---------------|---------------------|--------|
| Built-in (general-purpose) | Local (.mcp.json) | ✅ Works |
| Built-in (general-purpose) | Global (~/.claude/mcp.json) | ✅ Works |
| Custom (.claude/agents/) | Local (.mcp.json) | ❌ Hallucinates |
| Custom (.claude/agents/) | Global (~/.claude/mcp.json) | ✅ Works |
Hallucination Evidence
Using intentionally broken Python code def broken(\n return 42:
- Real MCP result:
'(' was never closed, line 1, column 11 - Custom subagent (foreground):
invalid syntax (<unknown>, line 2)- WRONG - Custom subagent (background):
SyntaxError: unexpected indent- WRONG (different hallucination) - Built-in subagent:
'(' was never closed, line 1, column 11 - CORRECT
The hallucinated errors are syntactically plausible but factually incorrect, confirming the subagent is not actually calling the MCP tool.
What We Ruled Out
- Not a model issue: Tested with both
haikuandsonnetmodels - same behavior - Not a tools restriction issue: Tested with
tools:field present and omitted - same behavior - Not a foreground/background issue: Both execution modes hallucinate
- Not a tool calling syntax issue: Subagents can call built-in tools (Read, Write, etc.) correctly
Documentation Conflict
The sub-agents documentation states:
"MCP Tools: Subagents can access MCP tools from configured MCP servers. When the tools field is omitted, subagents inherit all MCP tools available to the main thread."
This implies custom subagents should have access to all MCP servers, including local ones. The current behavior contradicts this documentation.
Expected Behavior
Custom subagents should be able to call MCP tools from locally-configured MCP servers (.mcp.json) the same way they can call:
- Built-in tools (Read, Write, Glob, Grep, Bash)
- Globally-configured MCP tools (
~/.claude/mcp.json)
Actual Behavior
Custom subagents cannot call locally-configured MCP tools. Instead, they generate hallucinated responses that look like real MCP tool results but contain incorrect data.
Impact
This bug prevents using custom subagents for workflows that depend on local MCP servers, such as:
- Code validation pipelines
- Project-specific tool integrations
- Custom development workflows
The hallucination behavior is particularly problematic because:
- Results look valid, making the bug hard to detect
- Different runs produce different hallucinated results
- No error message indicates the MCP call failed
Workarounds
- Use built-in
general-purposesubagent for tasks requiring local MCP tools - Move MCP servers to global config (
~/.claude/mcp.json) if project-agnostic - Perform MCP calls at orchestrator level and pass results to subagents
Suggested Fix
Ensure custom subagents defined in .claude/agents/ have access to locally-configured MCP servers from the project's .mcp.json file, consistent with how built-in subagents and globally-configured MCP servers behave.
18 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Update: Confirmed Workaround
Further testing has confirmed that user-scoped MCP servers work correctly in custom subagents, while project-scoped MCP servers do not.
Working Workaround
Add MCP servers with
--scope userinstead of using project-level.mcp.json:This stores the server in
~/.claude.jsonat the user level, and custom subagents can access it correctly.Updated Test Matrix
| Subagent Type | MCP Server Scope | Result |
|---------------|------------------|--------|
| Built-in (
general-purpose) | Project (.mcp.json) | ✅ Works || Built-in (
general-purpose) | User (--scope user) | ✅ Works || Custom (
.claude/agents/) | Project (.mcp.json) | ❌ Hallucinates || Custom (
.claude/agents/) | User (--scope user) | ✅ Works |Conclusion
The bug is specifically in how project-scoped MCP server configurations are inherited by custom subagents. User-scoped servers are inherited correctly.
Trade-off of workaround: User-scoped servers require absolute paths and are available across all projects, so this works best for tools that aren't project-specific.
@YS-Crabtree Ive tried the above workaround, but the MCP tool calls for custom asynchronous agents still fail
| Agent Type | Execution Mode | MCP Access |
|----------------------------|----------------|------------|
| Custom | Sync | ✅ Works |
| Custom | Async | ❌ Fails |
| Built-in (general-purpose) | Sync | ✅ Works |
| Built-in (general-purpose) | Async | ❌ Fails |
The async agent is trying to use Bash commands instead of calling the actual MCP function tools. Removing the project-scoped config didn't help.
The issue persists: async agents don't see MCP tools as callable functions, regardless of:
This appears to be a fundamental bug in how Claude Code passes MCP connections to background agents. Only sync
agents inherit the connections.
@dsull111 how do you run it synchronously?
run_in_background: falsedoes not seem to have an effect?Is this even getting any attention from anthropic? It's such a critical issue that makes sub agents useless hallucinating token wasters.
@dsull111 how do you change sub agent execution mode to sync?
It seems that all my custom sub agents even if i just launch one don't have access to my user scope MCP servers.
Yeah this is a frustrating issue. I've attempted the work around from @dsull111 but had no luck.
Even when spawning a general purpose sub agent and specifying the tools he has access to like which mcp server, that sub agent seems also not to have access to the mcp server like context7 and instead does webfetch research...
Potentially related: #25152 — Zed IDE's
agent_servers.claude.default_mode: "bypassPermissions"setting also causes severe sub-agent hallucination.Same symptom: sub-agents fabricate realistic but completely false data (database results, file contents, config values) instead of failing. The
bypassPermissionssetting may be altering how context/constraints are passed to sub-agents in a way that triggers the same hallucination behavior described here. Removing the setting immediately resolved the issue.Confirmed fixed in
@anthropic-ai/claude-agent-sdk@0.2.63(Claude Code 2.1.30+).We verified this with a standalone test: a custom subagent with
toolsincludingmcp__atlassian__*successfully called an Atlassian MCP server and returned real Confluence data — no hallucination.Requirements for it to work:
toolsconfiguration (e.g.,mcp__atlassian__*)See also: https://github.com/anthropics/claude-code/issues/13605#issuecomment-3981267292
Can confirm this doens't work :(
Still reproducible on Claude Code 2.1.63 (macOS 25.3.0).
Adding a data point: the issue extends beyond project-scoped servers. Custom subagent with
mcpServers: asc-mcpdeclared in frontmatter cannot access a user-scoped MCP server configured in~/.claude.json. Main thread calls the same server successfully. The subagent hallucinates results without any error indication.Re @verveguy's comment about the fix in 2.1.30+ — can confirm it does not resolve the issue for custom agents defined in
.claude/agents/. ThemcpServersfrontmatter field appears to be completely ignored at runtime.See also #25200 for additional reproduction details.
I retract my earlier statement that it works on 0.2.63. It does not work reliably on 0.2.63 nor on the latest 0.2.70
HOWEVER
IFF I set the frontmatter of the .claude/agents/my-test-agent.md to
tools: *OR I omit the tools: line altogether THEN all tools are visible including all MCP tools.Any attempt to restrict the tool list causes ALL MCP tools to be removed from the subagent scope.
We're hitting this too on Claude Code 2.1.76 (Windows).
Our setup: a plugin (Unimind) that defines custom agents in .claude/agents/ with inline MCP server definitions in the frontmatter using type: url and Streamable HTTP transport:
mcpServers:
type: url
url: "${MEMORY_MCP_URL}/mcp/read/mcp"
headers:
Authorization: "Bearer ${MCP_AUTH_TOKEN}"
The MCP server is confirmed working — we did a full handshake test via curl (POST with proper Accept: application/json, text/event-stream header) and got a 200 with valid initialize response, session ID, and reported capabilities.
But when the agents spawn, every MCP tool returns "No such tool available." The tools are never registered. No error is surfaced — agents just silently have no MCP tools.
This matches @verveguy's finding. Our agents don't use a tools: field at all, yet MCP tools from the mcpServers frontmatter are completely ignored. The env vars (MEMORY_MCP_URL, MCP_AUTH_TOKEN) are set and the permissions (mcp__vault-read__, mcp__vault-write__) are granted in ~/.claude/settings.json.
This is a blocker for any plugin architecture that gives agents their own MCP server connections.
I got the custom subagents from the lean4-skills plugin to use the lean4 mcp by using the full specifier in the agent tools definition.
e.g.
lean_goal -> mcp__lean-lsp__lean_goal
lean_hover_info -> mcp__lean-lsp__lean_hover_info
In my case it also worked to ask Claude under what identifier the mcp functions appear.
Hitting this on Claude Code 2.1.116. The scope appears broader than the current issue title suggests — sharing a reproduction matrix in case it's useful.
TL;DR
All MCP servers (local + plugin) fail to propagate to subagents spawned from inside a git worktree, regardless of subagent type or MCP registration scope. The asymmetry is worktree-boundary-specific, not scope-specific and not subagent-type-specific.
Reproduction matrix (2026-04-21, Claude Code 2.1.116)
All probes used the same pattern: a subagent is spawned with a 3-step prompt — Bash
echo STEP1, call the MCP tool, Bashecho STEP3, and report PASS/FAIL verbatim. The Bash bookends prove the subagent actually ran.| Context | Subagent type | MCP | Scope | Result |
|---|---|---|---|:-:|
| Main repo |
researcher(custom) | localcodebase-graph| project.mcp.json| ✅ PASS || Main repo |
implementer(custom) | localcodebase-graph| project.mcp.json| ✅ PASS || Main repo |
tester(custom) | plugincontext-mode| project (plugin-loaded) | ✅ PASS || Main repo |
debugger(custom) | pluginPlaywright| project (plugin-loaded) | ✅ PASS (tool in toolset) || Worktree |
researcher(custom) | localcodebase-graph| project.mcp.json| ❌ FAIL (No such tool available) || Worktree |
general-purpose(built-in) | localcodebase-graph| project.mcp.json| ❌ FAIL (not in loaded tool list, not in deferred tools retrievable via ToolSearch) |Top-level Claude sessions inside the worktree see all MCPs fine —
claude mcp get codebase-graphin the worktree showsScope: Project config (shared via .mcp.json), ✓ Connected. It's only subagents that lose access.We also previously verified the same failure mode against user-scope MCPs (registered via
claude mcp add --scope user, visible in~/.claude.json) — identical worktree-subagent gap, identical main-repo-subagent success. So scope is not the variable; worktree boundary is.Workaround we've shipped
Given both scopes hit the same wall and the degradation is silent (subagent falls back to grep/glob quietly, or fails hard on browser-required MCPs like Playwright), we added a hard preflight refusal to our pipeline orchestrator:
This refuses pipeline initialization from any worktree with a clear error pointing to this issue. Worktrees remain usable for isolated dev work, experiments, and anything not routed through subagents.
Suggested issue-title update
"Subagents spawned from worktrees cannot access MCP servers (project-scope, user-scope, plugin; custom and built-in subagent types)" — current framing "Custom Subagents Cannot Access Project-Scoped MCP Servers" is narrower than the actual symptom, which may obscure prioritization.
Happy to provide provenance-log extracts (PreToolUse/PostToolUse events with Bash bookends) if a maintainer wants deeper diagnostics.
Please fix this! see #25200 for yet more evidence.
Thanks for the report. This was fixed in the 2.1.x series (confirmed working in 2.1.116 and later). Custom subagents now inherit the project's MCP server registry. If you are seeing a worktree-specific variant of this, please follow #47733.
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.