Skip to content

功能规格说明:MCP 支持 ​

规格文件:docs/specs/ecosystem/mcp.md创建日期:2026-01-21

用户场景与测试 (必填) ​

用户故事:通过 MCP 使用外部工具(优先级:P1) ​

作为开发者,我希望将代理连接到外部 MCP 服务器,以便使用代理未内置的专用工具(如天气、数据库访问或自定义脚本)。

优先级原因:这是 MCP 支持的核心功能,实现可扩展性。

独立测试:连接到简单的 MCP 服务器(例如 "hello world" 服务器)并验证代理可以列出和调用其工具。

验收场景:

  1. 假设 有有效的 .mcp.json 配置,当 代理启动时,则 它必须尝试连接到定义的 MCP 服务器。
  2. 假设 MCP 服务器已连接且工具池未收敛,当 代理列出工具时,则 它必须包含带有 mcp__ 前缀的 MCP 工具。
  3. 假设 MCP 服务器已连接且工具池收敛已生效(池非空且 Exec 可声明,见 docs/specs/core/exec-tool.md),当 代理列出工具时,则 逐条扁平声明让位于 Exec 的目录——撤下的只是"声明"形态,工具本身照常可调用。
  4. 假设 AI 决定调用 MCP 工具,当 工具执行时,则 请求必须发送到正确的 MCP 服务器并将结果返回给 AI。
  5. 假设 AI 在 Exec 脚本里嵌套调用 MCP 工具,当 该调用执行时,则 请求必须同样发送到正确的 MCP 服务器、结果回到脚本(与扁平调用共用同一执行漏斗与权限检查)。

用户故事:把服务器自带的使用说明播报给模型(优先级:P2) ​

作为用户,我希望 MCP 服务器通过 initialize 自述的使用说明(instructions)在它变为可用的那一刻播报一次,这样"限流是多少、调用前要满足什么前提、整个服务器怎么用"这类不调用也要知道的内容不会丢失,同时服务器在会话中途连接时也不会让已经缓存的前缀失效。

优先级原因:这是上下文保真度而非工具能力。工具描述是可以被目录压缩的(模型要看原文得先搜索命中,见 docs/specs/core/exec-tool.md),而服务器级的使用约束一旦被压缩掉,模型就不知道自己在违反什么限制。另一面是缓存:这份内容只在"连接发生"时才有变化,若逐轮重算进系统提示,一次中途连接就会改写整个已缓存前缀(见 docs/specs/core/prompt-cache-control.md 边界情况 10);作为消息追加在尾部则不改写任何已有前缀。

独立测试:连接一个在 initialize 响应里返回多行 instructions 的 MCP 服务器,断言对话历史里出现了这段原文并标明来源服务器,且随后几轮不再重复出现;断开后断言只播报一次"已下线";服务器文本超过上限时断言被截断并标明。

验收场景:

  1. 假设 某 MCP 服务器在 initialize 响应里返回了 instructions,当 连接成功时,则 McpManager 必须保存这段文本,不得丢弃。
  2. 假设 某服务器带有 instructions 且尚未播报过,当 它变为可用(连接成功,或 reconnecting 且保留上次工具快照),则 必须在该轮 API 调用之前追加一条持久化的系统提示消息(isMeta,对 UI 隐藏),内容包含该服务器原文并标明来源服务器(多台服务器时彼此可区分)。
  3. 假设 instructions 是多行文本,当 播报时,则 必须原样保留(含换行),不得按宽度裁剪、也不得只保留首行;但 单台服务器的文本超过 2048 个字符时,则 必须截断到该上限并在末尾标明已被截断,不得静默丢弃。
  4. 假设 某服务器的工具被权限规则全部排除,当 计算本轮可播报集合时,则 不得播报该服务器的 instructions(说明与工具同源,不能让被拒服务器的内容绕过规则进入上下文);服务器一个工具都没有时照常播报。规则是在播报之后才收紧时,已播报的原文按"历史不改写"留在历史里,但不得再次播报。
  5. 假设 一台已播报过的服务器断开、连接失败或转为 error,当 后续轮次计算可播报集合时,则 必须播报一次"该服务器已下线、上述说明不再适用",此后不得再次播报它;不得声称会把它已经播报过的原文从历史里删除(历史不改写),也不得因此重算系统提示。
  6. 假设 本轮既没有新增也没有下线的服务器,当 计算可播报集合时,则 不得追加任何消息(无内容 = 不输出空消息、空段落或只有标题的空章节)。
  7. 假设 工具池已收敛、MCP 工具不再逐条扁平声明,当 服务器播报说明时,则 说明仍必须出现——它是服务器级上下文,不随工具声明形态变化。
  8. 假设 同一台服务器已经播报过且仍然可用、原文未变,当 后续每一轮到达时,则 不得重复播报(播报状态以对话历史中的标记为唯一真源,不另设进程内状态)。
  9. 假设 对话历史因压缩或回退导致播报标记不再存在,当 该服务器仍带 instructions 可用时,则 下一轮必须重新播报(宁可重复,不可丢失)。
  10. 假设 服务器断开后重新连上,当 它再次变为可用时,则 必须再播报一次它的 instructions(第一次播报已被"下线"公告作废,重复优于丢失)。
  11. 假设 会话中途有服务器连接或断开,当 对照前后两轮的系统提示文本时,则 系统提示(静态块与动态块)文本不得因 instructions 的来去而变化——工具声明随连接变化属既有行为(见 docs/specs/core/prompt-cache-control.md 边界情况 9)。

