[BUG] LSP plugin system not connecting to language servers - always returns "No LSP server available"

Open 💬 22 comments Opened Dec 23, 2025 by gustavo-cerqueira

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Environment

  • Claude Code version: 2.0.76
  • OS: WSL2 Ubuntu 22.04 (Linux 5.15.146.1-microsoft-standard-WSL2)
  • Node.js: 22.14.0
  • typescript-language-server: 5.1.3 (globally installed)
  • TypeScript: 5.9.3 (bundled with tsserver)

Problem

The LSP tool always returns "No LSP server available for file type: .ts" despite:

  1. Plugin typescript-lsp@claude-plugins-official installed at user scope
  2. Plugin enabled in ~/.claude/settings.json
  3. typescript-language-server binary correctly installed and working

Configuration Files

~/.claude/settings.json:

{
  "enabledPlugins": {
    "typescript-lsp@claude-plugins-official": true
  }
}

~/.claude/plugins/installed_plugins.json:

{
  "version": 2,
  "plugins": {
    "typescript-lsp@claude-plugins-official": [
      {
        "scope": "user",
        "installPath": "/home/gustavo/.claude/plugins/cache/claude-plugins-official/typescript-lsp/1.0.0",
        "version": "1.0.0",
        "installedAt": "2025-12-23T14:56:53.476Z",
        "lastUpdated": "2025-12-23T14:56:53.476Z",
        "isLocal": true
      }
    ]
  }
}

Diagnostic Tests

  1. Binary exists and responds:
$ which typescript-language-server
/home/gustavo/.nvm/versions/node/v22.14.0/bin/typescript-language-server

$ typescript-language-server --version
5.1.3
  1. LSP protocol works when tested directly via Node.js:
const {spawn} = require('child_process');
const msg = JSON.stringify({jsonrpc:'2.0',id:1,method:'initialize',params:{processId:null,rootUri:'file:///tmp',capabilities:{}}});
const header = 'Content-Length: ' + Buffer.byteLength(msg) + '\r\n\r\n';
const p = spawn('typescript-language-server', ['--stdio']);
p.stdout.on('data', d => console.log(d.toString()));
p.stdin.write(header + msg);

Result: Returns proper LSP response with capabilities (completions, code actions, etc.)

  1. Claude Code LSP tool fails:
LSP operation: hover
File: projects/backend2/apps/main/src/app.controller.ts
Result: "No LSP server available for file type: .ts"

Steps to Reproduce

  1. Install plugin: claude plugins install typescript-lsp@claude-plugins-official
  2. Verify ~/.claude/settings.json has "typescript-lsp@claude-plugins-official": true
  3. Restart Claude Code
  4. Use LSP tool on any .ts file
  5. Observe "No LSP server available for file type: .ts"

Expected Behavior

LSP operations (hover, goToDefinition, findReferences, etc.) should work on TypeScript files.

Actual Behavior

LSP tool returns "No LSP server available for file type: .ts" for all operations.

Additional Context

  • Tried installing at both project scope and user scope - same result
  • Cleared plugin cache and reinstalled - same result
  • The marketplace.json contains correct lspServers configuration
  • Also tested pyright-lsp plugin - same issue ("No LSP server available for file type: .py")

What Should Happen?

LSP operations (hover, goToDefinition, findReferences, etc.) should work on TypeScript files when the typescript-lsp plugin is installed and enabled. The LSP tool should connect to the typescript-language-server and return type information, hover documentation, and code navigation results.

Error Messages/Logs

LSP operation: hover
File: projects/backend2/apps/main/src/app.controller.ts
Result: "No LSP server available for file type: .ts"

Steps to Reproduce

  1. Install the typescript-lsp plugin:

``bash
claude plugins install typescript-lsp@claude-plugins-official
``

  1. Verify ~/.claude/settings.json contains:

