专题篇章 · 拆开一只生产级 Coding Agent

MCP 连接、发现与恢复

确认客户端角色,拆解 OAuth、工具命名、能力发现、状态合并与重连

本页解决的问题

先给结论

「MCP 连接、发现与恢复」要解决的关键问题是什么?

确认客户端角色,拆解 OAuth、工具命名、能力发现、状态合并与重连

判断标准

让这个结论先证明自己值得留下。 把这一页当成决策工具,而不是需要背下来的定义。把概念连到一个真实任务、一个可观察结果,以及一个能改变你判断的失败上。

下一步

写下一个问题:试完这个方法后,你能用什么证据回答它?

常见误区

结论听起来很完整,却没有检查最关键的假设。

Grok Build Source Course · 12 / 20

MCP:连接只是起点

真正的客户端还要完成配置合并、OAuth、能力发现、命名隔离、模型可见性控制、状态推送和断线恢复。源码将这些责任拆在 MCP crate 与 Session Actor 周边。

Client Rolestdio / Streamable HTTPOAuthserver__tool50 ms 状态合并
01 / OBJECTIVES

课程目标

核对协议角色

从调用方向判断客户端与服务端,避免把内部 Hub Server 等同于 MCP Server。

追踪可见性

解释工具如何从 tools/list 进入快照、搜索索引与模型注册表。

设计恢复状态机

把 OAuth、状态合并、客户端身份和重启退避放进同一连接生命周期。

02 / CORE VISUAL

从外部 Server 到模型工具

03 / ROLE CHECK

客户端与服务端:按源码措辞落位

SOURCE CONFIRMEDGrok Build 是 MCP 客户端

McpClient 启动 stdio 或 Streamable HTTP 连接,执行初始化、list_toolscall_tool。Computer Hub MCP Adapter 也描述为把 MCP Server 的工具桥接进 Hub 路由。

NOT ESTABLISHED通用 MCP 服务端没有源码证据

xai-grok-workspace 的 Hub Server 属于 xAI Computer Hub 协议。当前快照未找到将 Grok Build 自身通过 MCP 传输暴露给任意 MCP Client 的入口,因此本课只确认客户端角色。

04 / OAUTH

OAuth 与真实凭据落点

1 · 复用或刷新先读磁盘凭据并尝试 token refresh
2 · 浏览器授权需要交互时启动用户同意流程
3 · 回调换令牌授权码交换访问与刷新令牌
4 · 锁定写入文件锁配合原子保存,支持多进程
CONFIG TYPES

配置字段

oauth_client_id
oauth_client_secret_env_var
oauth_scopes
crates/codegen/xai-grok-config-types/src/mcp.rs
CREDENTIAL STORE

本地 JSON 文件

let path = grok_home
    .join("mcp_credentials.json");
// lock + load + insert + atomic save

源码采用该文件存储,并通过文件锁与原子保存处理并发写入。

crates/codegen/xai-grok-mcp/src/credentials.rs · oauth.rs
05 / VISIBILITY

工具如何获得模型可见性

NAMESPACE

server__tool

注册名由服务端名、保留分隔符 __ 和原始工具名组成。源码要求完整名称中恰好出现一次分隔符,避免解析歧义,也让两个 Server 的同名工具拥有不同 ToolId

crates/codegen/xai-grok-mcp/src/servers.rs: into_registration
TWO AUDIENCES

模型工具与 App 工具分流

禁用工具会存入 disabled_tool_registrationsmodel_visible 为真才进入模型侧 Tool Bridge;带 ui.resourceUri 的工具可单独进入 UI 通知。

crates/codegen/xai-grok-shell/src/session/acp_session_impl/mcp.rs
SEARCH SNAPSHOT

大量 MCP 工具不必全部常驻提示词

ToolMetadataSnapshot 保存工具与服务端元数据,BM25 索引支持按 qualified name 或裸工具名精确命中,再提供搜索结果。mcp_initialized 告诉搜索层能力发现是否完成。

pub struct ToolMetadataSnapshot {
    pub tools: Vec<ToolMetadata>,
    pub servers: Vec<ServerMetadata>,
    pub mcp_initialized: bool,
}
crates/codegen/xai-grok-shell/src/session/tool_index.rs
06 / RECOVERY

状态合并与重启保护

Initializing开始握手
Ready能力可用
NeedsAuth等待授权
Unavailable连接中断
Disabled配置关闭
50 MS COALESCE

同键保留最新事件

mcp_dispatcher(server_name, event_kind) 为键,在 50 ms tumbling window 内 last-write-wins。高频 tools/list_changed 最终只推一次 ACP 状态。

IDENTITY GUARD

旧断线不能误删新连接

移除 dead client 前比较 client_id。如果断线事件属于已被替换的旧客户端,保持当前客户端,并丢弃过期状态。

RESTART POLICY

不同传输采用不同恢复动作

stdio 自动重启使用固定退避 1s → 4s → 16s,并检查关闭中、已禁用、配置移除等护栏。HTTP 先尝试客户端内恢复,并使用独立退避。成功重连后重新发现与注册工具,随后刷新快照。