用户故事:管理 MCP 服务器生命周期(优先级:P2) ​

作为用户,我希望手动连接或断开 MCP 服务器并检查其状态,以便排查连接问题或管理资源。

优先级原因:提供对外部依赖的必要控制和可见性。

独立测试:使用 agent.getMcpServers() 检查状态并使用 agent.connectMcpServer() 重新连接失败的服务器。

验收场景:

  1. 假设 MCP 服务器已配置,当 调用 getMcpServers() 时,则 它必须返回当前状态(已连接、错误等)。
  2. 假设 服务器已断开,当 调用 connectMcpServer() 时,则 它必须尝试重新建立连接。

用户故事:通过 Agent 构造函数传递 MCP 服务器(优先级:P2) ​

作为集成 SDK 的开发者,我希望直接将 MCP 服务器配置传递给 Agent 构造函数,以便以编程方式配置服务器而不依赖 .mcp.json 文件。

优先级原因:为 SDK 使用者启用编程式 MCP 配置。

独立测试:在选项中带有 mcpServers 创建 Agent 并验证服务器在没有 .mcp.json 文件的情况下连接。

验收场景:

  1. 假设 mcpServers 传递给 Agent.create(),当 代理初始化时,则 这些服务器必须自动注册和连接。
  2. 假设 构造函数的 mcpServers 和 .mcp.json 文件同时存在,当 代理加载配置时,则 构造函数提供的服务器对于重复名称必须具有优先权。

用户故事:IDE 插件 MCP 管理对话框(优先级:P2) ​

作为 IDE 插件用户,我希望通过 /mcp 打开 MCP 管理界面,查看各服务器的连接状态并手动连接或断开,以便在不切换到 CLI 的情况下排查连接问题。

优先级原因:IDE 插件用户无法使用 CLI 的 MCP 管理界面,需要在插件内获得同等的状态可见性与基本控制能力;但属于辅助管理功能,非核心对话流程。2026-08-29 用户拍板:/mcp 从独立对话框改为唤起设置页并选中「MCP 服务」选项卡(与 /agents、/skills 一致)。

独立测试:在 IDE 中输入 /mcp,验证打开设置页并选中「MCP 服务」选项卡,列表列出服务器及其状态;对已断开的服务器点击连接,观察状态变为已连接;对已连接的服务器点击断开,观察状态变为未连接。