``json
{
"enabledPlugins": {
"typescript-lsp@claude-plugins-official": true
}
}
``

  1. Restart Claude Code
  2. Open any TypeScript project
  3. Use the LSP tool on any .ts file (e.g., hover, goToDefinition)
  4. Observe the error: "No LSP server available for file type: .ts"

Note: The typescript-language-server binary is correctly installed and works when tested directly via Node.js using the LSP protocol.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.0.76

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

_No response_

View original on GitHub ↗

22 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/14803
  2. https://github.com/anthropics/claude-code/issues/15148
  3. https://github.com/anthropics/claude-code/issues/13952

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

ytzhakov · 6 months ago

got the same issue version 2.0.76

mmereu · 6 months ago

Additional Windows-specific issue: Hook path corruption

On Windows, there's an additional bug where the ${CLAUDE_PLUGIN_ROOT} variable is incorrectly expanded in plugin hooks.

Environment

  • Claude Code: 2.0.76
  • OS: Windows 11
  • Shell: Git Bash (MINGW64)

The Problem

When plugin hooks try to use ${CLAUDE_PLUGIN_ROOT}, the path gets corrupted:

Expected:

C:\Users\marco.mereu\.claude\plugins\cache\boostvolt-lsps\pyright\1.0.0/hooks/check-pyright.sh

Actual (error message):

Plugin hook error: /bin/bash: C:Usersmarco.mereu.claudepluginscacheboostvolt-lspspyright1.0.0/hooks/check-pyright.sh: No such file or directory

Notice the path is completely mangled - backslashes removed, colons stripped, etc.

Affected plugins

  • pyright@boostvolt-lsps
  • vtsls@boostvolt-lsps
  • Any plugin using ${CLAUDE_PLUGIN_ROOT} in hooks.json

Workaround

I modified the hooks.json files to use inline commands instead of external scripts:

{
  "hooks": {
    "SessionStart": [{
      "hooks": [{
        "type": "command",
        "command": "command -v pyright-langserver >/dev/null 2>&1 || npm install -g pyright",
        "timeout": 60
      }]
    }]
  }
}

This avoids the path expansion issue entirely.

Root cause

The ${CLAUDE_PLUGIN_ROOT} environment variable seems to be passed through a shell that strips Windows path separators before bash can interpret them.

Piotr1215 · 6 months ago

Confirming still broken on v2.0.76 (Linux).

Setup verified correct:

  • Plugins installed: pyright-lsp, typescript-lsp, gopls-lsp, rust-analyzer-lsp, lua-lsp
  • .lsp.json files present with correct structure
  • Binaries in PATH and functional
  • Plugins enabled in settings.json

Result: No LSP server available for file type: .py/.ts/.go

Same race condition - LSP Manager completes before plugins load.

boldprojekte · 6 months ago

I have the same problem with typescript lsp. Using the mac osx system.

leo-petrucci · 6 months ago

I'm very confused, the plugin seems to be just:

ls ~/.claude/plugins/cache/claude-plugins-official/typescript-lsp/1.0.0/
README.md

Shouldn't it have... Code in there? How is it supposed to work?

Other plugins in the plugins repo have hookes, agents, commands and plugin.json. None of the LSP ones do though.

leo-petrucci · 6 months ago

I've spend the better part of two hours debugging this and I'm now fully convinced the LSP feature just does not work on Claude Code's side.

