claude-code - 💡(How to fix) Fix Bug: LSP tool (jdtls-lsp plugin) not propagated to spawned subagents

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

The LSP built-in tool (activated by jdtls-lsp@claude-plugins-official) is not available to spawned subagents — neither in-process (harness-mode) subagents nor tmux team members — even when the plugin is enabled globally in ~/.claude/settings.json.

MCP-server–backed tools (e.g., mcp__glean_default__*, mcp__plugin_context-mode_context-mode__*) propagate correctly to both subagent types. Only enabledPlugins-only built-in tools are affected.

Root Cause

jdtls-lsp@claude-plugins-official is a bare-marker plugin — its cache directory (~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/) contains only LICENSE and README.md. There is no .claude-plugin/plugin.json, no .mcp.json, no tool declarations. The LSP tool is a built-in Claude Code feature gated solely on "jdtls-lsp@claude-plugins-official": true in enabledPlugins settings.

The harness builds the --plugin-dir list used when constructing subagent tool environments from plugin cache dirs that have recognized manifest files (.claude-plugin/plugin.json, .mcp.json, .cursor-plugin/plugin.json). Since jdtls-lsp has none of these, it never appears in --plugin-dir. Subagent tool environments are built from --plugin-dir-derived MCP server connections — they do not re-read enabledPlugins to activate built-in tools.

The parent session sees LSP because it reads enabledPlugins at startup and activates the built-in tool directly.
Subagents do not because their tool sets are constructed from --plugin-dir entries only.

jdtls-lsp also does not appear in installed_plugins.json — it is a bare built-in that bypasses the normal install-tracking flow entirely.

Fix Action

Fix / Workaround

ProbeChange triedResult
Global enabledPlugins: trueSet in ~/.claude/settings.jsonParent ✅, subagents ❌
Fresh TeamCreate post-enablementCreated team after global enablement
Spawn order variationEnable first, then TeamCreate; vs TeamCreate then enable
Non-team probe (no team context)Omit team_name entirely
tools: ["LSP"] frontmatterAgent allowlist❌ (allowlist, not a grant)
Agent tool schema inspectionCheck for undocumented extraTools/plugins paramsNone found
claude plugin enable --scope=subagentCheck for propagation scope flagFlag does not exist
Team config editing~/.claude/teams/<n>/config.json has no tools/plugins fieldNo workaround path

User-accessible workaround attempt (Fix 4 — validation pending)

Fix 4 (plugin-side): Ship jdtls-lsp with a .claude-plugin/plugin.json so the standard --plugin-dir propagation path carries it to subagents automatically (see workaround above).

Code Example

Agent({
  subagent_type: "general-purpose",
  prompt: "Call ToolSearch(query='select:LSP', max_results=1) and report the exact result verbatim."
})

---

TeamCreate({ name: "lsp-probe" })
Agent({
  subagent_type: "general-purpose",
  team_name: "lsp-probe",
  name: "probe",
  run_in_background: true,
  prompt: "Call ToolSearch(query='select:LSP', max_results=1) and report the exact result verbatim."
})

---

mkdir -p ~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/.claude-plugin
cat > ~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/.claude-plugin/plugin.json <<'PLUGINJSON'
{
  "name": "jdtls-lsp",
  "displayName": "Eclipse JDT.LS (Java LSP)",
  "description": "Java language server (Eclipse JDT.LS) for Claude Code, providing code intelligence and refactoring.",
  "author": {
    "name": "Anthropic",
    "email": "[email protected]"
  }
}
PLUGINJSON

---

{
  "enabledPlugins": { "jdtls-lsp@claude-plugins-official": true },
  "subagentPlugins": ["jdtls-lsp@claude-plugins-official"]
}
RAW_BUFFERClick to expand / collapse

[🤖 AI Generated]

Summary

The LSP built-in tool (activated by jdtls-lsp@claude-plugins-official) is not available to spawned subagents — neither in-process (harness-mode) subagents nor tmux team members — even when the plugin is enabled globally in ~/.claude/settings.json.

MCP-server–backed tools (e.g., mcp__glean_default__*, mcp__plugin_context-mode_context-mode__*) propagate correctly to both subagent types. Only enabledPlugins-only built-in tools are affected.

Environment

  • Claude Code version: claude-code_2-1-142_harness (from AI_AGENT env var)
  • Platform: macOS 25.4.0
  • Execution context: SDK harness (worktree session)
  • Affected subagent backends: in-process and tmux

Root cause

jdtls-lsp@claude-plugins-official is a bare-marker plugin — its cache directory (~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/) contains only LICENSE and README.md. There is no .claude-plugin/plugin.json, no .mcp.json, no tool declarations. The LSP tool is a built-in Claude Code feature gated solely on "jdtls-lsp@claude-plugins-official": true in enabledPlugins settings.

The harness builds the --plugin-dir list used when constructing subagent tool environments from plugin cache dirs that have recognized manifest files (.claude-plugin/plugin.json, .mcp.json, .cursor-plugin/plugin.json). Since jdtls-lsp has none of these, it never appears in --plugin-dir. Subagent tool environments are built from --plugin-dir-derived MCP server connections — they do not re-read enabledPlugins to activate built-in tools.

