10 - MCP 集成与自服务
学习目标
本章聚焦 Hermes Agent 的 MCP 集成实现。你将了解:
mcp_tool.py如何支持三种传输层(stdio + SSE + Streamable HTTP)mcp_serve.py如何将 Hermes 自身暴露为 MCP Server- MCP OAuth 认证管理与凭证隔离策略
前置知识
本章涉及 MCP 协议的通用原理,建议先阅读:
下文直接聚焦 Hermes 的 MCP 具体实现。
项目实践
MCP 工具调用:三种传输层
tools/mcp_tool.py 实现了 MCP 客户端能力,支持三种传输层:
| 传输层 | 适用场景 | 特点 |
|---|---|---|
| Stdio | 本地 MCP 服务器 | 通过子进程 spawn,stdin/stdout 双向 JSON-RPC |
| SSE | 远程 MCP 服务 | Server-Sent Events 接收流式响应 |
| Streamable HTTP | 现代 MCP 服务器 | HTTP POST 发送请求,SSE 接收响应 |
MCP 工具在注册时自动通过 check_fn 检查服务器可用性。不可用的 MCP 服务器不会暴露给模型。
Hermes 作为 MCP Server
mcp_serve.py 使 Hermes Agent 自身可以作为 MCP 服务器被外部客户端调用:
暴露的能力:
- 将 Hermes 的对话能力暴露给外部 MCP 客户端
- 外部 Agent 可以通过 MCP 协议调用 Hermes 的工具
- 支持 MCP 标准生命周期(initialize → initialized → tools/list → tools/call)
与通用指南中 Codex 作为 MCP Server 的区别:Codex 暴露的是代码执行能力(codex / codex-reply 工具),Hermes 暴露的是完整的 Agent 对话能力,包括工具调用、记忆搜索、技能执行。
MCP OAuth 认证管理
tools/mcp_oauth_manager.py 和 tools/mcp_oauth.py 实现了 MCP 服务器的 OAuth 认证:
- 远程 MCP 服务器需要 OAuth 时,自动触发授权流程
- Token 持久化到磁盘,避免重复授权
- Token 刷新自动处理,过期前预刷新
MCP 凭证隔离
Hermes 的 MCP 子进程不继承主进程的 API key 等凭证:
这确保 MCP 服务器即使被攻击或行为异常,也无法读取 Hermes 主进程的凭证。MCP 所需的认证通过独立的 OAuth token 或配置文件中显式声明的凭证获取。
问题与规避
MCP 服务器启动失败
问题:配置的 MCP 服务器依赖缺失或配置错误,导致 spawn 失败。
对策:MCP 工具注册时的 check_fn 检查服务器可用性。不可用的 MCP 服务器不会出现在工具列表中,模型不会尝试调用。
OAuth Token 过期
问题:MCP 服务器的 OAuth token 过期后,工具调用返回认证错误。
对策:OAuth manager 在 token 过期前预刷新。刷新失败时自动触发重新授权流程。
设计取舍
MCP OAuth vs 静态凭证
| 方案 | 优势 | 代价 |
|---|---|---|
| OAuth(Hermes 默认) | Token 可撤销、有效期管理、安全性高 | 需要 OAuth 基础设施 |
| 静态 API Key | 配置简单 | 凭证泄漏后无法撤销 |
Hermes 优先使用 OAuth 认证远程 MCP 服务器,对于不支持 OAuth 的本地 MCP 服务器(stdio 传输),依赖 OS 进程隔离。
参考来源
- 源码验证:
tools/mcp_tool.py、mcp_serve.py、tools/mcp_oauth_manager.py、tools/mcp_oauth.py - 公开验证:MCP Specification