theorydelta field guide
built 2026-06-21 findings: 55 task hubs: 6 independent · evidence-traced · no vendor influence

Agent Config Dependencies Silently Cause Hallucination, Not Errors

Published: 2026-06-01 Last verified: 2026-06-01 empirical
Staleness risk: high — facts in this subject area change quickly between releases. Re-check the specific claims against your own environment before acting. (This rates the topic, not whether this page is out of date.)

Agent Config Dependencies Silently Cause Hallucination, Not Errors

What you expect

Claude Code documentation states that custom subagents in .claude/agents/ inherit all MCP tools available to the main thread when the tools field is omitted. MCP server env blocks in config files are expected to pass credentials to the spawned STDIO server process. The ${VAR} substitution syntax, familiar from Docker Compose and GitHub Actions, is expected to resolve environment variables in .mcp.json files. The Python Claude Agent SDK presents as a Python-native package.

When any of these declared dependencies are missing or mis-scoped, the expected behavior is a clear error that identifies the missing dependency.

What actually happens

The agent does not fail. It produces a plausible-looking wrong result and continues.

Custom subagent MCP scope isolation (fixed in Claude Code 2.1.x) — When a custom .claude/agents/ subagent called an MCP tool that existed in project-scoped .mcp.json, the call silently fell back to the model’s own generation instead of executing the tool. The hallucination was non-deterministic: different runs produced different wrong answers with no error emitted. This was fixed in the 2.1.x series — custom subagents now inherit the project’s MCP server registry (issue #13898, closed).

A worktree-specific variant remains: all MCP servers (local and plugin) fail to propagate to subagents spawned from inside a git worktree, regardless of subagent type. Tracked in issue #47733.

Historical test matrix from issue #13898 (behavior prior to 2.1.x):

Subagent typeMCP server locationResult
Built-in general-purposeLocal .mcp.jsonWorks
Built-in general-purposeGlobal ~/.claude/mcp.jsonWorks
Custom .claude/agents/Local .mcp.jsonHallucinated (fixed in 2.1.x)
Custom .claude/agents/Global ~/.claude/mcp.jsonWorks
Custom .claude/agents/User --scope userWorks

Hallucination evidence from a code validation test against a known Python syntax error (pre-fix):

  • 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, and different from the foreground run

env block not propagated to STDIO servers — The env object in MCP server configs (.mcp.json, claude_desktop_config.json) is stored correctly but not forwarded to the spawned STDIO server process. Servers requiring API keys or auth tokens fail silently at initialization or on the first API call. Confirmed independently across six clients:

ClientIssue
Claude Code VSCode extensionGlobal ~/.claude/mcp.json env block not passed
Claude Code CLIThree separate issues (#1254, #10955, #23216)
mcporterSTDIO servers not receiving env vars
Roo CodeAPPDATA env var not passed on Windows
VSCode MCP extensionServer cannot find env var from mcp_settings.json (#244621)

${VAR} substitution is a silent no-op — Variable substitution syntax in .mcp.json files is not resolved. The literal string ${ANTHROPIC_API_KEY} is passed to the downstream server as its credential. No error is emitted. The MCP client does not validate or reject the literal string; the server receives an invalid credential and fails at the first authenticated call — which may surface as an unrelated error, not a config error.

Claude Agent SDK hidden Node.js dependency — The Python Claude Agent SDK spawns a Node.js process to run cli.js. Missing Node.js produces spawn node ENOENT — a non-obvious error given the SDK presents as a pure Python package. Additionally, including 'user' in settingSources causes the SDK to prioritize ~/.claude/settings.json over environment variable credentials with no warning; if the settings file contains stale or wrong credentials, all API calls fail while the configured env var is silently ignored.

What this means for you

Any custom subagent that relies on project-scoped MCP tools is silently operating without those tools. The agent will not tell you the tool is unavailable — it will produce output that looks like the expected result but isn’t. The non-determinism is the key indicator: if two runs of the same task via a custom subagent produce different outputs, MCP scope mismatch is a primary suspect.

The env block and ${VAR} failures mean that secrets stored in MCP config files in these ways are not being delivered to the servers. Any MCP server requiring authentication may be silently failing or not running at all, while the calling agent continues to operate without knowing the tool is broken.

The combined effect: agent configurations can appear to be set up correctly while every authenticated MCP dependency is non-functional.

What to do

For custom subagent MCP scope isolationupgrade to Claude Code 2.1.x (issue #13898 is closed; fixed). If you’re on an older version and cannot upgrade immediately:

  1. Move the MCP server to user scope: claude mcp add my-server --scope user
  2. Use the built-in general-purpose subagent for tasks requiring project-scoped MCP tools
  3. Perform MCP calls at the orchestrator level and pass results down to the subagent as context

If you’re working in git worktrees: the worktree-specific variant (issue #47733) is still open — use the orchestrator-level workaround above until it lands.

For env block not propagated:

  1. Set required env vars in the shell environment before launching the MCP client — not in the env block of the config file
  2. For systemd service wrappers, use Environment= in the unit file
  3. For CI, set at the job level

For ${VAR} substitution:

  1. Do not use ${VAR} syntax in .mcp.json — it is not resolved
  2. Use shell-level env vars (which propagate via the Pattern 2 workaround above)
  3. Alternatively, use a secrets manager that injects at process spawn time rather than at config parse time

For Claude Agent SDK:

  1. Verify Node.js is installed and on PATH before initializing the SDK in Python environments that don’t bundle it
  2. Omit 'user' from settingSources if credential source should be env vars only
  3. When running in Electron or packaged contexts, compute the cli.js path dynamically post-unpack

Falsification criterion: The MCP scope isolation falsification criterion has been met — Claude Code 2.1.x fixed custom subagent access to project-scoped MCP tools (issue #13898, closed). The remaining failure modes (env block propagation, ${VAR} substitution, Agent SDK hidden Node.js dependency) would be disproved by fixes landing across the affected clients without requiring the shell-level workarounds above.

Evidence

ToolVersionEvidenceResult
Claude Code custom subagentsIssue #13898 — filed 2026-03-08source-reviewedCustom .claude/agents/ subagents hallucinate instead of failing when project-scoped MCP tools are unavailable; non-deterministic wrong outputs confirmed across foreground and background runs
Claude Code CLI env propagationIssues #1254, #10955, #23216independently-confirmedenv block not forwarded to spawned STDIO server process — three separate issues across Claude Code CLI
Claude Code VSCode extensionIssue #28090independently-confirmedGlobal ~/.claude/mcp.json env block not passed to server process
Roo CodeIssue #3702independently-confirmedAPPDATA env var not passed to Windows STDIO server — independently confirms env propagation failure in a separate client
mcporterIssue #64independently-confirmedSTDIO servers not receiving env vars in separate MCP client implementation
Claude Agent SDKreviewed 2026-03-08source-reviewedHidden Node.js runtime dependency; spawn node ENOENT with no docs; settingSources: ['user'] silently overrides env var credentials

Confidence: empirical — 3 tools reviewed, 5 independent issue threads across 4 separate client implementations confirming the env propagation failure.

Strongest case against: Issue #13898 (MCP scope isolation) was fixed in Claude Code 2.1.x — that specific failure mode no longer applies to current versions. The env propagation failures span multiple independent clients (Claude Code CLI, VSCode extension, Roo Code, mcporter), which makes a simultaneous fix less likely — but teams should verify current behavior against their specific client version. The ${VAR} substitution and Agent SDK Node.js dependency failures have no known fix as of this writing.

Open questions: Full taxonomy of hidden runtime dependencies when project-scoped MCP servers are absent from custom subagent scope — the current block documents MCP scope isolation but does not enumerate whether additional tool categories (beyond MCP function tools) silently fall back under the same scope constraint. Status of ${VAR} substitution feature requests across clients. Whether async agents (which also fail to call actual MCP function tools, falling back to Bash commands) share the same root cause as the custom subagent scope isolation failure.

Seen different? Contribute your evidence — theory delta is what makes this knowledge base work.

theorydelta.com · 2026 independent · evidence-backed · every claim sourced or labelled about · glossary · rss · mcp · /scan · llms.txt