pygls: The Generic Language Server Framework
pygls (pronounced like 'pie glass') is a pythonic generic implementation of the Language Server Protocol, serving as a foundation for writing custom Language Servers. It enables the creation of language servers with minimal code, supporting STDIO, TCP/IP, and WebSocket communication. Currently at version 2.1.1, pygls maintains an active development and release cadence, with recent updates in March 2026.
Warnings
- breaking Pygls v1.0 removed its hand-written LSP type and method definitions. All LSP types and method names must now be imported from `lsprotocol.types`. Previous modules like `pygls.lsp.methods` and `pygls.lsp.types` no longer exist.
- breaking Pygls v1.0 switched from Pydantic to `attrs` and `cattrs` for serialization and deserialization. Any custom LSP models defined in your server will need to be converted to `attrs`-style classes.
- breaking Pygls v2.0 removes support for Python 3.8. The minimum required Python version is now 3.9.
- breaking Pygls v2.0 includes a major upgrade to `lsprotocol` (v2025.x), bringing support for LSP v3.18 types and standardized object names. This might affect how certain complex LSP types are referenced.
- gotcha In pygls v2.0, server commands registered with `@server.command()` now unpack arguments directly into the command method's parameters, rather than passing a single list argument. Type annotations on command parameters can guide automatic JSON-to-attrs conversion.
- gotcha Pygls uses Python's built-in `logging` module. Server logs will not be visible by default unless you explicitly configure the logging module before starting your server.
Install
-
pip install pygls -
pip install pygls[ws]
Imports
- LanguageServer
from pygls.lsp.server import LanguageServer
- types
from lsprotocol import types
- TEXT_DOCUMENT_COMPLETION
from lsprotocol.types import TEXT_DOCUMENT_COMPLETION
Quickstart
from pygls.lsp.server import LanguageServer
from lsprotocol.types import (
TEXT_DOCUMENT_COMPLETION, CompletionItem, CompletionList, CompletionParams
)
server = LanguageServer('example-server', 'v0.1')
@server.feature(TEXT_DOCUMENT_COMPLETION)
def completions(params: CompletionParams):
"""Returns completion items."""
document = server.workspace.get_text_document(params.text_document.uri)
current_line = document.lines[params.position.line].strip()
items = []
if current_line.endswith('hello.'):
items = [
CompletionItem(label='world'),
CompletionItem(label='friend'),
]
return CompletionList(is_incomplete=False, items=items)
if __name__ == '__main__':
# Starts the language server using standard I/O (stdin/stdout)
server.start_io()