lsp-client

📁 lsp-client/lsp-client 📅 Jan 28, 2026
3
总安装量
3
周安装量
#59144
全站排名
安装命令
npx skills add https://github.com/lsp-client/lsp-client --skill lsp-client

Agent 安装分布

opencode 3
amp 2
github-copilot 2
codex 2
kimi-cli 2
gemini-cli 2

Skill 文档

LSP Client

Semantic code analysis using Language Server Protocol (LSP) clients. Provides language-aware code navigation, symbol search, and safe refactoring capabilities.

Quick Start

Three ways to use the library:

1. Use Pre-built Language Clients

import anyio
from pathlib import Path
from lsp_client import Position
from lsp_client.clients.pyright import PyrightClient

async def main():
    workspace = Path.cwd()
    
    async with PyrightClient(workspace=workspace) as client:
        definitions = await client.request_definition_locations(
            file_path="src/main.py",
            position=Position(line=10, character=5)
        )
        
        for def_loc in definitions:
            file = client.from_uri(def_loc.uri)
            print(f"Definition at {file}:{def_loc.range.start.line}")

anyio.run(main)

2. Create Custom Client with Selected Capabilities

See scripts/custom_client_template.py for a complete template.

Key pattern – inherit from capability mixins:

from attrs import define
from lsp_client.clients.base import PythonClientBase
from lsp_client.capability.request import (
    WithRequestHover,
    WithRequestDefinition,
    WithRequestReferences,
)

@define
class MyClient(
    PythonClientBase,
    WithRequestHover,
    WithRequestDefinition,
    WithRequestReferences,
):
    ...

3. Use Ready-Made Scripts

Run standalone analysis scripts without writing code:

# Analyze symbol at position
python scripts/basic_analysis.py src/main.py 10 5

# Find all symbols in file
python scripts/find_all_symbols.py file src/main.py

# Search workspace symbols
python scripts/find_all_symbols.py workspace MyClass

# Safe rename with preview
python scripts/safe_rename.py src/main.py 10 5 new_name

Common Workflows

Exploring Unfamiliar Codebase

Task: Understand how a function is used across the project

Approach:

  1. Find definition: client.request_definition_locations()
  2. Find all references: client.request_references()
  3. Get type info: client.request_hover()

Script: python scripts/basic_analysis.py <file> <line> <char>

Safe Refactoring

Task: Rename a symbol across the entire workspace

Approach:

  1. Preview changes: client.request_rename_edits()
  2. Review affected files
  3. Apply: client.apply_workspace_edit()

Script: python scripts/safe_rename.py <file> <line> <char> <new_name>

Symbol Search

Task: Find all classes/functions matching a pattern

Approach:

  1. Workspace-wide: client.request_workspace_symbol_list(query="MyClass")
  2. File-specific: client.request_document_symbol_list(file_path=...)

Script:

  • python scripts/find_all_symbols.py workspace <query>
  • python scripts/find_all_symbols.py file <path>

Available Clients

See references/language_servers.md for full list.

Quick reference:

  • Python: PyrightClient, PyreflyClient, BasedpyrightClient, TyClient
  • Rust: RustAnalyzerClient
  • TypeScript/JS: TypescriptClient, DenoClient
  • Go: GoplsClient
  • Java: JdtlsClient

All clients support both local (subprocess) and container (Docker) modes.

Capability System

The library uses capability mixins to compose exactly the features needed.

Selecting Capabilities

See references/capabilities.md for complete list.

Common combinations:

Basic navigation:

  • WithRequestDefinition
  • WithRequestReferences
  • WithRequestHover

IDE-like features:

  • Add WithRequestCompletion
  • Add WithRequestSignatureHelp
  • Add WithRequestCodeAction

Symbol search:

  • WithRequestDocumentSymbol (file-level)
  • WithRequestWorkspaceSymbol (project-wide)

Refactoring:

  • WithRequestRename
  • WithRequestCodeAction
  • WithRequestWorkspaceEdit

Why Capability Mixins?

  1. Type safety: Only methods for registered capabilities exist
  2. Automatic negotiation: Client tells server what it supports
  3. Zero boilerplate: No manual capability checking
  4. Composability: Mix exactly what you need

Local vs Container Servers

Every client supports dual server backends:

Local Server (Subprocess)

from lsp_client.clients.pyright import PyrightClient

async with PyrightClient() as client:
    # Uses local pyright-langserver if available
    ...

Pros: Fast startup, direct file access
Cons: Requires server installed locally

Container Server (Docker)

from lsp_client.clients.pyright import PyrightClient, PyrightContainerServer

async with PyrightClient(server=PyrightContainerServer()) as client:
    # Uses ghcr.io/lsp-client/pyright:latest
    ...

Pros: Zero installation, consistent environment
Cons: Docker overhead, path translation

Automatic Fallback

If no server specified, library tries:

  1. Explicit server= argument (if provided)
  2. Local installation
  3. Container fallback
  4. Auto-install hook (if defined)

Key Concepts

Position

LSP uses 0-indexed line and character positions:

from lsp_client import Position

# Line 10, character 5 (0-indexed)
pos = Position(line=10, character=5)

URI vs File Path

LSP servers work with URIs. The client handles conversion:

# Server returns URI
location = await client.request_definition_locations(...)

# Convert back to file path
file_path = client.from_uri(location.uri)

Async Context Manager

Always use async with to ensure proper cleanup:

async with Client(...) as client:
    # Client initialized, server running
    result = await client.request_hover(...)
# Server automatically shut down

Advanced Features

Configuration Management

Clients come with sensible defaults. Override as needed:

@define
class MyClient(PyrightClient):
    def create_default_config(self):
        return {
            "python": {
                "analysis": {
                    "typeCheckingMode": "strict",
                }
            }
        }

Server Lifecycle Hooks

Customize server behavior with hooks:

from lsp_client.server.local import LocalServer

@define
class CustomServer(LocalServer):
    async def setup(self, workspace):
        # Before server starts
        ...
    
    async def on_started(self, workspace, sender):
        # After server ready
        ...
    
    async def on_shutdown(self):
        # Before cleanup
        ...

See library’s examples/custom_hooks.py for details.

Troubleshooting

Server Not Found

Symptom: “Could not find language server”

Solution: Either install locally or use container:

from lsp_client.clients.pyright import PyrightContainerServer

client = PyrightClient(server=PyrightContainerServer())

Path Translation Issues

When using containers, always work with workspace-relative paths:

# Good
await client.request_hover(file_path="src/main.py", ...)

# Bad (absolute paths won't translate correctly)
await client.request_hover(file_path="/Users/me/project/src/main.py", ...)

Resources

Scripts

  • basic_analysis.py – Hover, definition, references for a symbol
  • find_all_symbols.py – Document/workspace symbol search
  • safe_rename.py – Preview and apply rename refactoring
  • custom_client_template.py – Template for creating custom clients

References

  • capabilities.md – Complete list of available LSP capabilities
  • language_servers.md – Supported language servers and selection guide