The client (editor) spawns the language server as a separate process and communicates over stdin/stdout (or socket/pipe) using JSON-RPC 2.0 framed with a Content-Length header. After initialization (initialize / initialized) the client sends buffer notifications (textDocument/didOpen, didChange, didClose) and requests for semantic features (textDocument/completion, hover, definition, references, codeAction, rename, formatting). The server replies, or pushes notifications (e.g. textDocument/publishDiagnostics with errors and warnings). Lifecycle, capability negotiation and document versioning are part of the specification.
Before LSP every editor had to implement integration with every language separately, leading to a combinatorial N×M explosion of plugins of uneven quality. LSP reduces this to N + M: one language server serves every editor, one client serves every language.
Client side of the protocol — spawns the language server as a subprocess, tracks open buffers and translates user interactions into LSP requests.
Official
Language-specific implementation (e.g. rust-analyzer, gopls, pyright). Builds and maintains a semantic model of the project — syntax trees, types, symbol indexes — and answers client requests.
Official
Standard JSON-RPC 2.0 framed with a Content-Length header. Most commonly uses stdio; the spec also allows sockets and named pipes.
During the initialize / initialized exchange the client and server announce which features they support (e.g. snippetSupport, hierarchicalDocumentSymbolSupport). Lets the protocol evolve without breaking older clients or servers.
Client and server must agree on buffer version — out-of-order textDocument/didChange leads to stale diagnostics and wrong edit positions.
Client must inspect capabilities announced by the server in the initialize response — assuming features the server does not support results in JSON-RPC errors.
Naive servers re-scan the whole workspace on every change, which on large monorepos causes multi-second completion stalls.
Microsoft, Red Hat and Codenvy design a shared protocol based on earlier OmniSharp work.
Microsoft publishes the open Language Server Protocol specification in June 2016, with reference implementations in VS Code, Eclipse Che and Visual Studio.
Version 3.0 stabilizes; Vim (coc.nvim, vim-lsp), Emacs (lsp-mode), Sublime, Atom and JetBrains gain LSP support.
LSP 3.16 adds semantic tokens, call hierarchy and moniker support — enriching the semantic information available to clients.
Cursor, Aider, Continue and Claude Code leverage LSP to feed LLMs semantic context about code (definitions, references, diagnostics), materially improving the quality of model-generated edits.