mazdak/mcp-lsp-proxy
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
- Python 3.11+ - Required for the proxy server
- Go (optional) - If you want to use Go language features
- 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
- Create a configuration file:
mcp-lsp-proxy --init
- 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 languagelanguages
: 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
-
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
- macOS:
-
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"
}
}
}
}
-
Restart Claude Desktop to load the new configuration.
-
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:
-
Using the CLI wizard:
claude mcp add
-
Adding directly via command:
claude mcp add-json lsp-proxy '{"command":"mcp-lsp-proxy","args":["--config","/path/to/mcp-lsp-config.toml"]}'
-
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" } } } }
-
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
-
Check server is running:
mcp-lsp-proxy --config your-config.toml
You should see:
MCP-LSP Proxy (MultiLSP) started
-
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
- For Go:
-
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 URIline
: 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 URIline
: 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 URIline
: 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 stringworkspace
: 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:
- Automatic Language Server Management - MultiLSP downloads and manages language servers automatically
- Unified API - Same interface for all languages (Python, Go, TypeScript, Rust, etc.)
- Battle-tested - Used by Microsoft for AI coding scenarios
- Simplified Configuration - No need to specify LSP server commands or installation paths
- Better Error Handling - Clear error messages when dependencies are missing
Core Components
-
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
-
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
-
MultiLSP Integration - Leverages Microsoft's library
- Handles all LSP protocol communication
- Manages language server subprocesses
- Provides unified async API
-
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:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- 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
- File URIs: Always use proper file URIs (e.g.,
file:///absolute/path/to/file.py
) - 0-indexed positions: Line and character positions are 0-indexed, matching LSP specification
- Multiple LSPs: You can configure multiple LSP servers for the same language; the proxy will use the last one defined
- Workspace folders: Configure workspace folders in the TOML for project-aware features
- 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