MCP 语言服务器(TypeScript)
一个模型上下文协议(MCP)服务器,它封装了语言服务器协议(LSP)服务器,使大型语言模型(LLM)能够通过MCP访问语言服务器的功能。
概述
这个项目连接了两个重要的协议:
- LSP(语言服务器协议)提供对代码的语义理解(定义、引用、诊断等)
- MCP(模型上下文协议)使大型语言模型(LLMs)能够利用这些能力
通过将LSP服务器封装到MCP中,大型语言模型(LLMs)能够深入理解代码库的语义,从而更有效地导航、分析和重构代码。
建筑学
高层结构
src/
├── index.ts # Main entry point and MCP server setup
├── logging/ # Logging infrastructure
│ └── logger.ts # Component-based logging system
├── protocol/ # LSP protocol types
│ ├── types.ts # Type definitions and wrappers
│ └── uri.ts # URI utilities
├── lsp/ # LSP client implementation
│ ├── client.ts # LSP client and process management
│ ├── transport.ts # JSON-RPC message transport
│ └── methods.ts # LSP method wrappers
├── watcher/ # File system watching
│ ├── watcher.ts # Workspace file watcher
│ └── gitignore.ts # Gitignore pattern matching
└── tools/ # MCP tool implementations
├── utilities.ts # Shared utility functions
├── definition.ts # Get symbol definitions
├── references.ts # Find symbol references
├── hover.ts # Get hover information
├── diagnostics.ts # Get diagnostics (errors/warnings)
├── edit.ts # Apply text edits
└── rename.ts # Rename symbols组件详情
1. 日志系统(logging/)
目的提供结构化、基于组件的日志记录功能,且日志级别可配置。
关键特性:
- 基于组件的过滤(核心、LSP、Wire、LSP进程、监视器、工具)
- 可配置的日志级别(DEBUG、INFO、WARN、ERROR、FATAL)
- 环境变量配置(
LOG_LEVEL,LOG_COMPONENT_LEVELS,LOG_FILE)
示例:
const logger = createLogger(Component.LSP);
logger.debug('Processing request: %s', requestId);
logger.error('Failed to initialize: %s', err);2. 协议层(protocol/)
目的LSP协议的类型定义和实用工具。
组件:
types.ts重新导出VSCode的LSP类型并提供包装接口uri.tsURI 转换实用程序pathToUri,uriToPath)
关键抽象概念:
ISymbol统一的界面用于SymbolInformation并且WorkspaceSymbolSymbolKindNames符号种类的可读名称FileChangeType,WatchKind文件监视枚举
3. LSP客户端(lsp/)
目的管理与LSP服务器进程的通信。
组件:
transport.ts - JSON-RPC 消息传输
- 实现了LSP消息帧(Content-Length头部)
- 处理消息的序列化/反序列化
- 支持请求和通知
消息流:
Client Request → JSON-RPC → LSP Server
← Response ←client.ts - LSP客户端实现
- 生成并管理LSP服务器进程
- 处理三种类型的通信:
1. 客户端 → 服务器请求工具调用(定义、悬停等) 1. 服务器 → 客户端请求能力注册,工作区编辑 1. 服务器 → 客户端通知诊断,消息
关键方法:
initialize()使用工作区配置初始化LSP服务器openFile()打开文件以进行分析call()发送LSP请求(并接收响应)notify()发送LSP通知(无响应)registerServerRequestHandler()处理服务器发起的请求registerNotificationHandler()处理服务器通知
流程管理:
- 退出时自动清理进程
- 优雅关闭,带超时和回退强制终止
- 用于日志记录的标准错误输出捕获
methods.ts - LSP方法包装器
为常见的LSP(语言服务器协议)方法提供类型化的包装器:
symbol()工作区符号搜索references()查找所有引用hover()获取悬停信息rename()重命名符号definition()转到定义
4. 文件监视器(watcher/)
目的监控工作区文件,并与LSP服务器同步更改。
组件:
gitignore.ts - Gitignore 匹配
- 加载并解析
.gitignore文件 - 确定是否应忽略文件/目录
- 用途
ignore用于模式匹配的库
watcher.ts - 工作区监视器
职责:
- 文件系统监控用途
chokidar监视文件变化 - 模式匹配支持LSP通配符模式(
**/*.ts,*.{js,ts}) - 智能过滤不包括
node_modules,.git构建产物(或构建工件) - 去抖动(或消抖)减少通知垃圾信息
- 文件打开自动打开与注册模式匹配的文件
事件流:
File Change → Filter → Debounce → Notify LSP Server
→ Open/Close Files配置:
excludedDirs要跳过的目录(例如。,node_modules)excludedFileExtensions要忽略的文件类型(例如。,.pyc)maxFileSize跳过大型二进制文件debounceTime发送通知前的延迟
5. 工具(tools/)
目的实现MCP工具以展示LSP功能。
utilities.ts - 公用设施共享
addLineNumbers()带有行号的格式代码getFullDefinition()扩展定义以包含注释/正文getLineRangesToDisplay()计算上下文范围formatLinesWithRanges()以行范围格式化输出
工具实现
每种工具都遵循相似的模式:
- 解析并验证输入
- 在LSP中打开必要的文件
- 调用相应的语言服务提供者(LSP)方法
- 格式化结果以供显示
- 返回格式化文本
definition.ts - 符号定义查找
readDefinition(client, 'MyClass.myMethod')
→ Searches workspace symbols
→ Opens files containing matches
→ Expands definition range (includes comments)
→ Returns formatted code with location inforeferences.ts - 查找所有引用
findReferences(client, 'myFunction')
→ Finds symbol via workspace/symbol
→ Calls textDocument/references
→ Groups by file
→ Shows context around each referencehover.ts - 获取悬停信息
getHoverInfo(client, 'file.ts', 10, 5)
→ Calls textDocument/hover
→ Formats hover content (markdown/plaintext)
→ Returns type info and documentationdiagnostics.ts - 获取诊断信息
getDiagnosticsForFile(client, 'file.ts')
→ Opens file
→ Retrieves cached diagnostics
→ Groups by severity
→ Shows context around each diagnosticedit.ts - 应用文本编辑
applyTextEdits(client, 'file.ts', [
{ startLine: 10, endLine: 12, newText: 'new code' }
])
→ Opens file
→ Converts to LSP TextEdit format
→ Applies edits from bottom to top
→ Writes back to filesystemrename.ts - 重命名符号
renameSymbol(client, 'file.ts', 10, 5, 'newName')
→ Calls textDocument/rename
→ Receives WorkspaceEdit
→ Applies changes across all files
→ Returns summary of changes6. 主服务器(index.ts)
目的协调所有组件并提供MCP工具。
生命周期:
- 解析配置命令行参数(工作区,LSP 命令)
- 初始化LSP启动LSP服务器进程,发送初始化请求
- 启动监视器监控工作区文件
- 注册工具定义可用的MCP工具
- 启动MCP服务器在标准I/O上监听MCP请求
- 处理请求将路由工具调用转发到相应的处理程序
- 优雅地关闭关闭文件,关闭LSP(语言服务器协议),进行清理
配置选项:
mcp-language-server \
--workspace /path/to/project \
--lsp typescript-language-server \
-- --stdio--workspace项目目录--lspLSP服务器命令--此后的参数将传递给LSP服务器
数据流
工具调用流程
MCP Client (LLM)
↓ (stdio)
MCP Server (index.ts)
↓
Tool Handler (tools/definition.ts)
↓
LSP Client (lsp/client.ts)
↓ (JSON-RPC over stdio)
LSP Server Process (e.g., typescript-language-server)
↓
File System / Code Analysis
↑
Results flow back up the chain文件变更流程
File System Change
↓
chokidar (watcher.ts)
↓
Filter & Debounce
↓
LSP Client
↓ workspace/didChangeWatchedFiles
LSP Server
↓
Diagnostics Published
↓
Cached in LSP Client
↓
Available to Tools关键设计模式
1. 分层架构
- 传输层、协议层和工具层之间的清晰分离
- 每一层都有明确的职责
- 抽象使得测试和修改成为可能
2. 事件驱动通信
- LSP 使用双向 JSON-RPC
- 服务器可以向客户端发送请求/通知
- 为不同消息类型注册的处理程序
3. 资源管理
- 显式打开/关闭的文件
- 在关机时进行进程清理
- 基于超时的清理回退机制
4. 防抖与缓存
- 文件更改事件经过防抖处理以减少干扰
- 客户端缓存的诊断信息
- 文件打开状态已跟踪
5. 错误处理
- 错误与上下文一起传播
- 在适当级别进行日志记录
- 在可能的情况下实现优雅降级
配置
环境变量
LOG_LEVEL设置全局日志级别(DEBUG、INFO、WARN、ERROR、FATAL)LOG_COMPONENT_LEVELS设置各组件级别(例如。,lsp:DEBUG,tools:INFO)LOG_FILE除了标准错误输出外,将日志写入文件LSP_CONTEXT_LINES参考上下文的行数(默认:5)
示例:调试模式
export LOG_LEVEL=DEBUG
mcp-language-server --workspace . --lsp gopls测试
单元测试
关注各个单独组件:
- 日志配置
- URI转换
- 消息封装/解析
- 模式匹配
- 文本编辑应用程序
集成测试
测试端到端流程:
- LSP 初始化
- 文件打开/关闭
- 工具执行
- 工作区监视
扩展点
该代码库设计为可扩展性:
- 新工具添加文件到
tools/并在(某处)注册index.ts - 自定义过滤器修改监视器配置
- LSP方法添加包装器
lsp/methods.ts - 自定义日志记录添加新组件或日志接收器
与Go版本的比较
这个TypeScript实现与Go版本在架构上保持一致,同时充分利用了TypeScript/Node.js生态系统的优势:
| 方面 | Go 版本 | TypeScript 版本 |
|---|---|---|
| LSP 类型 | 由 gopls 生成 | VSCode LSP 类型 |
| 文件监视 | fsnotify | chokidar |
| Git忽略文件 | go-gitignore(Go语言项目忽略文件模板) | 忽略 |
| 并发性 | Go 协程(Goroutines)和通道(Channels) | 异步/等待(Async/await)和 Promise |
| 进程管理 | os/exec | child_process |
| MCP SDK | mcp-go | @modelcontextprotocol/sdk |
依赖项
@modelcontextprotocol/sdkMCP协议实现vscode-languageserver-protocolLSP类型定义chokidar文件系统监视器ignoreGitignore 模式匹配
构建与运行
# Install dependencies
npm install
# Build
npm run build
# Run
node dist/index.js --workspace /path/to/project --lsp typescript-language-server -- --stdio许可证
BSD-3条款(与原始Go实现相同)
