Loading...
Loading...
9 new projects with 85 stars.
A production-ready, async-first Python client for the Language Server Protocol (LSP). Built for developers who need fine-grained control and extensibility when integrating language intelligence into their tools.
lsp-client is engineered for developers building production-grade tooling that requires precise control over language server environments:
Location vs LocationLink), providing consistent, high-level Python objects instead of raw JSON-RPC structures.uv add lsp-client
The following code snippet can be run as-is, try it out:
# NOTE: install pyrefly with `uv tool install pyrefly` first
import anyio
from lsp_client import Position, PyreflyClient
async def main():
async with PyreflyClient() as client:
refs = await client.request_references(
file_path="example.py",
position=Position(10, 5)
)
for ref in refs:
print(f"Reference at {ref.uri}: {ref.range}")
anyio.run(main)
The examples/ directory contains comprehensive usage examples:
rust_analyzer.py - Rust code intelligence with Rust-Analyzerpyrefly.py - Python linting and analysis with Pyreflyprotocol.py - Direct LSP protocol usageRun examples with:
uv run examples/pyrefly.py
Defining a custom client is super easy with the capability mixin:
@define
class MyPythonClient(
Client,
WithRequestHover, # textDocument/hover
WithRequestDefinition, # textDocument/definition
WithRequestReferences, # textDocument/references
WithNotifyDidChangeConfiguration, # workspace/didChangeConfiguration
# ... and other capabilities as needed
):
def create_default_servers(self) -> DefaultServers:
return DefaultServers(
local=LocalServer(program="pylsp", args=["--stdio"]),
)
def create_initialization_options(self) -> dict:
return {"plugins": {"pyflakes": {"enabled": True}}} # custom init options
def check_server_compatibility(self, info: lsp_type.ServerInfo | None) -> None:
return # Custom compatibility checks if needed
| Language Server | Module Path | Language |
| -------------------------- | ---------------------------------- | --------------------- |
| Pyright | lsp_client.clients.pyright | Python |
| Basedpyright | lsp_client.clients.basedpyright | Python |
| Pyrefly | lsp_client.clients.pyrefly | Python |
| Ty | lsp_client.clients.ty | Python |
| Rust Analyzer | lsp_client.clients.rust_analyzer | Rust |
| Deno | lsp_client.clients.deno | TypeScript/JavaScript |
| TypeScript Language Server | lsp_client.clients.typescript | TypeScript/JavaScript |
| Gopls | lsp_client.clients.gopls | Go |
lsp-client implements a prioritized server loading strategy to ensure your tool works across different environments without manual configuration:
Server instance, it will be used first.The mixin-based architecture allows you to define exactly what your client supports. This is not just for organization; it directly affects the Initialize request sent to the server, ensuring the server only sends relevant notifications and doesn't waste resources on unused features.
lsp-client features a sophisticated configuration system designed for production use:
ConfigurationMap to manage global settings and path-based overrides (e.g., different linting rules for tests/ vs src/).workspace/didChangeConfiguration notifications, ensuring the language server always has the latest settings without a restart.The library is built with extensibility as a core principle. You are never locked into the default behavior:
Server class to connect to language servers over custom transports (e.g., WebSockets, named pipes, or remote SSH).We welcome contributions! Please see our Contributing Guide for details on:
Note: Container-based language server execution is currently under maintenance and refactoring. This feature will be re-enabled in the next minor version release with improved stability and performance. For now, please use local language server installations.
This project is licensed under the MIT License - see the LICENSE file for details.