Support multiple LSP servers per language in plugin system
Summary
The plugin system's LSP dispatcher appears to use a one-server-per-language-ID model. When two plugins register lspServers for the same language ID (e.g., .py → python), only the first-loaded server starts. The second is silently discarded — no error, no process, no diagnostics.
Reproduction
- Install two LSP plugins that both register for Python:
basedpyright-lsp(type checking) —extensionToLanguage: {".py": "python"}ruff-lsp(linting/formatting) —extensionToLanguage: {".py": "python"}
- Enable both in
settings.json - Open a
.pyfile - Check running processes:
ps aux | grep -E "ruff|basedpyright"
Expected: Both servers running (6 basedpyright + some ruff processes)
Actual: Only basedpyright runs (6 processes). ruff has 0 processes. No error message.
Evidence
ruff serverworks correctly when tested manually with a persistent stdin pipe (responds to LSP initialize with full capabilities)- TypeScript dual-LSP works (biome + typescript-lsp both run) — likely because they register partially different language IDs
<new-diagnostics>only shows type-server output ((basedpyright)for Python,(typescript)for TS), never lint-server output- This matches Kate editor's documented limitation: "Kate's LSP Client does not support multiple servers for the same language" (from ruff's own docs)
Plugin configs
basedpyright-lsp (works):
{
"lspServers": {
"basedpyright": {
"command": "basedpyright-langserver",
"args": ["--stdio"],
"extensionToLanguage": { ".py": "python", ".pyi": "python" }
}
}
}
ruff-lsp (silently fails):
{
"lspServers": {
"ruff": {
"command": "ruff",
"args": ["server"],
"extensionToLanguage": { ".py": "python", ".pyi": "python" }
}
}
}
Feature Request
Support multiple LSP servers per language, similar to:
- Helix (≥23.10):
language-servers = ["ruff", "basedpyright"]array syntax - Neovim: Multiple servers via mason.nvim configuration
This would enable the standard dual-LSP pattern: one server for type intelligence (basedpyright/typescript-lsp), another for linting/formatting (ruff/biome).
Workaround
Currently using a PostToolUse hook (auto-formatter.py) that runs ruff format + ruff check after every file edit. This captures ruff's value but lacks live diagnostics.
Environment
- Claude Code: latest
- ruff: 0.14.13
- basedpyright: latest
- macOS Darwin 25.3.0
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