Subagents (Agent tool) cannot reach the LSP tool, contradicting documented MCP/tool inheritance
Description
The LSP tool (provided via the official LSP plugins, e.g. pyright-lsp@claude-plugins-official, rust-analyzer-lsp@claude-plugins-official, clangd-lsp@claude-plugins-official) is available and fully functional in the main conversation thread, but is completely unreachable from any subagent spawned via the Agent tool — built-in or custom, regardless of tools/disallowedTools configuration.
This contradicts the sub-agents documentation, which states:
Subagents inherit the internal tools and MCP tools available in the main conversation by default.
Repro
- Enable an LSP plugin (e.g.
pyright-lsp) insettings.jsonenabledPlugins, in a project with a supported language file. - In the main thread, confirm the tool is reachable:
```
ToolSearch({query: "select:LSP", max_results: 5})
LSP
→ returns the full function schema, and calling it (e.g. operation: "documentSymbol"`) works correctly.
- Spawn a plain, unmodified subagent via the
Agenttool (e.g.subagent_type: "general-purpose", no custom.claude/agents/*.mdoverride, notools/disallowedToolsrestriction) and have it run the identical call:
```
ToolSearch({query: "select:LSP", max_results: 5})
"No matching deferred tools found"`.
→ returns
Also reproduced with a custom subagent definition at .claude/agents/Explore.md (overriding the built-in Explore agent by name) using a disallowedTools denylist that does not mention LSP — same result, LSP is absent from that subagent's ToolSearch results.
Expected
Per the documented default, a subagent with no explicit tool restriction on LSP should be able to find and call it via ToolSearch, the same as the main thread.
Actual
LSP is never present in a subagent's deferred-tool registry, in any subagent context tested (built-in general-purpose, built-in Explore override, no restriction present in tools/disallowedTools).
Impact
This blocks any workflow that wants subagents (e.g. a read-only "Explore"/code-search subagent) to prefer LSP-based code navigation (documentSymbol, hover, goToDefinition, etc.) over grep/text search — the tool is architecturally unavailable to them, so prompt-level instructions to "try LSP first" cannot succeed no matter how the subagent is configured.
Environment
- Platform: Linux
- LSP plugins:
pyright-lsp@claude-plugins-official,rust-analyzer-lsp@claude-plugins-official,clangd-lsp@claude-plugins-official(all enabled insettings.json) - Reproduced via both the top-level
Agenttool withsubagent_type: "general-purpose"(default config, no overrides) and a custom.claude/agents/Explore.mdoverride
4 Comments
Reproduced on macOS with
csharp-lsp@claude-plugins-official, with one refinement that may narrow this down: for us the failure is specific to background subagents (run_in_background: true). Foreground subagents load and useLSPwithout issue.Evidence matrix (Claude Code 2.1.205; also reproduced on 2.1.202/2.1.203)
| Context |
ToolSearch("select:LSP")| MCP-server tools via ToolSearch ||---|---|---|
| Main thread | ✅ schema returned, tool works end-to-end | ✅ |
| Foreground subagent (
run_in_background: false) | ✅ schema returned first try, verified working (documentSymbol,workspaceSymbol,findReferencesreturn real results) | n/a (agent had explicittools:list) || Background subagent (
run_in_background: true) | ❌"No matching deferred tools found"| ✅ all 16 tools of a project-local stdio MCP server discoverable and loadable |Details:
tools:list that includesLSP, built-ingeneral-purpose, and an unrestricted (tools: *) custom agent. Not a startup race: it still fails when retried well after LSP was warmed up elsewhere in the same session.ENABLE_LSP_TOOL=1insettings.jsonenvmakes no difference (tested across a full restart).LSPtool is missing from the background deferred-tool registry.So at least on macOS the inheritance break appears scoped to the plugin-provided
LSPtool × background execution, rather than subagents generally. (If the original report's subagents were foreground, Linux may behave differently — worth confirming which mode was used.)Environment: macOS 26.5.2 (Darwin 25.5.0), Claude Code 2.1.205,
csharp-lspplugin 1.0.0, csharp-ls 0.24.0.They were background
Reproduced on macOS with a clangd plugin (not just csharp-ls), confirming the bug isn't language-server-specific.
.lsp.jsonpluginLSP hover/goToDefinitionwork end-to-end ✅run_in_background: true, the Agent tool default) —ToolSearch("select:LSP")→"No matching deferred tools found"; fails across a full restart, on a custom agent whose frontmattertools:explicitly listsLSP, ongeneral-purpose, and on an unrestrictedtools: *agent ❌run_in_background: false), same agent type / same session —LSP hoversucceeds on the first call, no ToolSearch needed ✅So the foreground/background split reported above reproduces exactly with a second, unrelated language server on 2.1.207. The
run_in_background: falseworkaround is reliable.Reproduced on 2.1.233 (Linux,
pyright-lsp@claude-plugins-official): the LSP tool works in the main conversation (hover returns results), but a subagent spawned via the Agent tool reports no LSP tool available, even via ToolSearch.This is intended behavior from two changes rather than broken inheritance: subagents now run in the background by default (since ~2.1.198, about when you filed this), and background subagents keep every MCP tool but only a fixed set of built-in tools — LSP isn't in that set, and listing it in a subagent's
toolsfield doesn't add it back. In interactive sessions, regular subagent spawns now always run in the background, so LSP is effectively main-conversation-only there. In headlessclaude -p, a foreground subagent still gets the LSP tool — verified hover works on 2.1.233.You were right that the docs contradicted this at the time. They've since been updated: sub-agents → Available tools now documents both tool filters, including the exact background tool list.
We agree the result is confusing — we're considering whether the read-only LSP tool should stay available to background subagents, and adding a note to the LSP plugin docs. Leaving this open to track that.
🤖 Generated with Claude Code