Skip to content

MCP 协议 — 练习

练习 1:配置 MCP 服务器

config.toml 中配置一个 MCP 服务器,观察工具注册和调用过程。

参考答案

MCP 服务器在 config.toml[mcp_servers] 段配置,支持三种传输方式:

  1. Stdio 传输(最常用):

    toml
    [mcp_servers.my-tools]
    command = "python"
    args = ["-m", "my_mcp_server"]
    env = { API_KEY = "..." }

    Codex 启动子进程,通过 stdin/stdout 进行 JSON-RPC 通信。

  2. HTTP 传输

    toml
    [mcp_servers.remote-api]
    url = "https://api.example.com/mcp"
    headers = { Authorization = "Bearer ..." }

    通过 HTTP POST 发送请求,SSE 接收响应。

  3. InProcess 传输: 内置工具直接在进程内调用,无需启动子进程或网络请求。

工具注册过程:

  • McpConnectionManager::new_uninitialized() 创建管理器
  • 配置加载时,为每个 [mcp_servers] 条目创建 AsyncManagedClient
  • 客户端连接后,调用 MCP tools/list 方法获取工具列表
  • tool_is_model_visible() 过滤工具,只向模型暴露可见的工具
  • 工具通过 tool_plugin_provenance 记录来源

验证方式:启动 TUI 后,模型在需要时会自动发现和使用已注册的 MCP 工具。

练习 2:追踪 MCP 工具调用

从一个触发 MCP 工具调用的指令出发,追踪完整的调用链。

参考答案

以用户指令"查询数据库中的用户列表"为例(假设配置了数据库 MCP 服务器):

  1. 用户输入CodexThread::submit(Op::UserInput("查询数据库中的用户列表"))

  2. 上下文构建Session::build_initial_context() 组装:

    • System prompt + 内置工具(shell、apply_patch)
    • MCP 工具声明(query_databaselist_tables 等)
    • 工具通过 tool_is_model_visible() 过滤
  3. 模型调用ModelClientSession::stream() 发送到 LLM,LLM 返回工具调用:

    json
    {"function": "query_database", "arguments": {"sql": "SELECT * FROM users"}}
  4. 工具路由Session 识别 query_database 是 MCP 工具(非内置工具),路由到 McpConnectionManager

  5. MCP 调用

    • McpConnectionManager 根据 tool_plugin_provenance 找到工具所在的服务器
    • 通过对应的传输层(Stdio/HTTP/InProcess)发送 tools/call 请求
    • MCP 服务器执行查询并返回结果
  6. 结果回传

    • 结果追加到对话上下文
    • 模型收到工具结果后生成最终回复
    • Event::TurnItemUpdated 通知消费者
  7. Elicitation(如需要):如果 MCP 服务器需要用户提供额外信息,通过 ElicitationRequestManager 发起请求。在 TUI 模式下显示表单,Exec 模式下自动拒绝。

练习 3:分析 MCP 通信协议

分析 Codex 与 MCP 服务器之间的消息格式和通信协议。

参考答案

Codex 与 MCP 服务器使用 JSON-RPC 2.0 协议通信(由 rmcp-client 实现),核心消息类型:

请求消息(Codex → MCP 服务器):

  • initialize:初始化连接,交换能力声明
  • tools/list:获取服务器支持的工具列表
  • tools/call:调用指定工具,传递参数
  • resources/list:获取可用的资源列表
  • resources/read:读取指定资源

通知消息

  • notifications/cancelled:取消正在执行的请求
  • notifications/elicitation:请求用户输入

三种传输层的协议映射

传输层消息载体连接管理
InProcess直接函数调用无需连接
Stdiostdin/stdout JSON Lines子进程生命周期
StreamableHttpHTTP POST (请求) + SSE (响应)HTTP 连接池

rmcp-clientcodex-rs/rmcp-client/src/rmcp_client.rs)是底层的 MCP 客户端实现,处理:

  • JSON-RPC 消息的序列化/反序列化
  • 请求 ID 的生成和响应匹配
  • 超时和重试逻辑
  • 连接的建立和关闭

拓展挑战

  • 阅读 rmcp-client 的完整实现,理解 JSON-RPC 消息处理
  • 分析 tool_is_model_visible() 的过滤逻辑和可见性元数据
  • 研究 MCP elicitation 在 TUI 模式下的表单渲染实现
  • 分析 McpServerMetadata 的字段和用途