验收场景:

  1. 假设 用户处于 IDE 中(VS Code 扩展 / JetBrains 插件 / 桌面端),当 用户输入 /mcp 并发送,则 打开设置页并选中「MCP 服务」选项卡(桌面端打开全页设置,IDE 打开编辑器区域设置标签页),不再弹出独立对话框。
  2. 假设 设置页「MCP 服务」选项卡已打开,则 列表显示每个服务器的名称、来源(用户级 / 项目级)、连接状态(已连接/连接中/重连中/错误/未连接,以不同颜色标识)、工具数量,以及上次连接时间。
  3. 假设 某服务器处于错误状态,当 列表渲染时,则 该服务器额外显示红色错误原因,且操作按钮显示为"重连"。
  4. 假设 用户点击某服务器的"连接"或"断开",当 操作进行中时,则 按钮显示进行中文案("连接中..."/"断开中...")并禁用,完成后状态刷新——断开操作必须有确定结果:即使进程无法干净退出、teardown 抛错或连接条目已缺失,host 也要回写最新服务器列表(或失败提示),按钮不得无限停留在"断开中..."。
  5. 假设 服务器状态在后台发生变化(如自动重连),当 列表打开时,则 列表实时刷新为最新状态。
  6. 假设 用户未配置任何 MCP 服务器,当 打开列表时,则 显示空状态引导文案,提示创建用户级或项目级 MCP 服务。
  7. 假设 设置页已打开,当 用户点击「返回」或切换其他选项卡,则 回到会话视图或切换到对应选项卡,设置页不产生任何消息。

用户故事:按来源 Tab 展示 MCP 服务(优先级:P1) ​

作为 GUI 用户,我希望设置页「MCP 服务」选项卡按来源以 Tab 形式展示 MCP 服务(用户级 / 项目级 / 插件),其中项目级在「项目级 MCP」Tab 下平铺展示(仅当前项目,不做多项目分组),以便快速定位某个来源下的 MCP 服务,并知道它属于哪一类(用户 / 项目 / 插件)。

为什么是这个优先级:MCP 服务来源决定其适用范围(用户级全局可用 / 项目级仅当前项目),Tab 化让长列表可扫读,与技能页形态统一(2026-08-29 用户拍板:MCP 区分用户级和项目级,用户级配置存 ~/.wave/mcp.json,项目级仍用项目根 .mcp.json;2026-09-01 用户拍板:设置页只针对当前项目,删除项目分组卡片,项目 Tab 直接平铺)。

独立测试:在具备用户级、项目级、插件 MCP 服务的环境中打开设置页 MCP 服务选项卡,验证来源 Tab 存在、项目级服务在「项目级 MCP」Tab 平铺列出并可执行管理操作。

验收场景:

  1. 假设 环境中存在用户级、项目级、插件来源的 MCP 服务,当 MCP 服务选项卡打开,则 顶部展示来源 Tab(用户级 MCP / 项目级 MCP / 插件 MCP),点击切换显示对应来源的服务
  2. 假设 存在项目级 MCP 服务,当 用户位于「项目级 MCP」Tab,则 服务平铺展示(不按项目分组、无项目卡片)
  3. 假设 项目 Tab 下存在多个 MCP 服务,当 列表展示,则 列出所有服务(名称、类型、命令或 URL、连接状态),并提供「编辑」「删除」操作入口
  4. 假设 用户级 MCP 配置存在,当 用户位于「用户级 MCP」Tab,则 列出 ~/.wave/mcp.json 中定义的所有服务
  5. 假设 某来源没有任何 MCP 服务,当 切换到该来源 Tab,则 显示空状态提示,不渲染空白分组

用户故事:新建 MCP 服务(优先级:P1) ​

作为 GUI 用户,我希望在 MCP 服务页点击「新增 MCP 服务」后打开 AI 对话框并预填一条新建提示词,通过自然语言描述即可创建 MCP 服务;配置文件不存在时由 AI 直接创建,已存在时也交由 AI 更新——「新增」一律只预填提示词、不打开文件(与技能 / 子代理 / 钩子的新建一致)。

为什么是这个优先级:手写 MCP 配置 JSON 门槛高;由 AI 根据自然语言生成配置是用户需求的核心(2026-08-29 用户需求:区分用户级和项目级,没有 .mcp.json 时跳转 AI 对话框通过提示词创建;2026-09-10 用户拍板:打开文件只发生在「编辑」,新增沿用技能 / 子代理 / 钩子的「只预填」语义)。

独立测试:在 MCP 服务页点击「新增」,验证 AI 对话框打开并预填提示词;补充描述发送后配置被写入(用户级 ~/.wave/mcp.json 或项目级 .mcp.json);返回 MCP 服务页验证新服务出现在对应来源分组。

