Language Server Protocol
The lsp tool gives Anode code intelligence: definitions, references, hover,
symbols, diagnostics, implementations, and call hierarchy. The tool appears only
when at least one language server is configured or auto-detected on PATH.
Configuration
Section titled “Configuration”Anode loads LSP server config from these files in this order:
| Load order | Path | Scope |
|---|---|---|
| 1 | ~/.config/anode/lsp.json | User |
| 2 | .lsp.json | Project root |
| 3 | .anode/lsp.json | Project Anode-specific |
All discovered configs are merged. Later entries override earlier entries for
the same server name, so .anode/lsp.json has the highest override priority.
The format is compatible with Claude Code’s LSP configuration.
Auto-Detection
Section titled “Auto-Detection”Anode auto-detects these servers from your PATH:
| Server | Language |
|---|---|
gopls | Go |
typescript-language-server | TypeScript/JavaScript |
pyright-langserver | Python |
rust-analyzer | Rust |
If a server is on your PATH, Anode uses it without configuration. Create a config file to override defaults or add servers not in this list.
CLI Inspection
Section titled “CLI Inspection”anode lsp listanode lsp doctorlsp list shows config file status plus configured and auto-detected language
servers. lsp doctor validates LSP config discovery and parsing; successful
checks end with LSP diagnostics passed..
Example Config
Section titled “Example Config”{ "gopls": { "command": "gopls", "args": ["serve"], "extensions": { ".go": "go" }, "initializationOptions": {}, "settings": { "gopls": { "staticcheck": true } } }, "typescript-language-server": { "command": "typescript-language-server", "args": ["--stdio"], "extensions": { ".ts": "typescript", ".tsx": "typescriptreact", ".js": "javascript", ".jsx": "javascriptreact" } }, "pyright": { "command": "pyright-langserver", "args": ["--stdio"], "extensions": { ".py": "python" }, "settings": { "python": { "analysis": { "typeCheckingMode": "basic" } } } }}Anode also accepts a wrapped form:
{ "languageServers": { "gopls": { "command": "gopls", "args": ["serve"], "extensions": { ".go": "go" } } }}ServerConfig Fields
Section titled “ServerConfig Fields”| Field | Type | Default | Description |
|---|---|---|---|
command | string | - | Server executable (required) |
args | string[] | [] | Command-line arguments |
env | map | {} | Environment variables |
cwd | string | workspace root | Working directory |
extensions | map | {} | File extension to language ID mapping |
initializationOptions | object | {} | LSP initialization options |
settings | object | {} | Server settings (workspace/configuration) |
startupTimeout | int (ms) | 10000 | Max time to wait for server startup |
shutdownTimeout | int (ms) | 5000 | Max time to wait for graceful shutdown |
restartOnCrash | bool | false | Auto-restart if server crashes |
maxRestarts | int | 3 | Maximum restart attempts |
disabled | bool | false | Disable this server |
The extensions map connects file extensions to LSP language identifiers. For example, {".go": "go"} tells Anode that .go files use the go language ID.
LSP operations
Section titled “LSP operations”The lsp tool exposes these operations:
| Operation | Description | Requires position? |
|---|---|---|
goToDefinition | Jump to where a symbol is defined | Yes |
findReferences | Find all usages of a symbol | Yes |
hover | Get type/doc info for a symbol | Yes |
documentSymbol | List all symbols in a file | No (path only) |
workspaceSymbol | Search symbols across the workspace | No (query only) |
goToImplementation | Find interface implementations | Yes |
diagnostics | Get errors/warnings for a file | No (path only) |
prepareCallHierarchy | Get call hierarchy item at position | Yes |
incomingCalls | Find callers of a function | Yes |
outgoingCalls | Find callees from a function | Yes |
Tool parameters
Section titled “Tool parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
operation | string | Yes | One of the operations above |
path | string | Depends | File path (relative to workspace) |
line | int | Depends | 0-indexed line number |
character | int | Depends | 0-indexed column number |
query | string | For workspaceSymbol | Search query |
includeDeclaration | bool | No | Include the declaration in findReferences |
limit | int | No | Max results to return |
Position-dependent operations require path, line, and character.
workspaceSymbol only queries servers that are already running.
Example usage
Section titled “Example usage”The agent calls the lsp tool like any other tool:
{ "name": "lsp", "args": { "operation": "goToDefinition", "path": "internal/run/engine.go", "line": 42, "character": 15 }}{ "name": "lsp", "args": { "operation": "workspaceSymbol", "query": "RunEngine" }}Passive Diagnostics
Section titled “Passive Diagnostics”After every edit_file or create_file call, Anode automatically reports diagnostics from the relevant language server. This gives the agent immediate feedback on type errors, syntax issues, and lint warnings.
Limits:
- Max 10 diagnostics per file.
- Max 30 diagnostics total per report.
The agent sees diagnostics without explicitly calling the lsp tool.
Server Lifecycle
Section titled “Server Lifecycle”- Lazy startup. Servers start on first use. Opening a Go file triggers
gopls; opening a TypeScript file triggerstypescript-language-server. - Graceful shutdown. Servers receive a shutdown request when the session ends.
- Restart fields.
restartOnCrashandmaxRestartsare parsed config fields, but the current manager does not restart crashed servers automatically.
Transport
Section titled “Transport”Anode communicates with language servers over JSON-RPC 2.0 via stdio. Messages use Content-Length framing per the LSP specification.
Keep Going
Section titled “Keep Going”- Tools - all built-in tools including the lsp tool
- Configuration - global and project settings
- Troubleshooting - fixing LSP connection issues
- Headless Execution - use Anode in scripts and pipelines