mcp-lsp-proxy

mazdak/mcp-lsp-proxy

3.2

If you are the rightful owner of mcp-lsp-proxy and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The MCP-LSP Proxy is a server that bridges AI assistants with multiple Language Server Protocol (LSP) servers, enabling advanced code intelligence features.

MCP-LSP Proxy

A Model Context Protocol (MCP) server that proxies multiple Language Server Protocol (LSP) servers, making code intelligence features accessible to AI assistants.

Requirements: Python 3.11+

Features

  • Multi-LSP Support: Connect to multiple LSP servers simultaneously via Microsoft's MultiLSP library
  • Automatic Language Detection: Routes requests to appropriate LSP based on file extension
  • Enhanced LSP Features:
    • Go to Definition
    • Find References
    • Hover Information
    • Document Symbols
    • Code Completions
    • Workspace Symbol Search
  • Smart Workspace Detection: Automatically finds project roots based on language-specific markers
  • TOML Configuration: Simple configuration format
  • Async Architecture: Native async/await support for efficient concurrent operations
  • Robust Go Support: Properly handles gopls with automatic workspace configuration

Installation

Prerequisites

  1. Python 3.11+ - Required for the proxy server
  2. Go (optional) - If you want to use Go language features
  3. Node.js (optional) - If you want to use TypeScript/JavaScript features

Install the Proxy

Using uv (recommended):

# Install in development mode
uv sync --extra dev

# Or install globally
uv tool install mcp-lsp-proxy

Using pip:

pip install mcp-lsp-proxy

Quick Start

  1. Create a configuration file:
mcp-lsp-proxy --init
  1. Test the server:
mcp-lsp-proxy

Configuration

Create a mcp-lsp-config.toml file:

# Global proxy settings
[proxy]
log_level = "INFO"
timeout = 30.0
auto_restart = true
max_restart_attempts = 3

# Python LSP
[lsp.python]
name = "Python LSP"
languages = ["python", "py"]

# TypeScript/JavaScript LSP
[lsp.typescript]
name = "TypeScript LSP"
languages = ["typescript", "javascript", "ts", "js", "tsx", "jsx"]

# Go LSP
[lsp.go]
name = "Go LSP"
languages = ["go"]

# Rust LSP
[lsp.rust]
name = "Rust LSP"
languages = ["rust", "rs"]

# Add more LSP servers as needed

Advanced Configuration

With MultiLSP backend, configuration is simplified:

  • name: Display name for the language
  • languages: List of language identifiers or file extensions

MultiLSP automatically handles:

  • Language server installation and management
  • Workspace detection and configuration
  • Server-specific initialization options
  • Environment setup

The proxy will automatically detect workspace roots based on language-specific markers:

  • Go: go.mod
  • Python: pyproject.toml, setup.py, requirements.txt
  • TypeScript/JavaScript: package.json, tsconfig.json
  • Rust: Cargo.toml
  • Java: pom.xml, build.gradle

To create a default configuration:

mcp-lsp-proxy --init

Integration Guide

Claude Desktop

  1. Find your configuration file:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json
    • Linux: ~/.config/Claude/claude_desktop_config.json
  2. Add the LSP proxy configuration:

{
  "mcpServers": {
    "lsp-proxy": {
      "command": "mcp-lsp-proxy",
      "args": ["--config", "/path/to/mcp-lsp-config.toml"],
      "env": {
        "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
      }
    }
  }
}
  1. Restart Claude Desktop to load the new configuration.

  2. Verify it's working by asking Claude to analyze code in your project.

Claude Code (CLI)

Claude Code is Anthropic's official CLI tool. You can configure MCP servers in several ways:

  1. Using the CLI wizard:

    claude mcp add
    
  2. Adding directly via command:

    claude mcp add-json lsp-proxy '{"command":"mcp-lsp-proxy","args":["--config","/path/to/mcp-lsp-config.toml"]}'
    
  3. Project configuration (.mcp.json in project root):

    {
      "mcpServers": {
        "lsp-proxy": {
          "command": "mcp-lsp-proxy",
          "args": ["--config", "./mcp-lsp-config.toml"],
          "env": {
            "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
          }
        }
      }
    }
    
  4. Using with Claude Code:

    claude --mcp-config /path/to/mcp-config.json
    

Other MCP Clients

For any MCP-compatible client, use these settings:

  • Command: mcp-lsp-proxy
  • Arguments: ["--config", "/path/to/config.toml"]
  • Protocol: stdio (standard input/output)