I've:

  • Tried the official LSP (which doesn't have any config)
  • The vtsls plugin
  • I even wrote my own with the alternative inline configuration described here

None of them work.

I debugged with Claude and here's what we found:

--------

Debug log evidence shows LSP manager initializes before plugins load:

2026-01-06T12:37:31.337Z [DEBUG] [LSP MANAGER] initializeLspServerManager() called
2026-01-06T12:37:31.339Z [DEBUG] LSP notification handlers registered successfully for all 0 server(s)
2026-01-06T12:37:31.340Z [DEBUG] Loading plugin typescript-lsp from source: "./typescript-lsp"
2026-01-06T12:37:31.342Z [DEBUG] Loading plugin vtsls from source: "./vtsls"
2026-01-06T12:37:31.342Z [DEBUG] Found 2 plugins (2 enabled, 0 disabled)

Key Issue: LSP manager registers 0 server(s) before plugins containing LSP configurations are loaded. After plugin loading completes, there's no re-scan for LSP servers.

To reproduce the above logs:

  1. install an LSP plugin
  2. Ask Claude to verify for errors using an LSP
  3. After it fails run grep -A 10 -B 5 "LSP.*manager\|lsp.*server\|typescript.*server" ~/.claude/debug/latest

--------

So I'm either losing my mind or the feature is just not done/working 🤷‍♂️

jifbrodeur · 6 months ago

Same here, seems to be related to the "official" anthropic plugin marketplace only having placeholders instead of the plugin code

Mzaxd · 6 months ago

Same in win11 claude code 2.0.76

leo-petrucci · 6 months ago

I've now seen one of my coworkers managing to get it working with the official plugin. He hasn't done anything special, but it indeed does work.

So no idea, we even have the same machine and the same setup so I can't imagine it would be a hardware compatibility issue of some sort.

evgenyfadeev · 6 months ago

Same issue in v2.1.6

vtsls installed, plugin installed and enabled, no LSP tools available.

leo-petrucci · 6 months ago

2.1.2 fixed it, but 2.1.7 broke it again.

No changes on my side aside from the update.

Can we get an answer from Anthropic? What's going on here? Should we switch to OpenCode and Codex?

Hellisotherpeople · 6 months ago

This is an example of why you should actually write some of your code by hand and not expect that you can simply "claude code" claude code.

FrancescoSaverioZuppichini · 6 months ago

I was thinking claude code will replace programmers

leo-petrucci · 6 months ago
2.1.2 fixed it, but 2.1.7 broke it again. No changes on my side aside from the update. Can we get an answer from Anthropic? What's going on here? Should we switch to OpenCode and Codex?

You're not gonna believe it, Claude 2.1.8 worked, then this morning 2.1.9 broke again.

FrancescoSaverioZuppichini · 6 months ago
> 2.1.2 fixed it, but 2.1.7 broke it again. > No changes on my side aside from the update. > Can we get an answer from Anthropic? What's going on here? Should we switch to OpenCode and Codex? You're not gonna believe it, Claude 2.1.8 worked, then this morning 2.1.9 broke again.

this is quite funny tbh

leo-petrucci · 6 months ago

Just to prove I'm not crazy I've installed two versions on my system.

With 2.1.9:

╭─── Claude Code v2.1.9 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│                                  │ Recent activity                                                                                              │
│           Welcome back!          │ 10m ago  Can you run an LSP check on  entrypoints/dashboard/client/src/pages/Home/components/SiteViewSwitch… │
│                                  │ 10m ago  can you remove the console log from entrypoints/dashboard/client/src/pages/Home/components/SiteVie… │
│                                  │ 46m ago  can you remove the console log from entrypoints/dashboard/client/src/pages/Home/components/SiteVie… │
│              ▐▛███▜▌             │ /resume for more                                                                                             │
│             ▝▜█████▛▘            │ ──────────────────────────────────────────────────────────────────────────────────────────────────────────── │
│               ▘▘ ▝▝              │ What's new                                                                                                   │
│                                  │ Added `auto:N` syntax for configuring the MCP tool search auto-enable threshold, where N is the context win… │
│                                  │ Added `plansDirectory` setting to customize where plan files are stored                                      │
│   Sonnet 4 · API Usage Billing   │ Added external editor support (Ctrl+G) in AskUserQuestion "Other" input field                                │
│            ~/project            │ /release-notes for more                                                                                      │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

  /model to try Opus 4.5. Note: you may need to request access from your cloud provider

❯ Can you run an LSP check on  entrypoints/dashboard/client/src/pages/Home/components/SiteViewSwitcher/GridViewSiteList.tsx

⏺ I'll run a TypeScript LSP check on the GridViewSiteList.tsx file to identify any type errors or issues.

⏺ Bash(npx tsc --noEmit entrypoints/dashboard/client/src/pages/Home/components/SiteViewSwitcher/GridViewSiteList.tsx)
  ⎿  Interrupted · What should Claude do instead?

With 2.1.2:


 ▐▛███▜▌   Claude Code v2.1.2
▝▜█████▛▘  Sonnet 4 · API Usage Billing
  ▘▘ ▝▝    ~/project

  /model to try Opus 4.5. Note: you may need to request access from your cloud provider

❯ Can you run an LSP check on  entrypoints/dashboard/client/src/pages/Home/components/SiteViewSwitcher/GridViewSiteList.tsx

⏺ I'll run an LSP check on that file to analyze its structure and potential issues.

⏺ LSP(operation: "documentSymbol", file: "entrypoints/dashboard/client/src/pages/Home/components/SiteViewSwitcher/GridViewSiteList.tsx")
  ⎿  Found 55 symbols (ctrl+o to expand)

Same config in both 🤷‍♂️

nerdalytics · 4 months ago

Did it ever worked? Installing the plugin is not enough, I guess.

⏺ LSP(operation: "documentSymbol", file: "src/index.ts")                                                                                                    
  ⎿  Error performing documentSymbol: Executable not found in $PATH: "typescript-language-server"                                                           
                                                                                                                                                            
⏺ No TypeScript LSP server is configured. The typescript-language-server binary isn't installed or isn't in $PATH.                                        
                                                                                                                                                            
  You could install it with:                                                                                                                                
                                                                                                                                                            
  npm i -g typescript-language-server typescript                                                                                                            
                                                                                                                                                          
  Want me to install it, or would you rather I just read the file directly?

I use the native installer, and then discovered the typescript-lsp plugin, but it never worked.

  1. typescript-lsp looks for typescript-language-server in PATH and the only documented setup is npm i -g.
  2. To avoid the global install, create a shim that delegates to bunx:
mkdir -p .mise/shims
cat > .mise/shims/typescript-language-server << 'SHIM'
  #!/usr/bin/env bash
  exec bunx --bun typescript-language-server "$@"
SHIM
chmod +x .mise/shims/typescript-language-server
  1. Add .mise/shims to PATH via mise.local.toml:
[env]
_.path = [".mise/shims"]

[tools]
bun = "latest"

4 Restart Claude Code. The CLI won't pick up the new PATH otherwise.

The plugin has no way to configure the server command — no custom binary path, no wrapper support. If you don't want a global install, you're hacking PATH yourself.

pdebuitlear · 3 months ago

still reproducing in v2.1.97

patrikhuber · 3 months ago

This https://github.com/anthropics/claude-plugins-official/pull/378 fixed it for me, LSP plugins now working.

manderse21 · 26 days ago

A third-party datapoint from outside the official marketplace: powershell-lsp, a
PowerShell Editor Services (PSES) plugin for .ps1/.psm1/.psd1 --
https://github.com/manderse21/claude-powershell-lsp.

The server itself works. The PSES stdio handshake, publishDiagnostics on a parse
error, hover, and go-to-definition are verified on pwsh 7 and Windows PowerShell 5.1,
on Windows and (as of this release) Linux CI.

A plugin-provided .lsp.json does not register on 2.1.167 -- in any configuration I
could test, including the installed-plugin-cache path.
Every LSP tool call below was
confirmed real via --output-format stream-json (a single LSP tool_use + its
tool_result, not a prompt echo).

  1. --plugin-dir session-load, literal .lsp.json (clean top-level map; literal

pwsh + absolute script path + literal PSES_BUNDLE_PATH; no
${CLAUDE_PLUGIN_ROOT}/${user_config.*} variables; full restart, not
/reload-plugins):

``
tool_use : {"operation":"goToDefinition","filePath":"./test.ps1","line":5,"character":6}
tool_result: No LSP server available for file type: .ps1
``

  1. Installed-cache, literal .lsp.json (the previously-untested path). A throwaway

plugin whose source ships the same clean literal .lsp.json was installed through
the real /plugin flow (claude plugin marketplace add + claude plugin install),
so the installer copied the file into the cache --
~/.claude/plugins/cache/<marketplace>/<plugin>/0.0.1/.lsp.json -- reaching the exact
reported-working setup with zero hand-writes. After a full restart (a fresh
claude -p, no --plugin-dir), probing a unique extension only this plugin declared:

``
tool_use : {"operation":"goToDefinition","filePath":"./test.ps1x","line":5,"character":6}
tool_result: No LSP server available for file type: .ps1x
``

  1. The installed real plugin (its cache already carries a template-var .lsp.json)

is inert the same way: goToDefinition on a .ps1 returns
No LSP server available for file type: .ps1.

So the inertness of a plugin .lsp.json file is not a reload-vs-restart artifact,
not a template-variable artifact, and not a --plugin-dir-vs-installed-cache
artifact. On 2.1.167 a .lsp.json file shipped in a plugin does not register a server,
in any configuration I could reach.

Relationship to the packaging gap (#379). #379 documents that installing a
marketplace LSP plugin copies only the source directory into the cache, so an
lspServers block living solely in marketplace.json is dropped and the installed
plugin ships with nothing but README.md (0 servers). The proposed fix,
PR #378 (add a real
.lsp.json to each official plugin directory), was closed unmerged (2026-02-11), so
#379 is still open and unaddressed. The installed-cache re-test above puts a real
.lsp.json physically in the installed plugin's cache and registration still fails --
which points past the packaging gap toward the registration path itself (the
LspServerManager init-ordering / "0 servers" symptom in #15168 / #15148).

Open sub-question (not tested here): whether ${CLAUDE_PLUGIN_ROOT} /
${user_config.*} template variables expand inside .lsp.json command/args/env.
This testing deliberately used literal paths to isolate the registration question; the
substitution question is moot while registration is inert, but it matters the moment
registration is fixed.

Workaround in shipping use. Because native registration cannot be relied on, the
plugin delivers diagnostics through a warm, per-session PostToolUse hook (one PSES
stays hot for the session; each edit is a pipe round-trip, ~2 s, vs a ~6 s cold start).
That works today on every supported host and is independent of the registration path --
but it is a workaround for this bug, not a replacement for a fix.

On the "it works" reports. Reports of a .lsp.json file in an installed plugin's
cache working are most likely a Claude Code version difference -- this datapoint is
2.1.167 specifically; the registrar behavior may differ in other builds. If a maintainer
can name the build where the installed-cache .lsp.json path registered, that would
localize the regression.

Environment

  • Claude Code: 2.1.167 (2026-06-06) through 2.1.183 (2026-06-19); native LSP

registration inert across the span

  • Plugin: powershell-lsp (standalone repo); server declared in plugin.json lspServers
  • docs/lsp.json.template
  • PSES v4.6.0, PSScriptAnalyzer 1.25.0; Windows 11
  • Harness: `claude -p --allowedTools LSP --strict-mcp-config --mcp-config '{"mcpServers":{}}'

--output-format stream-json; builtin LSP tool invoked; tool_use/tool_result
read from the event stream (not a prompt echo). Installed-cache case reached via
claude plugin marketplace add + claude plugin install (the installer populated the
cache), then a fresh
claude -p with no --plugin-dir`.

FrancescoSaverioZuppichini · 25 days ago

I've stopped using claude code some months ago, shitty software and shitty model - my life has been easier since