crates/codegen/xai-grok-shell/src/session/mcp_dispatcher.rs · mcp_restart.rs · acp_session_impl/mcp_snapshot.rs
07 / LAB

课堂练习:画出可恢复客户端

30 MIN

提交物
状态图与 6 条测试

  1. 画出配置载入、连接、OAuth、能力发现、注册、搜索和调用的状态图。
  2. 加入 disabled、app-only 与 model-visible 三种工具路径。
  3. 设计两个同名工具,验证 qualified name 可消除冲突。
  4. 模拟 100 条 tools/list_changed,写出 50 ms 合并后的预期通知数。
  5. 模拟旧客户端断线事件晚到,说明 client_id 护栏如何保护新连接。
  6. 分别为 stdio 与 HTTP 写一条可恢复测试和一条停止重试条件。
Takeaway

MCP 集成的工程量集中在协议外围。命名、可见性、身份、状态合并和恢复策略共同决定一条连接能否长期稳定工作。

源码快照说明:本页依据本地 grok-build-main 的 MCP、config-types、shell session 与 computer-hub adapter 源码整理。代码片段为教学截取。关于 MCP 服务端角色的结论采用保守口径,内部 Hub Server 不作为通用 MCP Server 证据。

「MCP: 连接只是起点」如何改变一次回答

「真正的客户端还要完成配置合并、OAuth、能力发现、命名隔离、模型可见性控制、状态推送和断线恢复。源码将这些责任拆在 MCP crate 与 Session Actor 周边」说明,模型处理的不是我们眼中的“字数”,而是一段段 Token。Token 的切分方式会影响输入长度、上下文能放下多少内容,以及一次请求要花多少计算。

长度、信息量和上下文不是一回事

当「从调用方向判断客户端与服务端,避免把内部 Hub Server 等同于 MCP Server」变长时,先要分清三件事:文字被切成多少 Token、哪些内容真正参与当前判断、以及旧内容是否已经超出上下文窗口。删掉重复说明通常比单纯把窗口开得更大更有效。

  • 画出配置载入、连接、OAuth、能力发现、注册、搜索和调用的状态图
  • 加入 disabled、app-only 与 model-visible 三种工具路径
  • 设计两个同名工具,验证 qualified name 可消除冲突

先保留会改变判断的内容

可以用「源码快照说明: 本页依据本地 grok-build-main 的 MCP、config-types、shell session 与 computer-hub adapter 源码整理。代码片段为教学截取。关于 MCP 服务端角色的结论采用保守口径,内部 Hub Server 不作为通用 MCP Server 证据」做一次对照:保留同样的问题,分别删掉重复背景、压缩格式和移除无关历史,比较答案质量、延迟与 Token 数量。

从「MCP: 连接只是起点」走到「核对协议角色」

「MCP: 连接只是起点」先把问题落在「真正的客户端还要完成配置合并、OAuth、能力发现、命名隔离、模型可见性控制、状态推送和断线恢复。源码将这些责任拆在 MCP crate 与 Session Actor 周边」上;到了「核对协议角色」,讨论继续推进到「从调用方向判断客户端与服务端,避免把内部 Hub Server 等同于 MCP Server」。两段连起来,重点就不只是记住一个结论,而是看清它成立所依赖的条件。

把这条判断带到下一个场景

处理长文本时,先保留会改变结论的内容,再决定如何压缩格式和历史;上下文更长只有在新增信息真正有用时才值得付出代价。

  • 「MCP: 连接只是起点」:真正的客户端还要完成配置合并、OAuth、能力发现、命名隔离、模型可见性控制、状态推送和断线恢复。源码将这些责任拆在 MCP crate 与 Session Actor 周边
  • 「核对协议角色」:从调用方向判断客户端与服务端,避免把内部 Hub Server 等同于 MCP Server
  • 「最后的要点」:模拟旧客户端断线事件晚到,说明 client_id 护栏如何保护新连接

最后的「最后的要点」把讨论落到「模拟旧客户端断线事件晚到,说明 client_id 护栏如何保护新连接」。回看这条线索时,最值得保留的是:当输入、规模或风险改变,哪些判断需要重新做一遍。

标记为已学完 阅读进度会自动记录
← 上一篇下一篇 →

继续阅读

同一条线上的下一篇。

文章讨论

读到这里,留下一个判断。

把刚想明白的地方、还没想通的问题,留给下一位一起学习的人。

正在讨论 MCP 连接、发现与恢复 拆开一只生产级 Coding Agent
3条讨论文章讨论 · 与共学社区同步
在共学社区查看
AM
Asha Morgan内容编辑
观点实践记录

我把这篇文章里的一个判断改写成了今天可以验证的小实验。比记住结论更有用的是,知道下一步要观察什么。

文章讨论7 有帮助
LH
Lin Harper独立开发者
观点观点

读完以后我先回头找它成立的条件,而不是直接把方法搬进项目。这个顺序让后面的取舍清楚很多。

文章讨论5 有帮助
KM
Kiki Moore产品运营
问题问题

如果把这个判断放到真实工作里,最先需要补的约束是什么?我想知道从阅读到第一次实践之间,哪一步最值得先做。

文章讨论4 有帮助