# vscode-languageserver-node: the six npm modules behind VS Code language servers

> Microsoft's vscode-languageserver-node repository publishes the client, server, protocol, types, text document and JSON-RPC modules that VS Code language servers are built on, versioned on independent release lines and built by a single Azure pipeline. The 3.18 protocol adds inline completion, server-provided documents and a tag for LLM generated code actions.

**microsoft/vscode-languageserver-node** — Language server protocol implementation for VSCode. This allows implementing language services in JS/TS running on node.js

- Repository: https://github.com/microsoft/vscode-languageserver-node
- Stars: 1,796 · Forks: 426
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/microsoft-vscode-languageserver-node

## The problem: language intelligence trapped in one editor

Every serious editor needs to know about the file you are editing: its symbols, its types, its errors, its refactorings. Writing that logic once per editor is unworkable, and writing it once per language is also unworkable. The Language Server Protocol solves the second half of that problem by moving language intelligence into a separate process and speaking to it over a JSON based protocol.

This repository is the Node.js implementation of that idea, and the project description is direct about the purpose: it allows implementing language services in JavaScript or TypeScript running on Node.js. It is the machinery behind a large share of the language servers people use every day, whether they know it or not.

The audience is two kinds of developer. The first writes a language server and needs a framework that handles the transport, the document synchronisation and the request dispatch, so that the work is about the language rather than about the plumbing. The second writes a VS Code extension that talks to an existing language server, and needs a client that handles the other half of the conversation.

The scope decision in this repository is worth stating plainly. It is a Node.js implementation for VS Code. The protocol itself is not VS Code specific, but this code is, and the client module in particular is described as the module to talk to a VS Code language server from a VS Code extension. A team whose editor is not VS Code needs a different client, even if the server side of the conversation is portable.

## Six modules, and the order of the stack

The repository publishes six npm modules, and reading their descriptions tells you the whole stack from the wire format upward.

At the bottom is vscode-jsonrpc, the underlying message protocol used to communicate between a client and a server. Above that, vscode-languageserver-types holds the data types used by both sides, the shapes that the protocol carries. Then vscode-languageserver-protocol is the actual protocol definition in TypeScript, the request and notification signatures that describe the language server interface itself. vscode-languageserver-textdocument provides text document implementations usable in a language server running on Node.js, which is the piece that lets a server hold the open documents without implementing the sync protocol from scratch.

Above that, vscode-languageserver is the module to implement a language server using Node.js as a runtime, and vscode-languageclient is the module to talk to a VS Code language server from a VS Code extension. So the server and the client are separate modules that meet at the protocol, and the protocol itself is separated from the message layer beneath it.

That separation is the design decision that makes the rest of the repository work. A protocol change, a new request or a new type, lands in one module, and the two implementations on either side are versioned against it independently. It is also why the release history looks the way it does.

## Protocol 3.18: inline completion, server documents and an LLM tag

The 3.18 protocol release is the interesting one for anyone building a server today, because it adds the request types that the last few years of editor tooling have been waiting for.

The new requests and notifications include textDocument/inlineCompletion, an inline completion request with its params, registration options and client capabilities, in a new file. There is workspace/textDocumentContent together with workspace/textDocumentContent/refresh, which gives the server a way to provide dynamic text document content for custom schemes, with multi-scheme registration supported. And there is textDocument/rangesFormatting, which formats multiple ranges in one request, alongside a new DocumentRangesFormattingRequest and DocumentRangesFormattingParams, and workspace/foldingRange/refresh, a server initiated folding range refresh with FoldingRangeRefreshRequest and FoldingRangeWorkspaceClientCapabilities. Notebook diagnostic pull and notebook code action kind support were added on top of the existing notebook feature.

Two changes are directly about how servers interact with newer tooling. WorkspaceEdit may now carry SnippetTextEdit entries, so a snippet can travel inside a workspace edit, with a new client capability workspace.workspaceEdit.snippetEditSupport. And CodeAction gained a tags field, where CodeActionTag.LLMGenerated lets a server mark an action as generated by a language model, behind the client capability textDocument.codeAction.tagSupport. There is also a new code action kind, CodeActionKind.RefactorMove, and CodeActionOptions.documentation lets providers ship documentation that appears in the actions menu.