Troubleshooting Integration

  1. Check server is running:

    mcp-lsp-proxy --config your-config.toml
    

    You should see: MCP-LSP Proxy (MultiLSP) started

  2. Verify language servers:

    • For Go: which go should return a path
    • For Python: MultiLSP handles this automatically
    • For TypeScript: which node should return a path
  3. Check logs: Set log_level = "DEBUG" in your config file for detailed logging.

Usage Examples

Once integrated, you can use these commands with your AI assistant:

Navigating Code

"Go to the definition of the calculate function in main.py"
"Find all references to the User class"
"Show me what the process_data function does" (uses hover)

Exploring Codebases

"What symbols are defined in this file?"
"Search for all functions that contain 'parse' in their name"
"Show me all the methods of the Calculator class"

Getting Help While Coding

"What completions are available after 'math.'?"
"What parameters does this function take?"
"Find where this variable is defined"

Available Tools

goto_definition

Navigate to the definition of a symbol.

Parameters:

  • uri: File URI (e.g., file:///path/to/file.py)
  • line: Line number (0-indexed)
  • character: Character position (0-indexed)

Example output:

Definition(s) found:
  → utils.py:25:5

find_references

Find all references to a symbol.

Parameters:

  • uri: File URI
  • line: Line number (0-indexed)
  • character: Character position (0-indexed)
  • include_declaration: Include the declaration in results (default: true)

Example output:

Found 5 reference(s) in 3 file(s):

main.py:
  Line 15, Col 8
  Line 42, Col 12

utils.py:
  Line 25, Col 5

tests/test_main.py:
  Line 10, Col 16
  Line 35, Col 20

get_hover

Get hover information (type info, documentation) at a position.

Parameters:

  • uri: File URI
  • line: Line number (0-indexed)
  • character: Character position (0-indexed)

Example output:

def process_data(items: List[Dict[str, Any]]) -> DataFrame

Process a list of items and return a pandas DataFrame.

Parameters:
- items: List of dictionaries containing item data

Returns:
- DataFrame with processed results

Design Note: While hover is primarily designed for interactive IDE experiences, it provides valuable type signatures and documentation that help AI assistants understand code context better than just reading the source.

get_diagnostics

Get diagnostics (errors, warnings) for a file or workspace.

Parameters:

  • uri: File URI (optional, omit for all files)

Example output:

Errors (2):
  main.py:15:10 - Undefined variable 'x' [pylsp]
  utils.py:8:1 - Missing return statement [pylsp]

Warnings (1):
  config.py:20:5 - Unused import 'os' [pylsp]

get_document_symbols

Get symbols (functions, classes, etc.) in a document.

Parameters:

  • uri: File URI

Example output:

Document symbols:
• MyClass (Class)
  • __init__ (Method)
  • process (Method)
  • validate (Method)
• helper_function (Function)
• CONSTANTS (Variable)

get_completions

Get code completions at a position.

Parameters:

  • uri: File URI
  • line: Line number (0-indexed)
  • character: Character position (0-indexed)

Example output:

Available completions:
• Add (Method) - func (c Calculator) Add(a, b int) int
• Multiply (Method) - func (c Calculator) Multiply(a, b int) int
• String (Method) - func (c Calculator) String() string
... and 5 more

search_workspace_symbols

Search for symbols across the entire workspace.

Parameters:

  • query: Search query string
  • workspace: Workspace path (optional, auto-detected if not provided)

Example output:

Found 3 symbol(s) matching 'Add':

/path/to/project/calculator.go:
  • Add (Function) - Line 15, Col 1
  • AddNumbers (Function) - Line 42, Col 1

/path/to/project/math/utils.go:
  • AddFloat (Function) - Line 8, Col 1

Language Server Setup

Before using the proxy, you need to install the language servers you want to use:

Python (pylsp)

pip install python-lsp-server[all]

TypeScript/JavaScript

npm install -g typescript typescript-language-server

Rust (rust-analyzer)

rustup component add rust-analyzer

Go (gopls)

go install golang.org/x/tools/gopls@latest

Java

Download the Java Language Server from Eclipse JDT.LS

Development

Setup

# Clone the repository
git clone https://github.com/yourusername/mcp-lsp-proxy
cd mcp-lsp-proxy

# Install with dev dependencies
uv sync --extra dev

Running Tests

# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=mcp_lsp_proxy

# Run specific test file
uv run pytest tests/test_server.py

Code Quality

# Format code
uv run ruff format .

# Lint
uv run ruff check --fix .

# Type checking
uv run mypy .

Architecture

The MCP-LSP Proxy acts as a bridge between AI assistants using the Model Context Protocol (MCP) and language servers implementing the Language Server Protocol (LSP). It uses Microsoft's MultiLSP library to handle the complex LSP protocol implementation.

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”         ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│   AI Assistant  │◄────────┤  MCP-LSP Proxy   ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā–ŗā”‚ LSP Servers  │
│  (MCP Client)   │  MCP    │   (MultiLSP)     │  LSP    │              │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜         ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Why MultiLSP?

This project uses Microsoft's MultiLSP library instead of implementing LSP from scratch because:

  1. Automatic Language Server Management - MultiLSP downloads and manages language servers automatically
  2. Unified API - Same interface for all languages (Python, Go, TypeScript, Rust, etc.)
  3. Battle-tested - Used by Microsoft for AI coding scenarios
  4. Simplified Configuration - No need to specify LSP server commands or installation paths
  5. Better Error Handling - Clear error messages when dependencies are missing

Core Components

  1. MCPMultiLSPServer (server.py) - Main server using Microsoft's MultiLSP

    • MCP tool registration and handling via list_tools/call_tool pattern
    • Automatic workspace detection and management
    • Language server lifecycle handled by MultiLSP
  2. WorkspaceManager - Smart workspace detection

    • Finds project roots based on language markers (go.mod, package.json, etc.)
    • Caches workspace paths for performance
    • Handles URI to path conversions
  3. MultiLSP Integration - Leverages Microsoft's library

    • Handles all LSP protocol communication
    • Manages language server subprocesses
    • Provides unified async API
  4. Configuration (config.py) - Simplified TOML configuration

Performance Optimizations

  • Pre-computed language mapping: O(1) lookup for file extension to LSP server
  • Connection reuse: Persistent LSP connections across requests
  • Async I/O: Efficient handling of multiple concurrent requests

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

Known Limitations

MultiLSP Integration

  • Language Support: Limited to languages supported by MultiLSP (Python, Go, TypeScript, JavaScript, Rust, Java, C#, Ruby, Dart, Kotlin)
  • Python Version: MultiLSP requires Python 3.8-3.10 for full compatibility, though it works with 3.11+ in most cases

Feature Limitations

  • Missing LSP Features: Some advanced LSP features are not yet exposed:

    • Code actions (refactorings, fixes)
    • Rename symbol across files
    • Document formatting
    • Diagnostics (errors/warnings)
  • Document Lifecycle: MultiLSP handles document synchronization internally, but doesn't expose live edits to the MCP layer

  • Workspace-Centric: Each language server instance is tied to a specific workspace root. The proxy automatically detects and manages multiple workspaces.

Performance Considerations

While the architecture includes TODOs for caching and connection pooling, these may not be necessary:

  • LSP servers already cache internally
  • One connection per language is typically sufficient
  • Most operations are fast enough without additional caching

Troubleshooting

LSP server not starting

  • Check that the LSP command is in your PATH
  • Verify the command works when run manually: pylsp --stdio
  • Check logs with log_level = "DEBUG" in configuration

No results returned

  • Ensure the file exists and is accessible
  • Some LSPs require the file to be saved to disk
  • Check that the file extension matches the configured languages

Timeout errors

  • Increase the timeout in configuration:
    [proxy]
    timeout = 60.0  # seconds
    

Tips and Best Practices

  1. File URIs: Always use proper file URIs (e.g., file:///absolute/path/to/file.py)
  2. 0-indexed positions: Line and character positions are 0-indexed, matching LSP specification
  3. Multiple LSPs: You can configure multiple LSP servers for the same language; the proxy will use the last one defined
  4. Workspace folders: Configure workspace folders in the TOML for project-aware features
  5. Performance: The proxy maintains persistent connections to LSP servers for better performance

Supported Language Servers

With MultiLSP backend, the following languages are supported out-of-the-box:

  • Python: Via Jedi Language Server (automatically managed)
  • Go: Via gopls (fully working with proper workspace detection)
  • TypeScript/JavaScript: Via TypeScript Language Server
  • Rust: Via rust-analyzer
  • Java: Via Eclipse JDT.LS
  • C#: Via OmniSharp
  • Ruby: Via Solargraph
  • Dart: Via Dart Language Server
  • Kotlin: Via Kotlin Language Server

MultiLSP handles downloading and configuring these language servers automatically.

License

MIT License - see LICENSE file for details