[BUG] LSP plugin system not connecting to language servers - always returns "No LSP server available"
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:
- Plugin typescript-lsp@claude-plugins-official installed at user scope
- Plugin enabled in ~/.claude/settings.json
- 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
- 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
- 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.)
- 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
- Install plugin:
claude plugins install typescript-lsp@claude-plugins-official - Verify ~/.claude/settings.json has
"typescript-lsp@claude-plugins-official": true - Restart Claude Code
- Use LSP tool on any .ts file
- 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
- Install the typescript-lsp plugin:
``bash``
claude plugins install typescript-lsp@claude-plugins-official
- Verify ~/.claude/settings.json contains:
``json``
{
"enabledPlugins": {
"typescript-lsp@claude-plugins-official": true
}
}
- Restart Claude Code
- Open any TypeScript project
- Use the LSP tool on any .ts file (e.g., hover, goToDefinition)
- 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_
22 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
got the same issue version 2.0.76
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
The Problem
When plugin hooks try to use
${CLAUDE_PLUGIN_ROOT}, the path gets corrupted:Expected:
Actual (error message):
Notice the path is completely mangled - backslashes removed, colons stripped, etc.
Affected plugins
pyright@boostvolt-lspsvtsls@boostvolt-lsps${CLAUDE_PLUGIN_ROOT}in hooks.jsonWorkaround
I modified the hooks.json files to use inline commands instead of external scripts:
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.Confirming still broken on v2.0.76 (Linux).
Setup verified correct:
pyright-lsp,typescript-lsp,gopls-lsp,rust-analyzer-lsp,lua-lsp.lsp.jsonfiles present with correct structuresettings.jsonResult:
No LSP server available for file type: .py/.ts/.goSame race condition - LSP Manager completes before plugins load.
I have the same problem with typescript lsp. Using the mac osx system.
I'm very confused, the plugin seems to be just:
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.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:
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:
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 🤷♂️
Same here, seems to be related to the "official" anthropic plugin marketplace only having placeholders instead of the plugin code
Same in win11 claude code 2.0.76
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.
Same issue in v2.1.6
vtsls installed, plugin installed and enabled, no LSP tools available.
2.1.2fixed it, but2.1.7broke 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?
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.
I was thinking claude code will replace programmers
You're not gonna believe it, Claude 2.1.8 worked, then this morning 2.1.9 broke again.
this is quite funny tbh
Just to prove I'm not crazy I've installed two versions on my system.
With
2.1.9:With
2.1.2:Same config in both 🤷♂️
Did it ever worked? Installing the plugin is not enough, I guess.
I use the native installer, and then discovered the typescript-lsp plugin, but it never worked.
4 Restart Claude Code. The CLI won't pick up the new
PATHotherwise.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.
still reproducing in v2.1.97
This https://github.com/anthropics/claude-plugins-official/pull/378 fixed it for me, LSP plugins now working.
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,
publishDiagnosticson a parseerror, hover, and go-to-definition are verified on
pwsh7 and Windows PowerShell 5.1,on Windows and (as of this release) Linux CI.
A plugin-provided
.lsp.jsondoes not register on 2.1.167 -- in any configuration Icould test, including the installed-plugin-cache path. Every
LSPtool call below wasconfirmed real via
--output-format stream-json(a singleLSPtool_use+ itstool_result, not a prompt echo).--plugin-dirsession-load, literal.lsp.json(clean top-level map; literalpwsh+ absolute script path + literalPSES_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
.lsp.json(the previously-untested path). A throwawayplugin whose source ships the same clean literal
.lsp.jsonwas installed throughthe real
/pluginflow (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 exactreported-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
.lsp.json)is inert the same way:
goToDefinitionon a.ps1returnsNo LSP server available for file type: .ps1.So the inertness of a plugin
.lsp.jsonfile is not a reload-vs-restart artifact,not a template-variable artifact, and not a
--plugin-dir-vs-installed-cacheartifact. On 2.1.167 a
.lsp.jsonfile 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
lspServersblock living solely inmarketplace.jsonis dropped and the installedplugin ships with nothing but
README.md(0 servers). The proposed fix,PR #378 (add a real
.lsp.jsonto 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.jsonphysically in the installed plugin's cache and registration still fails --which points past the packaging gap toward the registration path itself (the
LspServerManagerinit-ordering / "0 servers" symptom in #15168 / #15148).Open sub-question (not tested here): whether
${CLAUDE_PLUGIN_ROOT}/${user_config.*}template variables expand inside.lsp.jsoncommand/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.jsonfile in an installed plugin'scache 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.jsonpath registered, that wouldlocalize the regression.
Environment
registration inert across the span
plugin.jsonlspServersdocs/lsp.json.templatev4.6.0, PSScriptAnalyzer1.25.0; Windows 11--output-format stream-json
; builtinLSPtool invoked;tool_use/tool_result
claude plugin marketplace addread from the event stream (not a prompt echo). Installed-cache case reached via
+claude plugin install(the installer populated theclaude -pcache), then a fresh
with no--plugin-dir`.I've stopped using claude code some months ago, shitty software and shitty model - my life has been easier since