The rest of the release is familiar territory with new names. CompletionList.itemDefaults was extended with a per item default data payload, and a new CompletionList.applyKind describes a per field merge strategy, Replace or Merge, for commitCharacters and data between list defaults and individual items, gated by the client capability completionList.applyKindSupport. PrepareRenameResult was reified as named types, and WorkspaceEditMetadata was added so that ApplyWorkspaceEditParams.metadata can carry isRefactoring.

## Independent version lines, and what that means for your dependencies

The release history is the part that surprises people who expect a single version number for a single repository.

The most recent release is labelled 3.18.4 for the protocol, with 9.0.3 for JSON-RPC and 10.1.2 for both the client and the server. The published tags make the same structure explicit: release/types/3.18.4 on 2026-09-25, release/textDocument/1.0.15 on 2026-09-24 and release/server/10.1.2 on 2026-09-25. So the protocol moves in the 3.x line, the message layer in the 9.x line, the server and client in the 10.x line, and the types module on its own 1.x line, and each of them is released on its own schedule.

The practical consequence is a dependency decision. A project that pins the latest of each module independently can end up with a client that expects a protocol version the server does not implement, or a protocol package that has a request the server module has not yet surfaced. The repository is not a single artefact, and it does not publish a lockstep release, so the version set has to be chosen deliberately rather than accepted by default.

The other detail visible in the history is the handling of proposed features. The 3.18.1 notes record that the textDocumentContent capability is still behind a proposed gate even though in 3.18 it is no longer flagged as proposed. That is a good illustration of how a protocol evolves: features land, and then a gate around them is adjusted separately.

## Working in the repository: symlinks, one pipeline, a testbed

The contributing instructions are short, and they are the ones you need before touching anything. After cloning, you run npm install to install dependencies and npm run symlink to point the packages in the repository at each other, which is what makes local development across the six modules possible without publishing.

The build script in the root package.json shows the rest of the workflow. There are separate compile scripts per module, so the types, textDocument, jsonrpc, protocol and server packages each have their own TypeScript project configuration, and the compile script uses the build mode of the TypeScript compiler, tsc -b, which is what makes those per module builds composable. The symlink variants come in three flavours, for the packages themselves, for the tests and for the testbed.

The test setup is more than unit tests. The test script runs a build test and then delegates to a script in the build directory that runs the suites, and the dev dependencies include mocha for the unit level, http-server, playwright for browser driven work, and shelljs and shx for the build scripts. There is a testbed/ directory for end to end exercises and a client-node-tests/ directory for the client side, and the postinstall script installs dependencies in the testbed, wires up the symlinks and installs the playwright browsers.

Two other entries deserve a mention. The tsconfig-gen/ directory and the ts-json-schema-generator dependency point to schema generation from the TypeScript definitions, which is how a protocol package can publish JSON schemas for its types. And the .lsifrc.json configuration is for source indexing, so a language server written on top of this can expose its own symbols to code navigation tools.

## Where this is the wrong tool, and what the alternative costs

The first limit is the client. vscode-languageclient is built for a VS Code extension, with the VS Code extension host API as its transport. If your editor is not VS Code, you are not going to use this client, and the server side, while portable in principle, still speaks a protocol whose capabilities and lifecycle are shaped by what VS Code can do. The realistic alternative in that case is either a different language server framework for that editor, or writing the client yourself against vscode-jsonrpc, which is transport agnostic and the only piece here that is.

The second limit is scope. This is the protocol layer, not a language implementation. It gives you the request types, the document synchronisation and the dispatch, and you still have to write the analysis: the parser, the type inference, the diagnostics. For a team whose language is already supported by an existing server, this repository is unnecessary. For a team with a domain specific language, it is exactly the right starting point.

The third approach difference is between the protocol route and the editor API route. A VS Code extension can call the editor's own API directly, with no process boundary, no JSON serialisation and no lifecycle to manage, and get a better integrated result. The protocol route costs more, and buys you a language server that is not tied to one editor and can be reused by other clients. Which one is right depends on whether reuse outside VS Code is a real requirement for you, not on which is architecturally nicer.