验收场景:

  1. 假设 用户在 MCP 服务页「用户级 MCP」Tab,当 用户点击「新增用户级 MCP 服务」,则 关闭设置页回到会话视图,AI 对话框打开并预填用户级提示词,如 /settings 帮我配个用户级 MCP 服务器<名字>:连<command/url>,参数<args>
  2. 假设 用户在「项目级 MCP」Tab 点击「新增」,当 输入框预填,则 预填项目级提示词并带上项目名,如 /settings 帮我在【项目名称】下配 MCP 服务器<名字>:连<command/url>,参数<args>
  3. 假设 对应配置文件(~/.wave/mcp.json 或项目 .mcp.json)尚不存在,当 用户补充描述后发送,则 由 AI 创建配置文件并写入新服务,不额外打开文件
  4. 假设 对应配置文件已存在,当 用户点击「新增」,则 仍只预填提示词、不打开文件(打开文件仅发生在「编辑」;用户可在会话中让 AI 展示当前配置)
  5. 假设 MCP 服务创建成功,当 用户重新打开 MCP 服务页或列表刷新,则 新服务出现在对应来源分组(Tab)中,并带来源标识(用户 / 项目 / 插件)

用户故事:编辑 MCP 服务(优先级:P2) ​

作为 GUI 用户,我希望在 MCP 服务页点击「编辑」后打开 AI 对话框并预填一条编辑提示词,同时打开对应配置文件,以便基于当前内容描述修改点,由 AI 更新 MCP 服务配置。

为什么是这个优先级:MCP 配置修改通过 AI 自然语言描述更顺畅;同时打开配置文件让用户与 AI 都能直接看到/编辑实际 JSON(2026-08-29 用户需求:编辑跳转 AI 对话框提示词,并打开 .mcp.json 文件)。

独立测试:在 MCP 服务页点击某服务的「编辑」,验证 AI 对话框打开并预填编辑提示词、对应配置文件在编辑器打开;描述修改点并发送后配置文件被更新;返回 MCP 服务页验证服务配置已更新。

验收场景:

  1. 假设 用户在 MCP 服务页某服务条目上,当 用户点击「编辑」,则 关闭设置页回到会话视图,AI 对话框打开并预填编辑提示词,如 帮我编辑 MCP 服务器<名字>:把<要改的内容>改成<新内容>
  2. 假设 用户点击「编辑」,则 该服务所在配置文件(~/.wave/mcp.json 或项目 .mcp.json)同时打开便于对照修改(桌面端在会话视图右侧文件面板打开该文件,即消息中 read/edit/write 工具路径点击同款只读面板;IDE 在 VS Code / JetBrains 自身编辑器打开标签页);该路径由宿主解析为绝对路径后随 mcpConfigPathsResponse 下发,webview 不自造 ~ / 相对路径——宿主按 OS 绝对路径打开文件、无法展开 ~
  3. 假设 编辑提示词已预填,当 用户补充具体修改点后发送,则 消息以普通用户消息发送,由 AI 更新配置文件
  4. 假设 MCP 服务修改成功,当 用户重新打开 MCP 服务页或列表刷新,则 服务配置反映修改后的内容

用户故事:删除 MCP 服务(优先级:P1) ​

作为 GUI 用户,我希望在 MCP 服务页对用户级 / 项目级 MCP 服务执行「删除」时先出现二次确认,确认后服务配置从对应配置文件中移除并从列表删除,以便清理不再使用的 MCP 服务。

为什么是这个优先级:删除配置不可逆,需要确认;用户需求明确「二次确认后可删」且删除不依赖 AI(2026-08-29 用户拍板:确认框 + 直接删除配置)。

独立测试:在 MCP 服务页点击某服务「删除」,验证出现确认对话框;确认后服务配置从配置文件中移除、列表删除该服务;取消则无任何变化。

