LSP plugin: ${user_config.*} in initializationOptions kills connection before initialize is sent
Summary
When a Claude Code LSP plugin's .lsp.json uses ${user_config.*} template references in the initializationOptions field, the LSP server starts but never receives the initialize message. The server exits on stdin EOF before any LSP handshake occurs.
The same template references work correctly in the env section.
Reproduction
.lsp.json
{
"my-server": {
"command": "node",
"args": ["server.cjs", "--stdio"],
"initializationOptions": {
"boltUri": "${user_config.boltUri}",
"database": "${user_config.database}",
"reader": {
"username": "${user_config.username}",
"password": "${user_config.password}"
}
},
"extensionToLanguage": { ".java": "java" }
}
}
plugin.json userConfig
{
"userConfig": {
"boltUri": { "type": "string", "title": "Bolt URI", "description": "..." },
"username": { "type": "string", "title": "Username", "description": "..." },
"password": { "type": "string", "title": "Password", "description": "..." }
}
}
settings.json (user config stored after plugin install)
{
"pluginConfigs": {
"my-server@skills-dir": {
"options": {
"boltUri": "bolt://localhost:7687",
"username": "neo4j",
"password": "password"
}
}
}
}
Observed behavior
Server log shows only:
server start {"cwd": "..."}
The server then exits (stdin reaches EOF). No initialize message is ever received.
Expected behavior
Claude Code should send the LSP initialize request after spawning the server, with initializationOptions containing the substituted user config values.
Evidence
Verified with SIFTMAP_LOG_FILE instrumentation on the server:
- Without
initializationOptions: log showsserver start→initialize→graph connectivity OK— LSP tool becomes active - With
initializationOptionscontaining${user_config.*}: log shows onlyserver start— server receives nothing, exits
The same template references in the env section work correctly (verified: SIFTMAP_BOLT_URI env var is set and received by the server process).
Workaround
Move credentials from initializationOptions to the env section and read them from environment variables in the server process:
{
"my-server": {
"command": "node",
"args": ["server.cjs", "--stdio"],
"env": {
"MY_BOLT_URI": "${user_config.boltUri}",
"MY_USERNAME": "${user_config.username}",
"MY_PASSWORD": "${user_config.password}"
},
"extensionToLanguage": { ".java": "java" }
}
}
Environment
- Claude Code version: 2.1.195
- Plugin installed via: skills-dir symlink (
~/.claude/skills/my-server) - macOS 25.3.0 / Apple Terminal
- LSP server: Node.js stdio process using
vscode-languageserver
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