🛠️ 第四篇:工具与扩展

第10章 MCP 集成:连接外部工具生态

一个开放协议如何让 Agent 接入全世界的工具

10.1 本章导读

第9章的插件是"私有扩展"——你写代码、打包、安装。本章讲一种更开放的方式:MCP(Model Context Protocol),一个工具接入的标准协议。只要某个工具方提供了 MCP Server(文件系统、数据库、GitHub、Slack……社区已有成百上千个),你不用写一行适配代码就能接入。

10.2 MCP 是什么:工具的 USB 接口

💡 一句话理解 MCP

USB 让任何外设即插即用到任何电脑;MCP 让任何工具即插即用到任何 Agent。工具方实现一次 MCP Server,所有支持 MCP 的 Agent(Claude、本项目、其他)都能直接用——不用每家各写一套集成。

对比第9章的插件体系:

维度插件(第9章)MCP(本章)
耦合面向本项目的 SPI 写代码面向开放协议,一次实现处处可用
获取方式自己开发或找本项目专用插件直接用社区现成的 MCP Server
通信Java=进程内,Node=私有 JSON-RPC标准化 JSON-RPC 2.0
适合深度定制、性能敏感快速接入生态、标准化能力

10.3 本项目的 MCP 架构:三种传输

MCP 支持多种传输。本项目当前支持 stdioSSEstreamable-http:stdio 把 Server 作为子进程拉起并通过 stdin/stdout 做 JSON-RPC 2.0 通信;远程 Server 则通过 URL、请求头和 HTTP/SSE 语义接入。

关键类分工:

模块职责
IMcpClientdomain/tool/mcpMCP 客户端端口(connect/listTools/callTool)
StdioMcpClientinfrastructure/adapter/mcpstdio 实现:ProcessBuilder 拉子进程,stdin/stdout 跑 JSON-RPC 2.0
HttpMcpClientinfrastructure/adapter/mcpSSE 与 streamable-http 实现:处理 URL、请求头、事件流与 HTTP 请求
McpToolAdapterdomain/tool/mcp把 MCP 工具适配成系统统一 ToolDefinition,注册为 mcp__<serverName>__<toolName>
McpBootstrapdomain/tool/mcp启动时读取配置、连接 Server、注册工具

10.3.1 握手序列

StdioMcpClient.connect() 内部是标准 MCP 初始化握手:

// StdioMcpClient.connect()(简化)
ProcessBuilder pb = new ProcessBuilder(cmd);   // 拉起 MCP Server 子进程
// ...
sendAndWait("initialize", Map.of(...));         // 1. 发送 initialize 请求
sendNotification("notifications/initialized", Map.of());  // 2. 发送 initialized 通知
// 此后即可 listTools / callTool

10.4 动手:接入一个文件系统 MCP Server

以社区官方的 filesystem Server 为例,在 harness.yml 配置:

harness:
  extensions:
    mcp:
      enabled: true
      servers:
        - name: filesystem
          transport: stdio
          command: npx
          args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
          env: {}
          cwd: ~

远程服务使用 transport: ssetransport: streamable-http,并声明 url;需要鉴权时配置 headers。无论哪种传输,注册后的工具都会进入同一个 ToolRegistry

启动后,McpBootstrap 会拉起该 Server、列出它的工具(read_file、write_file、list_directory 等),注册为 mcp__filesystem__read_file 这样的工具名。之后 Agent 就能像调内置工具一样调它们——在控制台问"读一下 /tmp 下的某个文件",模型会选择 mcp__filesystem__read_file

⚠️ MCP 工具同样受治理

MCP 工具注册后进的是同一个 ToolRegistry、同一个 ToolCallExecutor——Hook、超时、审批矩阵对它们一样生效。接入第三方 MCP Server 前,务必确认它的工具是否该加进 harness.approval.required-tools(比如任何带写能力的工具),并检查远程 URL、Header 与密钥来源。

10.5 当前边界

已知限制

  • stdio、SSE、streamable-http 均已可用,但仍需在启动前校验命令、URL、协议和密钥
  • MCP 与插件 Bridge 互不打通——MCP Server 不能作为插件包安装,插件也不能通过 MCP 协议暴露
  • 社区 MCP Server 质量参差,接入前建议先手动 npx ... 跑通验证

10.6 小结与下一章预告

本章要点:MCP 是工具的开放标准协议;本项目支持 stdio、SSE 和 streamable-http 三种传输;McpToolAdapter 把远端工具注册为 mcp__<server>__<tool>,与内置工具同链同治理;配置在 harness.extensions.mcp.servers

下一章:能力越来越强(文件、Shell、插件、MCP),风险也越来越大。怎么保证 Agent 不会执行危险操作?第11章讲任务、审批与治理的完整链路。