Support multiple LSP servers per language in plugin system

Resolved 💬 6 comments Opened Mar 10, 2026 by YouJianFengXue Closed May 30, 2026

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

  1. Install two LSP plugins that both register for Python:
  • basedpyright-lsp (type checking) — extensionToLanguage: {".py": "python"}
  • ruff-lsp (linting/formatting) — extensionToLanguage: {".py": "python"}
  1. Enable both in settings.json
  2. Open a .py file
  3. 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 server works 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

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