Language Server Protocol plugin
The LSP plugin gives coding agents compiler diagnostics, symbol definitions, references, and approved renames or formatting. Install the plugin and a language server separately; Jazz does not bundle a language server. Servers must support LSP 3.17 over stdio.
Install the published plugin through the normal plugin lifecycle. No repository clone or local build is needed; the published artifact includes its diff renderer:
jazz plugin add com.jazz.plugins.lsp
jazz plugin inspect com.jazz.plugins.lsp
jazz plugin trust com.jazz.plugins.lsp
jazz plugin enable com.jazz.plugins.lsp --agent default
Replace default with your agent name or ID, or omit --agent to enable it for every agent.
Install your language-server executable separately and configure its command in ~/.jazz/lsp.json:
{
"servers": [
{
"id": "typescript",
"command": "typescript-language-server",
"args": ["--stdio"],
"extensions": {
".ts": "typescript",
".tsx": "typescriptreact"
},
"rootMarkers": ["tsconfig.json", "package.json"]
},
{
"id": "javascript",
"command": "typescript-language-server",
"args": ["--stdio"],
"extensions": {
".js": "javascript",
".jsx": "javascriptreact"
},
"rootMarkers": ["jsconfig.json", "package.json"]
}
]
}
For HTML and CSS, use vscode-langservers-extracted (npm install --global vscode-langservers-extracted) with command: "vscode-html-language-server" for
.html/.htm and command: "vscode-css-language-server" for .css, both with
args: ["--stdio"]. The HTML server also reports diagnostics for CSS inside inline
<style> blocks. Both use the LSP 3.17 pull model; the plugin queries
textDocument/diagnostic directly. Avoid the older
vscode-html-languageserver-bin / vscode-css-languageserver-bin packages: their
pinned vscode-jsonrpc crashes at startup (messageReader.onClose is not a function). See the plugin README for a complete
lsp.json example.
Install typescript-language-server and a compatible typescript package containing
tsserver.js before using this example. To configure another
language, add an entry with its executable, argument vector, an extensions-to-language-ID
map, and project-root markers. Each extension is bound to exactly one language ID because the
language decides how the server parses the file: .tsx and .jsx must open as the React
dialects (typescriptreact, javascriptreact), never as plain typescript or javascript. A
legacy top-level languageId is rejected at load time with a message naming the replacement.
The first entry whose extensions name a file’s extension wins. The
plugin walks upward from the current directory to identify configured project roots and starts
their servers before the first model request. It also starts a matching server when Jazz later
touches a supported file outside those roots. If no marker exists, it uses the agent’s current
directory. JAZZ_LSP_CONFIG can point to another JSON file. A missing or invalid config is
reported to the agent.
The plugin reads source files from disk and sends didOpen and didChange as Jazz works with them.
It checks tracked files again before each model request, including after external edits. It keeps
diagnostics bounded and relevant to those files; it does not pour whole-workspace diagnostics into
every turn. A failed server start is retried after a short delay rather than on every model request;
an unavailable server does not stop the coding run. The model cannot choose the
executable or its arguments.
The tools use 1-based line and UTF-16 character coordinates. code_actions lists available
actions for a range. apply_code_action selects one by its exact title, with a zero-based index
when titles repeat, and resolves lazy edits when the server supports it. Actions without an edit
are rejected. rename_symbol, apply_code_action, and format_document turn the returned
WorkspaceEdit into a multi-file diff for Jazz’s normal approval flow. Jazz persists the prepared
edit if approval is parked. At execution, the plugin locks every target and checks its complete
content digest before replacing files; a changed file produces a stale-edit error and writes
nothing. It also rejects a server response if the source file changed while the server was
preparing the edit. Resource operations such as create, delete, and move are rejected explicitly. LSP
servers’ unsolicited workspace/applyEdit requests are refused.
Semantic query tools are declared read-only. Rename, code action application, and formatting are
declared high-risk and use Jazz’s approval gate. The configured server command is part of the
operator’s plugin setup and trust decision, not a model-authored shell command. The operator must
trust that executable, just as with any plugin that runs local code. The server receives source
contents from files Jazz reads or changes during the agent’s run, as well as files the agent
explicitly queries through an LSP tool. Its stdout is untrusted protocol data;
code action commands are never executed. The plugin performs no network egress itself, but a
configured server may have its own network behavior. Review the server before enabling the
plugin on a remote or unattended surface.
The current edit path validates all files before writing and uses sibling temporary files plus atomic per-file renames. A multi-file edit is not one filesystem transaction: an I/O failure during replacement can leave a partial set of files changed. External programs that ignore Jazz’s edit locks can also race after validation.