One more practical limit. The modules move on separate version lines, so an upgrade is a coordination exercise rather than a single version bump, and the 3.18 features are new enough that the editor support for them is still uneven, particularly for the ones behind a proposed gate.

## Licence, maintenance and the AI agent instructions

The licence is MIT, and the repository is published by Microsoft Corporation, so the code can be used in commercial products and modified without any copyleft obligation. There is a License.txt at the root, and a SECURITY.md for reporting security issues in the protocol implementation itself, which is a slightly unusual thing to have in a library that mostly defines message shapes.

The repository is not archived and the last push was on 2026-10-16, so the modules are being maintained. The release cadence in the history is steady, with the protocol at 3.18.4, JSON-RPC at 9.0.3 and the client and server at 10.1.2, all from late September 2026.

The most interesting piece of documentation for anyone working with an AI assistant on this codebase is the contributing guidance itself. The project documentation says to see CONTRIBUTING.md for the repository map, the focused build and test commands, the generated-file workflows and the maintenance hazards, and it adds that AI coding agents should also read AGENTS.md. That is a project that has decided its own structure is hard enough to reason about that a human-written map of it is necessary, and that an agent needs to be pointed at that map rather than left to explore the tree. The changes/ directory, the eslint configuration files, the jsconfig.json and the .vscode/ directory complete a repository that is set up for a large number of contributors, and the documentation links to the VS Code example language server walkthrough for the on-ramp.

## Conclusion

Adopt these modules if you are writing a language server for VS Code in TypeScript, since they are the reference implementation of the protocol and the fastest way to a working server. Do not adopt them if your target is an editor other than VS Code, because the client module is VS Code specific, and do not expect a single version number to describe the whole stack, since the six modules move on separate release lines. Before you start, read AGENTS.md and CONTRIBUTING.md as the project asks, because they document the build layout and the maintenance hazards, and pin the client, server and protocol versions together rather than taking the latest of each.

## FAQ

### Which npm modules does vscode-languageserver-node publish?

Six: vscode-languageclient for talking to a language server from a VS Code extension, vscode-languageserver for implementing a server on Node.js, vscode-languageserver-textdocument for the text document implementation, vscode-languageserver-protocol for the protocol definition in TypeScript, vscode-languageserver-types for the shared data types, and vscode-jsonrpc for the underlying message protocol.

### How do I build the repository after cloning it?

Run npm install to install the dependencies and npm run symlink to point the packages in the repository at each other. The root package.json carries separate compile scripts per module, and the test script runs a build test before the suites, with a testbed and a client-node-tests directory for end to end work.

### Do the modules in vscode-languageserver-node share a version number?

No. The recent history shows protocol 3.18.4, JSON-RPC 9.0.3 and both client and server at 10.1.2, and the published tags are namespaced per module, such as release/types/3.18.4 and release/server/10.1.2. Each module is released on its own schedule, so a project has to pin a consistent set.

### What did the 3.18 protocol release add?

It added textDocument/inlineCompletion, workspace/textDocumentContent with its refresh request for server provided documents, textDocument/rangesFormatting, and workspace/foldingRange/refresh. It also added snippet support in workspace edits, a CodeActionTag.LLMGenerated tag for actions produced by a language model, and a new CodeActionKind.RefactorMove.

### What licence is vscode-languageserver-node released under?

MIT, with a License.txt at the root of the repository and the MIT licence recorded in the package metadata, so the modules can be used and modified in commercial products without a copyleft obligation.

## Sources

- [Issues](https://github.com/microsoft/vscode-languageserver-node/issues)
- [License: MIT](https://github.com/microsoft/vscode-languageserver-node/blob/main/LICENSE)
- [microsoft/vscode-languageserver-node on GitHub](https://github.com/microsoft/vscode-languageserver-node)
- [README](https://github.com/microsoft/vscode-languageserver-node/blob/main/README.md)
- [Releases](https://github.com/microsoft/vscode-languageserver-node/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/microsoft-vscode-languageserver-node