The parent session sees LSP because it reads enabledPlugins at startup and activates the built-in tool directly.
Subagents do not because their tool sets are constructed from --plugin-dir entries only.

jdtls-lsp also does not appear in installed_plugins.json — it is a bare built-in that bypasses the normal install-tracking flow entirely.

Reproduction steps

Prerequisites:

  1. Install jdtls-lsp@claude-plugins-official plugin
  2. Set "jdtls-lsp@claude-plugins-official": true in ~/.claude/settings.json (user-global) and project settings.local.json
  3. Confirm the parent session sees LSP: ToolSearch(query="select:LSP") → returns full LSP schema ✅

Probe A (non-team, in-process subagent):

Agent({
  subagent_type: "general-purpose",
  prompt: "Call ToolSearch(query='select:LSP', max_results=1) and report the exact result verbatim."
})

Expected: full LSP tool schema
Actual: No matching deferred tools found

Probe B (team-context, in-process subagent):

TeamCreate({ name: "lsp-probe" })
Agent({
  subagent_type: "general-purpose",
  team_name: "lsp-probe",
  name: "probe",
  run_in_background: true,
  prompt: "Call ToolSearch(query='select:LSP', max_results=1) and report the exact result verbatim."
})

Expected: full LSP tool schema
Actual: No matching deferred tools found

Both probes confirmed across 6+ spawn attempts in multiple sessions (2026-05-20 and 2026-05-21), covering: fresh teams, varied spawn order, different agent types (general-purpose, java-lsp-worker), tools: frontmatter present/absent, run_in_background true/false.

Configurations exhausted

ProbeChange triedResult
Global enabledPlugins: trueSet in ~/.claude/settings.jsonParent ✅, subagents ❌
Fresh TeamCreate post-enablementCreated team after global enablement
Spawn order variationEnable first, then TeamCreate; vs TeamCreate then enable
Non-team probe (no team context)Omit team_name entirely
tools: ["LSP"] frontmatterAgent allowlist❌ (allowlist, not a grant)
Agent tool schema inspectionCheck for undocumented extraTools/plugins paramsNone found
claude plugin enable --scope=subagentCheck for propagation scope flagFlag does not exist
Team config editing~/.claude/teams/<n>/config.json has no tools/plugins fieldNo workaround path

User-accessible workaround attempt (Fix 4 — validation pending)

Other plugins that appear in --plugin-dir (skill-creator, superpowers) all have .claude-plugin/plugin.json. Creating one for jdtls-lsp may cause the harness to include it in --plugin-dir, which in turn may propagate the built-in LSP tool to subagents.

mkdir -p ~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/.claude-plugin
cat > ~/.claude/plugins/cache/claude-plugins-official/jdtls-lsp/1.0.0/.claude-plugin/plugin.json <<'PLUGINJSON'
{
  "name": "jdtls-lsp",
  "displayName": "Eclipse JDT.LS (Java LSP)",
  "description": "Java language server (Eclipse JDT.LS) for Claude Code, providing code intelligence and refactoring.",
  "author": {
    "name": "Anthropic",
    "email": "[email protected]"
  }
}
PLUGINJSON

After creating the file, open a new Claude Code session (the change does not affect the already-running session). Then spawn a subagent and check ToolSearch(query="select:LSP").

Status: file created; fresh-session validation in progress. Will update this issue with results.

Caveat: this file may be overwritten by claude plugin update. It also does not fix the tmux team-member case (separate process, started without --plugin-dir).

Proposed platform fixes

Fix 1 (preferred): When the harness constructs an in-process subagent's tool environment, also read enabledPlugins from settings and activate any built-in tools gated on those plugins — the same logic the parent process runs at startup.

Fix 2: When spawning tmux team members, include --plugin-dir (or an equivalent flag) for every plugin in enabledPlugins, even those with no MCP server files. This lets the spawned process activate built-in tools from enabledPlugins.

Fix 3: Add a subagentPlugins / propagatePlugins settings key that explicitly lists plugins to force into subagent environments:

{
  "enabledPlugins": { "jdtls-lsp@claude-plugins-official": true },
  "subagentPlugins": ["jdtls-lsp@claude-plugins-official"]
}

Fix 4 (plugin-side): Ship jdtls-lsp with a .claude-plugin/plugin.json so the standard --plugin-dir propagation path carries it to subagents automatically (see workaround above).

Additional notes

  • The asymmetry (MCP-server tools propagate, built-in plugin tools don't) is the clearest signal this is a harness propagation gap, not a misconfiguration.
  • --bare mode explicitly skips LSP — but harness-mode subagents are not using --bare. The gap exists despite --setting-sources=user,project,local being passed.
  • jdtls-lsp is absent from installed_plugins.json and plugin-catalog-cache.json — it is managed separately from all other plugins, which may be contributing to it falling through the propagation path.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Bug: LSP tool (jdtls-lsp plugin) not propagated to spawned subagents