语言服务器协议模型上下文协议

LSP MCP是一个为LLMs/AI代理提供语言服务器协议(LSP)能力的服务器,使AI能够从代码库中获取语言感知的上下文。

作者 By jonrad
本地部署 语言服务器协议 AI代理
GitHub

LSP-MCP

一种模型上下文协议(MCP)服务器,为LLM/AI代理提供语言服务器协议(LSP)服务器的功能。这使AI能够从代码库中获取语言感知上下文。

  • LSP-MCP

  • 示例

  • 警告

  • 特性

  • 快速开始

  • 克劳德桌面

  • 使用Docker(推荐)

  • 使用npx

  • 光标

  • MCP CLI客户端

  • ABC(引言)

  • 什么是MCP?

  • 什么是LSP?

  • 发展

  • 依赖项

  • 决策

  • 路线图

  • 参考文献

示例

输入:

1
2
3
4
5
6
7
8Use lsp to give me insights into the following typescript code:
let foo = "bar";
function x() {
  let foo = 123;
  console.log(foo);
}
x();
console.log(foo);

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17I'll use LSP (Language Server Protocol) to analyze your TypeScript code. Let me break down what's happening:
Here's what the code does and the insights from LSP analysis:
1. Variable Shadowing:
There are two variables named foo:
A global foo (string type) initialized with the value "bar"
A local foo (number type) inside the function x() initialized with the value 123
2. Execution Flow:
First, the global foo is declared and assigned the value "bar"
When function x() is called, the local foo variable is declared and assigned 123
The console.log(foo) inside the function outputs 123 (the local variable)
After the function finishes, console.log(foo) outputs "bar" (the global variable)
3. Scope Isolation:
The LSP confirms that TypeScript correctly identifies the different types:
The global foo is a string type
The local foo inside the function is a number type
Changes to the local foo don't affect the global foo
This is a classic example of variable shadowing in JavaScript/TypeScript, where a local variable with the same name as a global variable takes precedence within its scope.

警告

这处于POC状态。

特性

  • 同时支持多个LSP(多种编程语言),请参阅 示例配置
  • 从LSP JSON模式动态生成支持的LSP方法,请参阅 json模式

快速开始

克劳德桌面

使用Docker(推荐)

修改 claude_desktop_config.json (如所述 MCP文件)具有以下内容:

JSON``` 1 2 3 4 5 6 7 8{ “mcpServers”: { “lsp”: { “command”: “docker”, “args”: [“run”, “-i”, “—rm”, “docker.io/jonrad/lsp-mcp:0.3.1”] } } }


您可能希望通过传递docker与容器共享一些文件 `-v /local_dir:/remote_dir`。然后,你可以向克劳德询问中的文件 `/remote_dir/<filename>`.


#### 使用npx


注意:Claude Desktop似乎对npx很挑剔。有时它说mcp失败了,但工具仍然有效。我会调查一下。…稍后😊


JSON```
1
2
3
4
5
6
7
8{
  "mcpServers": {
    "lsp": {
      "command": "npx",
      "args": ["-y", "--silent", "git+https://github.com/jonrad/lsp-mcp", "--lsp", "npx -y --silent -p 'typescript@5.7.3' -p 'typescript-language-server@4.3.3' typescript-language-server --stdio"]
    }
  }
}

这将为Claude提供打字语言服务器的LSP功能。您可以通过切换来修改语言服务器 --lsp 争论(然后重新启动克劳德)。

尚不支持同时使用多个LSP。

光标

按照说明 由Cursor提供。对于设置,请选择 Type = commandCommand = docker run ... 正如上文为克劳德所述(例如 docker run -i --rm -v <LOCAL_DIR>:<REMOTE_DIR> jonrad/lsp-mcp:<version>)

MCP CLI客户端

按照Claude的说明进行操作,但配置文件位于 ~/.llm/config.json

ABC(引言)

什么是MCP?

什么是LSP?

发展

BASH``` 1 2 3yarn yarn mcp-cli # Interactive MCP tool to help with development yarn dev —help # Get the CLI help


### 依赖项


### 决策


- 使用python-我想利用一个客户端库,使启动变得简单。节点中创建了许多LSP,但成熟的客户端库似乎依赖于vscode。我喜欢它的外观 [multilspy](https://github.com/microsoft/multilspy),所以我们从python开始。我已经创建了一个python MCP,这对我很有帮助,所以至少我在那里有一条腿
- [紫外线](https://docs.astral.sh/uv/) 用于包管理等-我最近看到这个用法越来越频繁,这是学习它的借口。将来切换包管理器很烦人,但可行。一旦实施了CI/CD,我可能不得不重新审视这个决定。也许我可以使用它,而不是依赖 [任务文件](https://taskfile.dev/) 也?TBD
- 尽可能异步-现在是2025年
- 毕竟切换到节点。使用python的POC比我预期的更成功。但是,multilspy并不支持整个LSP规范,vscode的库将更容易使用,因为node可以说是LSP服务器/客户端的事实标准语言。
- 使用低级MCP SDK。我认为我需要更多的控制,坦率地说,与更高级别的FastMCP相比,它并没有那么复杂。
- 使用 [动物圈](https://zod.dev/) 用于配置验证。它已经是MCP SDK的依赖项,所以没有理由过度考虑它。
- 我设置为始终使用LSP,即使对于未知语言也是如此(例如,LLM为python提供了textDocument/documentSymbol请求,但没有注册python LSP)。我可能会重新考虑这个决定。
- 决定只有在被问到问题时才启动LSP。可以稍后进行配置,但目前这可以防止资源的过度使用。


### 路线图


这只是我最终想做的事情的清单。这些没有时间表或顺序。


- 弄清楚如何在LSP客户端(this)和LSP服务器之间同步功能
- 自动生成LSP JSON模式或查找其发布位置
- 将json模式设置为cli参数,这样我们就没有更新代码来支持新的模式
- 连接到已运行的LSP服务器(通过多路复用LSP服务器?)
- 切换到(任务文件)[[https://taskfile.dev/\](https://taskfile.dev/%5C)]
- 创建适当的发布流程


## 参考文献


- [生成的LSP JSON模式](https://gist.github.com/bollwyvl/7a128978b8ae89ab02bbd5b84d07a4b7#file-generated-protocol-schema-json)