跳转到内容

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.pytools/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.pymcp_serve.pytools/mcp_oauth_manager.pytools/mcp_oauth.py
  • 公开验证:MCP Specification