验收场景:

  1. 假设 用户在 MCP 服务页某用户级 / 项目级服务条目上,当 用户点击「删除」,则 弹出二次确认对话框,说明将删除的服务名及其配置文件路径
  2. 假设 确认对话框已显示,当 用户点击「取消」或关闭对话框,则 不执行删除,服务保持原样
  3. 假设 确认对话框已显示,当 用户点击「确认删除」,则 服务配置从对应配置文件(~/.wave/mcp.json 或项目 .mcp.json)中移除,列表删除该服务,不经过 AI
  4. 假设 删除成功,当 用户重新打开 MCP 服务页或列表刷新,则 该服务不再出现在任何来源分组中
  5. 假设 服务由插件提供,当 列表展示,则 不提供「删除」入口(只读来源不可删除)

用户故事:用户级 MCP 配置(优先级:P2) ​

作为用户,我希望在 ~/.wave/mcp.json 中配置常用的 MCP 服务器,以便这些服务器对所有项目可用,无需在每个项目根目录重复配置。

优先级原因:用户级配置是常见 MCP 服务器(数据库、代码搜索等)的复用基础,也是设置页 MCP 视图「用户级/项目级」双 tab 的数据支撑(2026-08-31 用户拍板:先支持用户级 MCP 配置,再实现 MCP 设置视图)。

独立测试:在 ~/.wave/mcp.json 配置一个服务器并在无项目 .mcp.json 的新目录启动代理,验证服务器自动注册并可连接;同时配置用户级与项目级同名服务器,验证项目级覆盖用户级。

验收场景:

  1. 假设 ~/.wave/mcp.json 存在且包含 mcpServers,当 代理在任何工作目录初始化时,则 用户级服务器必须自动注册并尝试连接(与项目 .mcp.json 行为一致)。
  2. 假设 用户级与项目级配置了同名服务器,当 代理合并配置时,则 项目级(.mcp.json)覆盖用户级(~/.wave/mcp.json),构造函数传入的 mcpServers 优先级最高(构造函数 > 项目 > 用户 > 插件)。
  3. 假设 用户级 ~/.wave/mcp.json 不存在,当 代理初始化时,则 正常继续,不报错(用户级配置为可选)。
  4. 假设 用户级 ~/.wave/mcp.json 格式错误,当 代理初始化时,则 记录错误并跳过用户级来源,其余配置源(项目/构造函数)正常加载。

