LSP: .lsp.json `settings` never reach the language server (workspace/configuration handler returns null)
Summary
A plugin's .lsp.json settings field never reaches the language server, so server-side configuration (e.g. intelephense's environment.phpVersion) is silently ignored and the server falls back to its built-in defaults.
The LSP integration itself works (document symbols, hover, references, and diagnostics all function), but there appears to be no working channel to deliver per-server configuration.
Environment
- Claude Code: 2.1.186 (Linux / WSL2)
- Plugin:
php-lsp@claude-plugins-officialwith a manually-added.lsp.json(the shipped plugin omits it — see anthropics/claude-plugins-official#444) - Language server:
intelephense1.18.5
.lsp.json
{
"php": {
"command": "intelephense",
"args": ["--stdio"],
"extensionToLanguage": { ".php": "php", ".phtml": "php", ".ctp": "php" },
"settings": {
"intelephense": {
"environment": { "phpVersion": "7.2.34" }
}
}
}
}
Expected
intelephense analyzes code targeting PHP 7.2.34.
Actual
intelephense analyzes targeting its default PHP 8.5. Opening a .php file containing $str{0} (curly-brace string offset — valid in 7.2, removed in 8.0) yields:
Array or string offset access with curly braces deprecated in PHP 7.4. Targeting PHP 8.5. [P1034] (intelephense)
The Targeting PHP 8.5 text confirms the phpVersion setting from .lsp.json was never applied.
Root cause (from inspecting the 2.1.186 binary)
intelephense receives environment.phpVersion only through LSP configuration (it does not read it from initializationOptions — only storagePath/globalStoragePath/clearCache/licenceKey are read there). Both LSP configuration channels appear broken:
- Pull (
workspace/configuration) — the client advertises the capability as disabled:
```
workspace:{configuration:!1, workspaceFolders:!1}
null
…yet still registers a handler that returns for every requested item:`
jsLSP: Received workspace/configuration request from ${S}
C.onRequest("workspace/configuration", (k) => (
T(),`
k.items.map(() => null)
))
null` for every section.
So any server that pulls config gets
- Push (
workspace/didChangeConfiguration) — the.lsp.jsonschema documentssettingsas "Settings passed to the server via workspace/didChangeConfiguration", but the value never takes effect (intelephense still targets its default version after init and after re-parsing the document).
Net effect: the settings field in .lsp.json is effectively a no-op for any server that needs configuration to function correctly.
Repro
- Install
php-lsp@claude-plugins-officialand add the.lsp.jsonabove. - Restart Claude Code (LSP/plugin config is read at process startup).
- Open a
.phpfile containing:
``php``
<?php
$str = 'hello';
echo $str{0};
- Observe the diagnostic reports
Targeting PHP 8.5instead of honoringphpVersion: "7.2.34".
Suggestion
Either implement the workspace/configuration pull handler to return the matching section from .lsp.json settings (e.g. return settings["intelephense"] for section: "intelephense"), or ensure the didChangeConfiguration push delivers settings in the shape servers expect. As-is, server configuration via .lsp.json settings cannot be relied upon.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