第10章 MCP 集成:连接外部工具生态
一个开放协议如何让 Agent 接入全世界的工具
10.1 本章导读
第9章的插件是"私有扩展"——你写代码、打包、安装。本章讲一种更开放的方式:MCP(Model Context Protocol),一个工具接入的标准协议。只要某个工具方提供了 MCP Server(文件系统、数据库、GitHub、Slack……社区已有成百上千个),你不用写一行适配代码就能接入。
10.2 MCP 是什么:工具的 USB 接口
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 支持多种传输。本项目当前支持 stdio、SSE 和 streamable-http:stdio 把 Server 作为子进程拉起并通过 stdin/stdout 做 JSON-RPC 2.0 通信;远程 Server 则通过 URL、请求头和 HTTP/SSE 语义接入。
关键类分工:
| 类 | 模块 | 职责 |
|---|---|---|
IMcpClient | domain/tool/mcp | MCP 客户端端口(connect/listTools/callTool) |
StdioMcpClient | infrastructure/adapter/mcp | stdio 实现:ProcessBuilder 拉子进程,stdin/stdout 跑 JSON-RPC 2.0 |
HttpMcpClient | infrastructure/adapter/mcp | SSE 与 streamable-http 实现:处理 URL、请求头、事件流与 HTTP 请求 |
McpToolAdapter | domain/tool/mcp | 把 MCP 工具适配成系统统一 ToolDefinition,注册为 mcp__<serverName>__<toolName> |
McpBootstrap | domain/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 / callTool10.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: sse 或 transport: streamable-http,并声明 url;需要鉴权时配置 headers。无论哪种传输,注册后的工具都会进入同一个 ToolRegistry。
启动后,McpBootstrap 会拉起该 Server、列出它的工具(read_file、write_file、list_directory 等),注册为 mcp__filesystem__read_file 这样的工具名。之后 Agent 就能像调内置工具一样调它们——在控制台问"读一下 /tmp 下的某个文件",模型会选择 mcp__filesystem__read_file。
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章讲任务、审批与治理的完整链路。