LSP plugin: ${user_config.*} in initializationOptions kills connection before initialize is sent

Resolved 💬 1 comment Opened Jun 29, 2026 by twilliams-sift Closed Jun 29, 2026

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 shows server startinitializegraph connectivity OK — LSP tool becomes active
  • With initializationOptions containing ${user_config.*}: log shows only server 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

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