1. Cursor中的MCP工具概述
Cursor作为一款智能编程助手,内置了强大的MCP(Model Context Protocol)工具支持系统。MCP是一种协议规范,允许Cursor与外部服务进行标准化交互。理解Cursor中的MCP工具体系对于充分发挥其潜力至关重要。
1.1 Cursor工具的分类
Cursor中的工具主要分为两大类:
内置工具:Cursor自带的50-70个功能工具(数量会随版本更新变化),这些工具直接集成在Cursor中,无需额外配置即可使用。典型的内置工具包括:
- 代码搜索与导航(如查找函数定义)
- 文档查询
- 单位换算等实用功能
自定义MCP Server工具:通过配置
mcpServers添加的外部工具,这些工具运行在独立进程中,Cursor通过MCP协议与它们通信。这类工具完全由用户自定义,可以实现各种特定需求。
重要提示:内置工具和MCP Server工具是两条平行的能力线,只有LLM(大语言模型)能看到全部工具。Cursor内部会根据情况调用不同的实现,如果提示词不够精确,可能会出现Cursor调用自己的工具而没有调用到你自定义工具的情况。
1.2 MCP学习资源
对于想要深入理解MCP协议的开发者,可以参考以下资源:
- MCP官方文档
- GitHub上的 servers仓库 ,包含多种MCP服务器实现
- 记住Cursor只是众多MCP客户端中的一个
2. 自定义MCP Server配置详解
2.1 添加MCP Server的位置
在Cursor中添加自定义MCP Server非常简单:
- 打开Cursor设置
- 导航到"Tools & MCP"部分
- 点击"New Mcp Server"进行添加
添加后,所有配置的MCP Server都会显示在工具列表中,方便管理和调用。
2.2 MCP Server配置结构
mcpServers配置的本质是"进程启动描述"(Process Spec),它定义了如何启动一个MCP Server进程并通过stdio与之通信。其通用JSON结构如下:
{ "mcpServers": { "<server-id>": { "command": "<executable>", "args": ["<arg1>", "<arg2>", ...], "env": {"<key>": "<value>"} } } }这个结构在各种编程语言(Java/Python/Node.js/Go等)中都是通用的。下面是一个实际的配置示例:
{ "mcpServers": { "memory": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-memory"], "env": {"MEMORY_FILE_PATH": "C:\\Users\\wtyy\\.mcp-storage\\memory.json"} }, "playwright": { "command": "npx", "args": ["-y", "@playwright/mcp@latest", "--browser", "chrome"] }, "gitlab": { "command": "npx", "args": ["-y", "@zereight/mcp-gitlab"], "env": { "GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-******", "GITLAB_API_URL": "https://git.wtyy.com" } } } }2.3 配置项详解
2.3.1 server-id(逻辑标识)
- 语义:MCP Server的逻辑ID,用于Cursor内部管理和UI显示
- 规则:
- 可以是任意字符串
- 推荐使用kebab-case命名(如user-service)
- 不参与MCP协议通信,不会传给Server
2.3.2 command(进程入口)
- 语义:启动MCP Server的可执行文件
- 规则:
- 必须是一个单独的可执行文件
- 不能包含参数(参数必须放在args数组中)
- 示例:
"command": "java" "command": "python3" "command": "node" "command": "npx"
2.3.3 args(进程参数)
- 语义:传递给command的参数数组
- 规则:
- 必须是数组格式
- 每个元素是一个独立参数
- 顺序会被严格保留
- Cursor不会做任何拼接或转义
- 示例:
"args": ["-jar", "/path/to/server.jar"] "args": ["server.py"] "args": ["--mcp"]
2.3.4 env(环境变量)
- 语义:启动MCP Server时注入的环境变量
- 规则:
- 可选配置
- Key和Value都必须是字符串
- 会与系统环境变量合并
- 如果与系统环境变量冲突,会覆盖系统值
- 示例:
"env": { "LOG_LEVEL": "debug", "SPRING_PROFILES_ACTIVE": "prod" }
3. MCP Server实现规范
3.1 必须实现的接口
一个可被Cursor正常使用的自定义MCP Server,最少需要实现以下3个接口:
3.1.1 initialize(初始化/握手)
这是Cursor启动MCP Server后的第一次通信,用于确认协议支持和Server能力。
请求示例(Cursor → MCP Server):
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "clientInfo": { "name": "cursor", "version": "x.y.z" } } }响应示例(MCP Server → Cursor):
{ "jsonrpc": "2.0", "id": 1, "result": { "capabilities": { "tools": {} } } }注意:如果不返回
capabilities.tools,Cursor会认为该Server不支持任何工具。
3.1.2 tools/list(工具列表)
Cursor和LLM用这个接口来构建工具上下文,决定何时调用哪个工具。
请求示例:
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }响应示例:
{ "jsonrpc": "2.0", "id": 2, "result": { "tools": [ { "name": "get_user_by_id", "description": "根据用户id查询用户信息(name、email、age)", "inputSchema": { "type": "object", "properties": { "id": { "type": "integer", "description": "用户唯一ID" } }, "required": ["id"] } } ] } }关键点:
description和inputSchema非常重要,这是LLM判断是否要调用该工具的核心依据。
3.1.3 tools/call(工具调用)
这是实际执行业务逻辑的接口。
请求示例:
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "get_user_by_id", "arguments": { "id": 123 } } }响应示例:
{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "json", "json": { "id": 123, "name": "Alice", "email": "alice@example.com", "age": 28 } } ] } }3.1.4 shutdown(优雅关闭,可选)
Cursor关闭或重新加载时会调用此接口,让Server有机会释放资源。
请求示例:
{ "jsonrpc": "2.0", "method": "shutdown" }3.2 MCP Server运行时行为规则
3.2.1 通信模型
- 只支持stdio(标准输入/输出)通信
- 不支持socket/http/grpc等其他通信方式
- Server不需要监听任何端口
3.2.2 生命周期管理
- Cursor负责启动Server进程
- Server应该是常驻进程
- 一个Server对应一个独立进程
- Cursor退出时,所有关联的Server进程也会被终止
3.2.3 输出规则
| 输出流 | 允许内容 |
|---|---|
| stdout | 仅MCP JSON-RPC消息 |
| stderr | 任意日志信息 |
重要:如果违反此规则,Server会被Cursor判定为异常状态。
3.2.4 JSON-RPC规则
- 一行一个JSON消息
- 必须使用UTF-8编码
- 每条消息后必须flush
- Cursor不支持chunked或streaming传输
4. Cursor与MCP Server的交互流程
4.1 完整调用链
- 用户在Cursor输入自然语言指令
- Cursor将上下文和MCP工具描述发送给LLM
- LLM决定是否要调用某个MCP工具
- Cursor解析LLM的工具调用意图
- Cursor作为MCP Host调用对应的MCP Server
- MCP Server执行工具逻辑(你的代码)
- 结果通过MCP协议返回给Cursor
- Cursor把结果交给LLM
- LLM生成最终回复给用户
4.2 详细交互示例
4.2.1 Cursor启动MCP Server
根据配置启动对应的进程,例如:
{ "mcpServers": { "user-service": { "command": "java", "args": ["-jar", "/path/user-mcp-server.jar"] } } }4.2.2 初始化握手(initialize)
Cursor → MCP Server:
{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "clientInfo": { "name": "cursor", "version": "x.y.z" } } }MCP Server → Cursor:
{ "jsonrpc": "2.0", "id": 1, "result": { "capabilities": { "tools": {} } } }4.2.3 获取工具列表(tools/list)
Cursor → MCP Server:
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }MCP Server → Cursor:
{ "tools": [ { "name": "get_user_by_id", "description": "根据id查询用户", "inputSchema": { "type": "object", "properties": { "id": { "type": "integer" } }, "required": ["id"] } } ] }4.2.4 实际工具调用(tools/call)
Cursor → MCP Server:
{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "get_user_by_id", "arguments": { "id": 123 } } }MCP Server → Cursor:
{ "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "json", "json": { "id": 123, "name": "Alice", "email": "alice@example.com", "age": 28 } } ] } }4.3 工具匹配机制
Cursor会把所有可用工具(包括内置工具和自定义MCP工具)交给LLM,每个工具都有完整的描述信息:
{ "name": "get_user_by_id", "description": "根据用户id查询用户信息", "inputSchema": { "type": "object", "properties": { "id": { "type": "integer" } }, "required": ["id"] } }LLM会根据以下因素决定调用哪个工具:
- 用户输入的自然语言描述
- 工具的名称和描述
- 输入参数的结构
- 工具的历史调用情况
提示:如果配置了很多MCP Server且工具名称相似,可以在提示词中明确指定要调用的工具名称,如"调用get_git_mr_diffs mcp,分析这个MR的改动"。
5. MCP Prompts与MCP Tools的区别
5.1 基本概念
虽然名称相似,但MCP Prompts和MCP Tools是两个不同的概念:
- MCP Tools:通过MCP协议注册的基础工具,不能被手动调用,只能由Cursor自动调用
- MCP Prompts:通过MCP协议注册的高级命令,可以被手动调用(通过/执行),内部会使用MCP Tools完成工作
5.2 类比说明
用餐厅比喻更容易理解:
- MCP= 餐厅的运营系统(协议/基础设施)
- 定义了如何点餐、如何上菜、如何结账等规范
- MCP Tools= 具体的服务(工具)
- 点餐服务、做菜服务、结账服务
- MCP Prompts= 套餐菜单(高级命令)
- "套餐A" = 点餐 + 做菜 + 上菜 + 结账(完整流程)
- 用户只需要说"我要套餐A",系统自动完成所有步骤
5.3 实际示例
当用户输入/wtyy/review-java-code时:
- MCP Prompt被识别为一个高级命令
- 命令内部指导AI使用相关的MCP Tools
- AI通过MCP协议调用工具
- 工具返回结果,命令整合并输出最终响应
5.4 创建MCP Prompts
创建MCP Prompts通常需要:
- 定义清晰的命令名称和描述
- 设计完整的执行流程
- 确定需要使用哪些MCP Tools
- 实现结果整合逻辑
- 在Cursor中注册该Prompt
6. 最佳实践与常见问题
6.1 工具设计建议
命名规范:
- 使用清晰、具体的工具名称
- 避免与内置工具名称冲突
- 考虑使用前缀区分不同领域的工具
描述优化:
- 描述要准确反映工具功能
- 包含关键使用场景和限制
- 使用自然语言,方便LLM理解
参数设计:
- 参数命名要有意义
- 提供详细的参数描述
- 明确标记必填参数
6.2 常见问题排查
工具未被调用:
- 检查工具描述是否清晰
- 确认输入参数schema定义正确
- 验证initialize响应中包含tools能力
通信失败:
- 确认只通过stdio通信
- 检查JSON格式是否符合规范
- 验证每条消息后是否执行了flush
性能问题:
- 避免在工具调用中执行长时间操作
- 考虑实现缓存机制
- 对于复杂操作,可以提供进度反馈
6.3 调试技巧
日志记录:
- 将调试信息输出到stderr
- 记录完整的请求和响应
- 包含时间戳和关键状态信息
测试工具:
- 开发独立的测试客户端
- 模拟Cursor的调用流程
- 验证各种边界条件
版本控制:
- 为工具接口维护版本号
- 提供向后兼容性
- 记录变更历史
7. 高级主题:工具发现与上下文管理
Cursor与LLM之间传递MCP工具信息的方式不是简单的"每次原样带过去",而是通过一套精细的会话管理机制:
7.1 两层机制
会话级能力注入:
- Cursor在当前会话中注入可用工具列表
- 包括工具名、参数结构、约束条件等
- 让模型知道能调用哪些工具及如何传参
按需读取:
- 对MCP工具,通常会先读取工具描述符
- 然后按schema调用具体工具
- 这使得工具是"可发现、可验证参数"的
7.2 会话管理
- 同一会话内:上下文连续,模型知道之前调用过什么工具、当前页面状态等
- 新会话/新对话:不会自动继承上个会话的完整状态,需要Cursor重新注入可用工具与上下文
7.3 性能优化
懒加载:
- 不是所有工具都在会话开始时加载
- 根据上下文预测可能需要的工具
- 动态注入相关工具描述
缓存机制:
- 缓存常用工具的描述信息
- 减少重复传输的数据量
- 基于工具版本号实现智能更新
增量更新:
- 只传输变化的工具信息
- 减少网络传输开销
- 提高响应速度
在实际开发MCP工具时,理解这些底层机制有助于设计出更高效、更可靠的集成方案。通过遵循MCP协议规范并结合Cursor的特性,开发者可以构建强大的自定义工具,显著提升开发效率和体验。