Skip to content

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.

Anode loads LSP server config from these files in this order:

Load orderPathScope
1~/.config/anode/lsp.jsonUser
2.lsp.jsonProject root
3.anode/lsp.jsonProject 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.

Anode auto-detects these servers from your PATH:

ServerLanguage
goplsGo
typescript-language-serverTypeScript/JavaScript
pyright-langserverPython
rust-analyzerRust

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.

anode lsp list
anode lsp doctor

lsp 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..

{
"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" }
}
}
}
FieldTypeDefaultDescription
commandstring-Server executable (required)
argsstring[][]Command-line arguments
envmap{}Environment variables
cwdstringworkspace rootWorking directory
extensionsmap{}File extension to language ID mapping
initializationOptionsobject{}LSP initialization options
settingsobject{}Server settings (workspace/configuration)
startupTimeoutint (ms)10000Max time to wait for server startup
shutdownTimeoutint (ms)5000Max time to wait for graceful shutdown
restartOnCrashboolfalseAuto-restart if server crashes
maxRestartsint3Maximum restart attempts
disabledboolfalseDisable 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.

The lsp tool exposes these operations:

OperationDescriptionRequires position?
goToDefinitionJump to where a symbol is definedYes
findReferencesFind all usages of a symbolYes
hoverGet type/doc info for a symbolYes
documentSymbolList all symbols in a fileNo (path only)
workspaceSymbolSearch symbols across the workspaceNo (query only)
goToImplementationFind interface implementationsYes
diagnosticsGet errors/warnings for a fileNo (path only)
prepareCallHierarchyGet call hierarchy item at positionYes
incomingCallsFind callers of a functionYes
outgoingCallsFind callees from a functionYes
ParameterTypeRequiredDescription
operationstringYesOne of the operations above
pathstringDependsFile path (relative to workspace)
lineintDepends0-indexed line number
characterintDepends0-indexed column number
querystringFor workspaceSymbolSearch query
includeDeclarationboolNoInclude the declaration in findReferences
limitintNoMax results to return

Position-dependent operations require path, line, and character. workspaceSymbol only queries servers that are already running.

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"
}
}

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.

  • Lazy startup. Servers start on first use. Opening a Go file triggers gopls; opening a TypeScript file triggers typescript-language-server.
  • Graceful shutdown. Servers receive a shutdown request when the session ends.
  • Restart fields. restartOnCrash and maxRestarts are parsed config fields, but the current manager does not restart crashed servers automatically.

Anode communicates with language servers over JSON-RPC 2.0 via stdio. Messages use Content-Length framing per the LSP specification.