边界情况 ​

  • 手动断开不得被自动重连撤销:用户主动断开某服务器时,teardown 触发的 transport close 不得被指数退避自动重连机制再次拉起;断开后需用户显式点击"连接"才会重连。自动重连仅适用于非人为原因(进程崩溃、传输意外断开)的恢复。
  • 断开 vs 删除:断开仅是运行时动作——终止子进程并把状态置为未连接,配置文件(.mcp.json / ~/.wave/mcp.json)中的服务保留,可随时手动重新连接;从配置中移除服务须走"删除"。
  • 断开竞态护栏:断开时若有并发连接/崩溃后的陈旧进程退出事件,不得误删新建立的连接或误改新状态——只有"当前代际"的传输关闭才允许改写该服务器的连接与状态。
  • 服务器崩溃:如果 MCP 服务器进程意外终止,McpManager 必须检测传输错误并将服务器状态更新为 error。
  • 工具名称冲突:来自不同服务器的同名工具通过添加 mcp__[serverName]__[toolName] 前缀来处理。该扁平全名同时是沙箱 tools 对象上的键与权限规则匹配的身份;工具池收敛只撤下"声明",全名与身份都不变(见 docs/specs/core/exec-tool.md)。
  • 不支持的 Schema 字段:包含 $schema、exclusiveMinimum 或 exclusiveMaximum 等字段的 MCP 工具 schema 必须被清理以确保与 LLM API 的兼容性。
  • 服务器级 instructions 与工具描述的职责边界? 服务器级的 instructions 走独立的播报通道(服务器可用时追加一条 isMeta 消息,见本文件"把服务器自带的使用说明播报给模型")、不参与目录预算也不裁剪,适合承载"不调用也要知道"的内容(限流、前置条件、整体用法约定);单个工具的描述会被目录压缩、要拿原文得靠搜索命中,所以不要把服务器级约束写进工具描述里。
  • instructions 会不会让前缀缓存失效? 不会(这正是把它从系统提示挪到消息通道的原因):播报只追加在消息尾部,不改写系统提示文本,也不改写任何已有历史。对齐对象是 Claude Code 的 mcp_instructions_delta 附件——CC 把同一条内容从"每轮重算的系统提示段"移出,注释写明后者 "busts the prompt cache on late MCP connect"。代价是两点,都是刻意的:①服务器断开不能再把原文从上下文里移除(历史不改写,只能追加一条"不再适用");②断开后重连会再播报一次(重复优于丢失)。单台服务器文本上限 2048 字符(对齐 Claude Code 的 MAX_MCP_DESCRIPTION_LENGTH),按英文字符口径计价、不做 CJK 感知(MCP 服务器自述的说明绝大多数是英文,与目录预算同一口径)。
  • 无效配置:如果 .mcp.json 格式错误,代理应记录错误并在没有 MCP 工具的情况下继续。
  • 配置合并:当存在多个配置源(构造函数、项目 .mcp.json、用户 ~/.wave/mcp.json、插件)时,它们按以下优先级合并:构造函数 > 项目(.mcp.json)> 用户(~/.wave/mcp.json)> 插件服务器。
  • SSE 重连:当 SSE EventSource 连接意外断开时,系统必须尝试使用指数退避自动重连。重连期间,服务器状态必须显示 "reconnecting"。如果所有尝试后重连仍失败,状态必须转为 "error"。
  • 无 HTTP→SSE 回退:当基于 URL 的服务器具有 type: "http"(或无 type,默认为 "http")时,如果 Streamable HTTP 连接失败,系统不得回退到 SSE。需要 SSE 的用户必须显式设置 type: "sse"。
  • 未知类型:如果 type 设置为无法识别的值,系统必须在连接时抛出错误。
  • IDE 对话框状态刷新竞态:IDE 插件对话框收到状态推送时,必须忽略比当前列表更旧的快照,防止旧数据覆盖新状态。
  • 删除 MCP 服务失败怎么办? host 更新配置文件失败(权限不足 / 文件不存在)时,向 webview 返回错误提示,列表保持删除前状态,不静默失败
  • 用户级 / 项目级 MCP 配置文件路径? 用户级 ~/.wave/mcp.json,项目级 <项目工作目录>/.mcp.json;两级合并加载,同名服务器用户级覆盖项目级
  • 项目级 MCP 的目标项目是哪个? 三端设置页均为单项目模型——展示/管理当前会话 workdir 的项目级配置;「项目级 MCP」Tab 平铺展示,无项目分组归属推断(2026-09-01 用户拍板:设置页只针对当前项目)
  • 项目级 MCP 的目标项目是哪个? 三端设置页均为单项目模型——展示/管理当前会话 workdir 的项目级配置;新建/编辑项目级 MCP 的目标项目 = 当前对话的 workdir,AI 对话框直接写入该项目目录(2026-08-29 用户拍板:不做跨项目选择)
  • 新建/编辑 MCP 提示词中的 /settings 前缀怎么办? GUI 中 /settings 不是可拦截的本地斜杠命令,预填文本作为普通用户消息原样发送给 AI;前缀仅作为自然语言指令的一部分提示 AI 处理 MCP 配置请求
  • IDE 侧「打开配置文件」与「关闭设置页」的先后顺序? 两个动作都由设置页入口向宿主发出,且关闭动作会销毁设置页载体(VS Code 设置 WebviewPanel 被 dispose、JetBrains 设置文件编辑器被 close);打开文件必须先于关闭设置页发出,否则销毁后到达的打开请求被丢弃——表现为四个视图(技能 / 子代理 / 钩子 / MCP 服务)点「编辑」都不打开文件(桌面端设置页与聊天共用一个 webview,不涉及此顺序)。同理,配置文件路径缺失时只预填提示词、不打开文件(不自造占位路径)

假设 ​

  • MCP 服务器可以是本地进程(stdio)或远程端点(http/sse)。
  • 代理具有执行 MCP 配置(.mcp.json / ~/.wave/mcp.json)中指定命令的足够权限。
  • .mcp.json 文件位于代理的工作目录中,用户级 ~/.wave/mcp.json 对所有工作目录生效。
  • MCP 服务器配置可以通过多个源提供:构造函数选项、项目 .mcp.json、用户 ~/.wave/mcp.json、插件配置。