LSP client library for providing code intelligence to the LLM agent. Manages LSP server lifecycles and communicates over JSON-RPC/stdio, reusing the user's Neovim LSP configuration so no manual server setup is required.
tcode (startup)
|
+-- extract_config_from_nvim() // headless nvim discovers installed servers
|
+-- LspManager::new(config, root_dir)
|
+-- LspServer::start() // spawns server process, performs initialize handshake
|
+-- LspTransport // JSON-RPC framing over stdin/stdout
tcode creates an LspManager at startup and passes it (via Arc) to the tools crate, which exposes it as the LSP tool.
The client advertises support for:
textDocument/definition(go-to-definition)textDocument/references(find references)textDocument/hover(type info, documentation)textDocument/documentSymbol(hierarchical symbols in a file)textDocument/implementation(go-to-implementation)textDocument/callHierarchy(incoming/outgoing calls)workspace/symbol(project-wide symbol search)window/workDoneProgress(progress tracking)
LSP configuration extraction from Neovim. Runs nvim --headless with an embedded Lua script that queries vim.lsp.config and vim.filetype.match to produce a JSON manifest of:
- Server names, commands, filetypes, root markers
- Server settings and init options
- File extension to filetype mappings
Falls back to an empty config on any failure (nvim not installed, timeout, parse error).
LspManager owns the config and a map of running server instances. Key behaviors:
- Lazy start:
get_or_start_server(filetype)spawns a server on first use for a given filetype - Root detection: walks up from project dir looking for root markers (e.g.
Cargo.toml,go.mod) - Pre-warming:
pre_warm()detects project type from marker files and eagerly starts relevant servers - Shutdown:
shutdown_all()sends the LSP shutdown/exit sequence to all running servers
LspServer wraps a single running LSP server process. Handles:
- The
initialize/initializedhandshake - Typed request/response via
request::<R>(params)usinglsp-typestrait bounds - Typed notifications via
notify::<N>(params) - Convenience methods:
open_file(),close_file() - Server capability and progress inspection
- rust-analyzer special-casing: injects
checkOnSave: falseto avoid heavy background checks
LspTransport implements the JSON-RPC over stdio protocol:
- Content-Length framed message reading/writing
- Background reader task that dispatches responses to waiting
oneshotchannels - Auto-replies to server-initiated requests (e.g.
window/workDoneProgress/create) ProgressTrackerfor monitoring server indexing/loading state- 30-second request timeout with automatic cleanup
- Clean shutdown with process kill on drop
| Crate | Purpose |
|---|---|
lsp-types |
LSP protocol type definitions |
tokio |
Async runtime, process spawning, IO |
serde / serde_json |
JSON-RPC serialization |
parking_lot |
Fast synchronous mutexes (progress tracker) |
url |
File path to URI conversion |
anyhow |
Error handling |
tracing |
Structured logging |