Write Language Servers that comply with 3.17 of the LSP Specification
See the codego-lsp is a Go library for building Language Server Protocol servers in Go without reimplementing JSON-RPC transport, handler dispatch, document sync, or protocol types.
servertest harness for end-to-end LSP tests over in-memory pipesgo get github.com/owenrumney/go-lsp
package main
import (
"context"
"log"
"github.com/owenrumney/go-lsp/lsp"
"github.com/owenrumney/go-lsp/server"
)
type Handler struct{}
func (h *Handler) Initialize(_ context.Context, _ *lsp.InitializeParams) (*lsp.InitializeResult, error) {
return &lsp.InitializeResult{
ServerInfo: &lsp.ServerInfo{Name: "example", Version: "0.1.0"},
}, nil
}
func (h *Handler) Shutdown(_ context.Context) error { return nil }
func (h *Handler) Hover(_ context.Context, _ *lsp.HoverParams) (*lsp.Hover, error) {
return &lsp.Hover{
Contents: lsp.NewHoverContents(lsp.Markdown, "**hello**"),
}, nil
}
func main() {
srv := server.NewServer(&Handler{})
if err := srv.Run(context.Background(), server.RunStdio()); err != nil {
log.Fatal(err)
}
}
Implement server.HoverHandler, server.CompletionHandler, server.TextDocumentSyncHandler, and other interfaces as needed. go-lsp registers methods and advertises capabilities automatically.
Generate a starter server:
go run github.com/owenrumney/go-lsp/cmd/scaffold@latest \
--name mylang \
--module github.com/you/mylang-lsp \
--lang mylang \
--features hover,completion,diagnostics
Run tests with the included harness:
func TestHover(t *testing.T) {
h := servertest.New(t, &Handler{})
h.DidOpen("file:///test.txt", "plaintext", "hello")
hover, err := h.Hover("file:///test.txt", 0, 0)
if err != nil {
t.Fatal(err)
}
if hover == nil {
t.Fatal("expected hover result")
}
}
server.Client includes helpers for common outbound LSP calls, including:
PublishDiagnosticsShowMessage, LogMessage, ShowMessageRequestShowDocumentConfigurationApplyEditRegisterCapability, UnregisterCapabilityServer supports optional inbound middleware and request concurrency controls:
server.WithMethodMiddleware(...)server.WithNotificationMiddleware(...)server.WithMaxConcurrentRequests(n)server.WithRequestTimeout(d)These are opt-in. Default behavior stays simple.
The optional debug UI helps inspect LSP traffic while developing and testing.

docs/getting-started.mddocs/testing.mdexamples/examples/hover/ — basic hover providerexamples/completion/ — completion + resolveexamples/diagnostics/ — publish diagnostics on saveexamples/codeactions/ — quick fixes and code actionsexamples/symbols/ — document symbolsexamples/toylang/ — multi-feature toy language serverGo
84.2%
HTML
12.8%
CSS
1.2%
Write Language Servers that comply with 3.17 of the LSP Specification
See the codego-lsp is a Go library for building Language Server Protocol servers in Go without reimplementing JSON-RPC transport, handler dispatch, document sync, or protocol types.
servertest harness for end-to-end LSP tests over in-memory pipesgo get github.com/owenrumney/go-lsp
package main
import (
"context"
"log"
"github.com/owenrumney/go-lsp/lsp"
"github.com/owenrumney/go-lsp/server"
)
type Handler struct{}
func (h *Handler) Initialize(_ context.Context, _ *lsp.InitializeParams) (*lsp.InitializeResult, error) {
return &lsp.InitializeResult{
ServerInfo: &lsp.ServerInfo{Name: "example", Version: "0.1.0"},
}, nil
}
func (h *Handler) Shutdown(_ context.Context) error { return nil }
func (h *Handler) Hover(_ context.Context, _ *lsp.HoverParams) (*lsp.Hover, error) {
return &lsp.Hover{
Contents: lsp.NewHoverContents(lsp.Markdown, "**hello**"),
}, nil
}
func main() {
srv := server.NewServer(&Handler{})
if err := srv.Run(context.Background(), server.RunStdio()); err != nil {
log.Fatal(err)
}
}
Implement server.HoverHandler, server.CompletionHandler, server.TextDocumentSyncHandler, and other interfaces as needed. go-lsp registers methods and advertises capabilities automatically.
Generate a starter server:
go run github.com/owenrumney/go-lsp/cmd/scaffold@latest \
--name mylang \
--module github.com/you/mylang-lsp \
--lang mylang \
--features hover,completion,diagnostics
Run tests with the included harness:
func TestHover(t *testing.T) {
h := servertest.New(t, &Handler{})
h.DidOpen("file:///test.txt", "plaintext", "hello")
hover, err := h.Hover("file:///test.txt", 0, 0)
if err != nil {
t.Fatal(err)
}
if hover == nil {
t.Fatal("expected hover result")
}
}
server.Client includes helpers for common outbound LSP calls, including:
PublishDiagnosticsShowMessage, LogMessage, ShowMessageRequestShowDocumentConfigurationApplyEditRegisterCapability, UnregisterCapabilityServer supports optional inbound middleware and request concurrency controls:
server.WithMethodMiddleware(...)server.WithNotificationMiddleware(...)server.WithMaxConcurrentRequests(n)server.WithRequestTimeout(d)These are opt-in. Default behavior stays simple.
The optional debug UI helps inspect LSP traffic while developing and testing.

docs/getting-started.mddocs/testing.mdexamples/examples/hover/ — basic hover providerexamples/completion/ — completion + resolveexamples/diagnostics/ — publish diagnostics on saveexamples/codeactions/ — quick fixes and code actionsexamples/symbols/ — document symbolsexamples/toylang/ — multi-feature toy language serverGo
84.2%
HTML
12.8%
CSS
1.2%