Build Server Protocol: how an editor and a build tool talk to each other
Protocol for IDEs and build tools to communicate about compile, run, test, debug and more.
At a glance
- What is it?
- BSP is a JSON-RPC protocol that lets an IDE ask a build tool to compile, run, test and debug a project, so that a Scala or Rust build tool can present its own project model inside an editor instead of the editor guessing. The specification, its documentation and the support libraries are all generated from a single Smithy model, and the protocol is now at 2.2 with a set of in-flight changes that move report identification and run parameters around.
- Who is it for?
- Adopt the Build Server Protocol if you maintain a build tool and want it to work in every editor that speaks BSP, rather than writing a separate IDE plugin for each one, or if you build an editor and want to integrate with build systems without a plugin per build tool.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the protocol is for
The Build Server Protocol is an effort to improve the integration between language servers and editors and build tools. The effort is led by the Scala Center together with the help of other tooling developers in the Scala ecosystem and beyond.
The problem it addresses is one every editor author has hit. An editor knows how to open files, offer completion and show diagnostics. It does not know how your build system works. It does not know which source files belong to which module, what the classpath of a module is, what arguments a test needs, or how to launch a debugger with the right settings. The usual outcome is that the editor integrates with the build tool through a plugin, one per build tool, per editor, and every combination has to be written.
BSP replaces the plugin with a protocol. The editor speaks JSON-RPC to a build server, and the build server answers questions about the project: what are the targets, what are the source directories, what are the compile and run settings, what diagnostics came out of a compile. The build tool implements the protocol once, and every editor that speaks it gets the integration for free.
The topic list names json-rpc and language-server-protocol, and the second of those is the important comparison. LSP is the protocol that made editor integration with compilers a solved problem, and BSP is the same idea one layer up, at the level of the build rather than the language. A language server knows about the file you are editing; a build server knows about the module.
The README is explicit that even though the protocol currently focuses on Scala developer tools, it is designed to be language-agnostic. And the 2.2 changelog shows that promise being kept: the unreleased section adds a cargo protocol extension and a Rust protocol extension, alongside a general set of changes to run parameters and report identification.
The primary language is Scala, the licence is Apache-2.0, the default branch is master, and the homepage is build-server-protocol.github.io. The last push was on 2026-10-19 with the project not archived, and the recent releases are v2.2.0-M3 from 2024-09-14, v2.2.0-M2 from 2024-03-14 and v2.1.1 from 2024-01-22.
One Smithy model, and everything generated from it
The most interesting engineering decision in the repository is stated in one sentence: the specification text, the docs and the support libraries for some of the supported languages are automatically generated from the Smithy model at spec/src/main/resources/META-INF/smithy/bsp/bsp.smithy.
Smithy is an interface definition language, in the same family as OpenAPI or Protocol Buffers, and using it here means the protocol has a single source of truth that is a machine-readable schema rather than a prose document. That matters more for a protocol than it would for an ordinary library, because a protocol is a contract between independently written implementations, and a contract written as prose drifts from the code that implements it.
The direction of generation is what makes this valuable. The schema is the input, and the specification text, the documentation and the support libraries are all outputs. So a change to a message shape is made once, in the schema, and the document that describes it and the client library that sends it are regenerated together. A new field cannot be documented in one place and forgotten in another.
The repository layout shows the pieces that this produces. There is a spec/ directory holding the Smithy model and the specification sources, a codegen/ directory for the generators, a docs/ directory for the documentation, and a website/ directory for the site hosting the published specification. There are also bsp4j/ and bsp4s/, which are the support libraries, the Java one and the Scala one, named with the 4j and 4s suffixes in the usual way for a JVM ecosystem. And a testkit/ directory plus a tests/ directory.
So the repository is not just a specification document with an implementation guide. It contains the schema, the generators, the generated libraries and the tests, in one tree, which means a client library and the spec it implements are versioned together.
The build system is Bazel, and it is worth noting the size of the configuration. There is a BUILD file, a WORKSPACE file, a MODULE.bazel and a MODULE.bazel.lock, which is the Bzlmod module system, a .bazelversion file pinning the Bazel release, a .bazelrc and a .bazelignore. There is a maven_install.json, which is how Bazel consumes Maven artifacts. And a version.bzl file, which is how the protocol version is defined in a form Bazel can read, so the version in the specification and the version in the build are the same value.
There is also a .scalafmt.conf for the Scala sources and a .yamlfmt for the YAML, along with a .prettierignore, and a .git-blame-ignore-revs file, which lists commits that reformat files and should be ignored when running git blame, so that a reformat does not destroy the history of who changed a line.
What the 2.2 changelog says about where the protocol is going
The changelog is the most direct evidence of how the protocol is evolving, and the 2.2.0 unreleased section is a good sample of the kind of change a protocol makes.
Three unstable notifications are added: run/printStdout, run/printStderr and run/readStdin. These let a client see the output of a running task and feed input into it, and the word unstable in the changelog is a formal marker that a client should not depend on the shape yet. It is the correct way to add a feature to a protocol without freezing it, and it is worth noticing that the project has the discipline to use that marker rather than shipping a stable-looking addition that everyone then depends on.
Then a change to how reports are identified. An optional originId field is added to TaskStartParams, TaskProgressParams and TaskFinishParams, and it is deprecated in CompileReport and TestReport, to support BSP clients that need to distinguish between multiple reports for the same target. The migration note says to use the originId field in TaskFinishParams instead of CompileReport or TestReport to identify the report.
That is a real interoperability problem being solved. If a build tool compiles a target twice, or produces a compile report and a test report for the same target, the client had no way to tell which report a later message referred to. The fix is to carry an identifier through the whole task lifecycle, and to deprecate the old location rather than remove it, so existing implementations keep working.
The rest of the section is about parameters and extensions. Optional support for environment variables and working directory parameters in buildTarget/run and buildTarget/test requests, with the arguments and environment variables lists in ScalaMainClass and ScalaTestSuites marked deprecated as they are replaced by the parameters in the base request. The cargo and Rust protocol extensions. An update to the diagnostic-related structures to match LSP 3.17. A buildToolParams field added to compile, test and run requests. And an optional data field on SourceItem.
The pattern across all of these is worth naming. The base protocol is kept small and generic, and anything specific to one build tool or one language goes into an extension. The Rust and cargo extensions are examples: a language-agnostic core with a Rust-shaped layer on top, rather than a core that grows a Rust-shaped section.
The maintainers, and the governance of a shared protocol
The maintainers section is a good illustration of how a protocol like this is actually run, because the list is long and includes a category of former maintainers.
There are two current maintainers. Adrien Piquerez of the Scala Center, and Łukasz Wawrzyk of VirtusLab. Both organisations are from the Scala ecosystem, which matches the description of the project's origins.
The former maintainers list is longer and the affiliations are more varied. Chris Kipp, formerly of Lunatech. Jorge Vicente Cantero, Ólafur Páll Geirsson and Tomasz Pasternak, the last of them from JetBrains and VirtusLab. Andrzej Głuszak and Justin Kaeser from JetBrains. Marcin Abramowicz from JetBrains. And the README notes that Tomasz Pasternak was from JetBrains and VirtusLab.
What that list shows is the pattern of a protocol that has been through a change of guard, and the record is kept rather than erased. A protocol with more than one maintainer organisation and a mix of independent contributors and a major IDE vendor is one that has outgrown the team that started it, and the repository keeps the history of that transition visible.
JetBrains appearing repeatedly in the list is the other significant fact. An IDE vendor investing maintainer time in a protocol that reduces per-build-tool plugin work is acting in its own interest, and that investment is one of the reasons the protocol exists at all. The Scala Center's role is the other half, since it is the ecosystem that needed the protocol first.
The contribution guidance is a single line, pointing at a CONTRIBUTING document, and the chat is on Discord. For a project where the artefact is a specification rather than a running service, that is an entirely appropriate set of arrangements: proposals happen in issues, the schema is the thing being argued over, and the generated artefacts follow.
The NOTICE.md file at the root is worth a mention. A specification that is implemented by many organisations needs an explicit record of what notice applies to it, and a NOTICE file is how Apache-licensed projects record that.
How to evaluate it, and what to check first
There are four things to consider, and the first one depends on what role you would play.
Are you a build tool author or an editor author? The protocol is designed for both, but the work is different. A build tool author implements a server that answers questions about targets, source directories, compile settings, run settings and diagnostics, and the effort is in mapping an existing build system's model onto the BSP shape. An editor author implements a client that talks to one or more build servers, and the effort is in caching, in handling the case where no build server is running, and in presenting the results.
Second, the version question. The recent releases are 2.2.0-M3 from September 2024 and 2.1.1 from January 2024, and the 2.2.0 section in the changelog is still marked unreleased, with new notifications, a deprecated field and two language extensions in flight. The last push was on 2026-10-19, so work is continuing on the specification even though the release tags are older. If you are implementing, you need to decide whether to target 2.1.x, which is stable, or 2.2, which has the newer features and the deprecated fields to work around.
Third, the extension mechanism. A build tool for a language that needs something BSP does not cover should look at the extension point rather than waiting for a core change. The Rust and cargo extensions in the 2.2 changelog are the model to follow, and they are a good demonstration that the language-agnostic design has held up in practice.
Fourth, the language support libraries. The repository ships bsp4j and bsp4s, generated from the same Smithy model as the specification, so a Java or Scala implementation gets the message types for free. If you are in the JVM ecosystem that removes most of the work, and if you are elsewhere you are relying on generated clients from the model, which is the same benefit in a different form.
What you get in exchange is a way to make your build tool work in every editor that supports BSP, rather than writing a plugin per editor. For a tool that already has an IDE plugin for one editor, that is a straight swap of the plugin for a protocol implementation. The cost is that the protocol is a contract, and contracts only pay off if enough people implement them, which is why the extension mechanism and the language-agnostic design matter as much as the feature set.
Editorial conclusion
Adopt the Build Server Protocol if you maintain a build tool and want it to work in every editor that speaks BSP, rather than writing a separate IDE plugin for each one, or if you build an editor and want to integrate with build systems without a plugin per build tool. Do not adopt it expecting a stable 2.2, because that section is still marked unreleased and carries deprecated fields alongside new ones, so decide whether to target the 2.1 line or the newer shape and plan for the transition. Before you commit, read the Smithy model rather than only the prose specification, since the model is what the documentation and the support libraries are generated from, look at how the Rust and cargo extensions are structured if your build tool needs something the core does not cover, and check whether the generated library for your language already exists so you are not writing message types by hand.
Frequently asked questions
What is the Build Server Protocol?
It is a JSON-RPC protocol for communication between IDEs and build tools about compiling, running, testing and debugging. The project is an effort to improve integration between language servers and editors and build tools, led by the Scala Center, and it is Apache-2.0 licensed and designed to be language-agnostic even though it currently focuses on Scala developer tools.
How is the Build Server Protocol specification produced?
The specification text, the documentation and the support libraries for some of the supported languages are all automatically generated from the Smithy model at spec/src/main/resources/META-INF/smithy/bsp/bsp.smithy. A single machine-readable schema is therefore the source of truth, and the document and the client libraries cannot drift apart from the code.
What support libraries does the project publish?
The repository contains bsp4j and bsp4s, the Java and Scala support libraries, along with a testkit and a tests directory, and a codegen directory holding the generators. The libraries are generated from the same Smithy model as the specification, so a JVM implementation gets the message types without hand-writing them.
What is changing in Build Server Protocol 2.2?
The unreleased 2.2.0 section adds unstable run/printStdout, run/printStderr and run/readStdin notifications, an optional originId field on the task start, progress and finish parameters with deprecation of the same field in CompileReport and TestReport, environment variable and working directory parameters for run and test requests, and cargo and Rust protocol extensions.
Who maintains the Build Server Protocol?
The current maintainers are Adrien Piquerez of the Scala Center and Łukasz Wawrzyk of VirtusLab. The README also lists a longer set of former maintainers from Lunatech, the Scala Center, JetBrains and VirtusLab, and the project is developed with the help of tooling developers in the Scala ecosystem and beyond.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/build-server-protocol-build-server-protocol)Was this useful?