MCP协议、熔断器与OAuth——Agent接入外部世界的工程方案
MCP协议、熔断器与OAuth——Agent接入外部世界的工程方案
《Claude Code 架构解密》精读笔记 · 第15篇
覆盖章节:第9章后半(9.6-9.12, p.237-251)
主题:8种MCP传输适配、分级熔断连接缓存、OAuth/XAA认证状态机、分区批处理编排、插件模块化组合
导语:从"内部拦截"到"外部集成"
第14篇解析了 Hook 事件系统——Claude Code 的"内部扩展骨架"。但 Agent 的真正威力不仅来自"能拦截什么",更来自"能连接什么"。
当 Agent 需要查询公司内部的知识库、调用云服务 API、读取设计稿里的组件定义、甚至控制智能家居设备时,它需要一个统一的外部集成通道。这个通道就是 MCP(Model Context Protocol)。
但"统一接入"说起来容易,做起来难。MCP 服务器可能跑在本地子进程里,也可能部署在远程 HTTP 服务上,还可能嵌在 IDE 的 WebSocket 连接里——8 种传输协议,每种都有不同的连接方式、错误处理和安全约束。更麻烦的是,这些连接会断开、会超时、会认证过期——Agent 不能每次都傻傻地报错,而要有智能的故障恢复机制。
本篇将深入 Claude Code 的 MCP 协议栈、连接管理体系、认证状态机,以及把这一切打包分发的插件系统。这是 Agent 从"产品"走向"平台"的另一半故事。
一、架构图解:MCP 协议栈与插件全景
┌─────────────────────────────────────────────────────────────────┐
│ MCP 协议栈 + 插件系统全景 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 插件系统(Plugin System) │ │
│ │ Skills(.md) + Commands(.md/.ts) + Agents(.md) │ │
│ │ + Hooks(hooks.json) + MCP(.mcp.json) │ │
│ │ → 注册到各自子系统,优先级999(最低) │ │
│ └───────────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ 插件安装时自动注册 │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 工具编排层(Tool Orchestration) │ │
│ │ 分区-批处理:isConcurrencySafe → 并发/串行决策 │ │
│ │ + 触发 PreToolUse/PostToolUse Hook │ │
│ └───────────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ MCP 客户端层(connectToServer + 连接缓存) │ │
│ │ │ │
│ │ 8种传输适配器 │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ │
│ │ │stdio │ │ http │ │ sse │ │ ws │ │ │
│ │ └──────┘ └──────┘ └──────┘ └──────┘ │ │
│ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────────┐ │ │
│ │ │sse-ide││ws-ide││ sdk ││claudeai- │ │ │
│ │ └──────┘ └──────┘ └──────┘ │proxy │ │ │
│ │ └──────────┘ │ │
│ │ │ │
│ │ 连接缓存(memoize)+ 本地/远程分组并发 │ │
│ │ 四层熔断:指数退避 → 认证熔断 → 终端错误 → 会话过期 │ │
│ └───────────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 认证层(OAuth State Machine) │ │
│ │ pending → connected → failed / needs-auth │ │
│ │ + 标准OAuth流程 + XAA跨应用访问 │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
二、核心点拆解
2.1 8 种 MCP 传输协议统一适配
问题:8 种协议,1 个接口
MCP 工具服务器可能运行在各种环境中——本地子进程通过标准输入输出通信,远程服务通过 HTTP/SSE 连接,IDE 通过 WebSocket 内嵌,SDK 通过控制通道桥接。如何用统一的客户端接口屏蔽这些传输差异?
Claude Code 的 connectToServer 函数实现了 8 种传输适配器,统一收敛到 MCP SDK 的 client 接口:
| 传输类型 | 适配器类 | 连接方式 | 特殊处 |
|---|---|---|---|
stdio |
StdioClientTransport |
子进程 spawn | 本地最低开销 |
sse |
SSEClientTransport |
Server-Sent Events + OAuth | 远程流式 |
http |
StreamableHTTPClientTransport |
可流式 HTTP | 支持 POST 双向 |
ws |
WebSocketTransport |
Bun/Node 双运行时 | IDE 内嵌 |
sse-ide |
SSEClientTransport |
SSE + IDE Auth Token | Token 注入 |
ws-ide |
WebSocketTransport |
WebSocket + IDE Auth Token | Token 注入 |
sdk |
SdkControlClientTransport |
控制消息桥 | SDK 集成 |
claudeai-proxy |
StreamableHTTPClientTransport |
HTTP + Claude.ai OAuth | 组织级认证 |
这种设计的核心模式是**适配器模式(Adapter Pattern)**的极端版本——不是"一个接口多种实现",而是"8种完全不同的通信协议,统一到一个 Client 接口"。每种适配器处理协议特有的连接建立、消息编解码、错误处理和断开重连。
连接缓存与分组并发
连接管理有两个关键优化:
连接缓存:使用 memoize 确保同一配置只建立一次连接,缓存键为 ${name}-${JSON.stringify(config)}。这避免了重复连接同一服务器的开销。
本地/远程分组启动:
启动时按传输类型分组:
本地传输(stdio)→ 低并发(默认3),避免子进程爆炸
远程传输(http/ws)→ 高并发(默认20),充分利用网络
这种分组策略源于一个实际问题:如果同时 spawn 20 个本地 MCP 服务器子进程,在资源受限的机器上可能导致 OOM。但远程连接只是 TCP 握手,20 个并发完全可以承受。
InProcessTransport:避免进程开销
对于 Chrome MCP 和 Computer Use MCP 这样的"重量级"工具,Claude Code 提供了 InProcessTransport——直接在主进程内启动 MCP 服务器,避免 325MB 的子进程开销。这是**“性能热路径特殊处理”**的典型实践。
缓存失效:onclose 的全面清理
连接缓存最棘手的问题是失效。Claude Code 在 onclose 回调中执行全面清理:
// 连接关闭时清除所有相关缓存
client.onclose = () => {
memoizedConnect.cache.delete(cacheKey); // 连接缓存
toolsCache.delete(name); // 工具列表缓存
resourcesCache.delete(name); // 资源缓存
commandsCache.delete(name); // 命令缓存
// 确保下次调用重建连接
};
这种**“一次断开,全面清理”**的策略确保了不会出现"连接已断但缓存仍在"导致的幽灵调用。
2.2 四层渐进式故障恢复:分级熔断
MCP 连接可能因网络抖动、认证过期、服务器崩溃等原因断开。Claude Code 实现了四层故障恢复机制,从轻到重逐层升级:
第一层:指数退避重连
检测断开 → 检查是否禁用 → 更新为 pending → 等待退避时间 → 重连
1s → 2s → 4s → 8s → 16s (上限 30s)
最多5次,失败后标记 failed
第二层:认证缓存熔断
对返回401的服务器,进行15分钟的"短路缓存":
const MCP_AUTH_CACHE_TTL_MS = 15 * 60 * 1000;
// 缓存命中时跳过连接,注入 McpAuthTool 供用户手动认证
第三层:终端错误计数
连续3次终端错误(ECONNRESET/ETIMEDOUT/EPIPE/SSEdisconnected)
→ 强制关闭 → 触发重连流程
第四层:会话过期检测
HTTP 404 + JSON-RPC -32001 ("Session not found")
→ 清除连接缓存 → 重试一次 → 仍失败则报错
这四层防御体现的核心模式是分级熔断(Tiered Circuit Breaking):
| 故障级别 | 触发条件 | 恢复路径 | 用户感知 |
|---|---|---|---|
| 轻故障 | 网络抖动 | 自动重连,最多5次 | 无感 |
| 中故障 | 认证过期(401) | 熔断15分钟 + 注入 McpAuthTool |
手动触发重新认证 |
| 重故障 | 终端错误连续3次 | 标记 failed,停止重试 | 明确报错 |
| 会话级 | HTTP 404 + -32001 | 清除缓存重试一次 | 短暂延迟后恢复或报错 |
每一级都有明确的触发条件和恢复路径,避免了"一刀切"的粗暴策略。
子进程的渐进式退出
对于 stdio 类型的 MCP 服务器(本地子进程),Claude Code 实现了 SIGINT → SIGTERM → SIGKILL 的渐进式退出策略:先礼貌请求退出,再强制终止,最后无条件杀死。每个阶段都有超时窗口,确保子进程有机会做清理工作。
2.3 OAuth 认证状态机:Token 的完整生命周期
连接状态的显式建模
MCP 服务器的连接状态不是简单的"连接/断开"二值,而是一个包含认证维度的复杂状态空间。Claude Code 将其建模为显式的状态机:
pending ─────→ connected
│ │
│ ├── [onerror] ──→ pending(重连)
│ │
├── [401] ──→ needs-auth
│ │
├── [失败超限] → failed
│
└── [用户主动] → disabled
McpServerConnection 使用**判别联合类型(Discriminated Union)**表达这些状态——每个状态携带不同的数据(如 needs-auth 携带认证 URL,failed 携带错误原因)。这比"一个状态字段 + 若干可选字段"的类型设计更安全——编译器会强制处理每个状态分支。
标准 OAuth 流程
当 MCP 服务器返回 401 需要认证时,Claude Code 启动标准 OAuth 流程:
- RFC 8414/9728 发现授权服务器元数据
- 启动本地回调服务器(随机端口,避免端口冲突)
- 打开浏览器 → 用户授权 → 回调获取
authorization_code code + PKCE(Proof Key for Code Exchange) → Access Token- Token 安全存储:macOS Keychain / Windows Credential Manager
PKCE 是 OAuth 2.1 的必要安全机制,防止授权码被中间人截获后使用。
XAA 跨应用访问流程
对于企业内部的跨应用场景,Claude Code 还支持 **XAA(Cross-Application Access)**流程:
OIDC 登录 → 获取 id_token(缓存复用,避免重复登录)
→ RFC 8693 Token Exchange: id_token → ID-TAG
→ RFC 7523 JWT Bearer Grant: ID-TAG → access_token
这是一个三步令牌变换链,每一步都遵循标准 RFC 规范。XAA 的核心价值是:用户只需登录一次(OIDC),就能访问多个内部系统,无需每个系统都单独认证。
Token 管理的细节
Token 生命周期管理中有几个值得注意的实现细节:
- Step-up 认证:
wrapFetchWithStepUpDetection处理"权限不够,需要更高级别认证"的场景 - 强制刷新重试:
createClaudeAiProxyFetch支持收到 401 后的一次性强制 Token 刷新重试——只重试一次,避免死循环 - 安全存储:Token 不存放在文件中,而是使用操作系统级的凭证管理器,防止明文泄露
2.4 分区批处理工具编排:并发与正确性的精确平衡
问题:多工具调用的执行顺序
LLM 可能在一次响应中返回多个工具调用。这带来一个关键问题:哪些工具可以并发执行,哪些必须串行?
直觉上,文件读取是"安全的"——并发读 10 个文件不会相互影响。但文件编辑就不行——如果两个编辑操作修改同一个文件,并发执行会导致冲突。Shell 命令更加复杂——git add . && git commit -m "fix" 这样的命令序列显然不能乱序执行。
分区-批处理策略
Claude Code 的 toolOrchestration.ts 实现了一种**"分区-批处理"编排模式**:
LLM 返回 tool_use[] → partitionToolCalls → Batch[]
├── 按 isConcurrencySafe 分区
├── 连续安全工具 → 合并为一个并发批次
└── 不安全工具 → 单独作为串行批次
并发批次:
Promise.all(runToolUseN)- 上限:10 并发
- 上下文修改:延迟收集,批次完成后按序应用
串行批次:
- 逐个
runToolUse - 上下文修改:立即应用
注意"上下文修改"的处理方式:并发批次中的工具可能都会修改对话上下文,但并发执行时无法确定顺序。Claude Code 的策略是延迟收集、按序应用——先并发执行所有工具,收集各自的上上下文修改,批次完成后按工具在原始数组中的顺序依次应用。
Hook 集成
工具编排与 Hook 系统紧密集成。每个工具执行前后都会触发 PreToolUse/PostToolUse Hook,Hook 可以:
- 修改工具输入参数
- 做出权限决策(
allow/deny) - 修改 MCP 工具的输出结果
但权限决策遵循**“安全优先"原则**:Hook 返回的 allow 不能绕过 settings.json 中的 deny/ask 规则。这确保了 Hook 不能被用来"越权”——一个恶意插件无法通过 Hook 给自己开放被系统禁止的工具。
2.5 插件系统:Skills、Commands 与 Agents 的模块化组合
为什么 Hook 和 MCP 还不够
Hook 是行为级扩展——在生命周期节点注入逻辑片段。MCP 是能力级扩展——接入外部工具和资源。但还有一类需求它们无法优雅满足:工作流级扩展。
考虑这样的场景:团队需要一套标准化的代码审查流程——包含一个特定的 Agent 定义(带专用 system prompt 和工具白名单)、几个配套的斜杠命令(如 /review 和 /approve)、一组 Hook(提交前自动运行 lint)、甚至自定义的输出样式。这些组件分属 Hook、MCP、Agent、Command 四个不同的子系统,单独配置既繁琐又容易遗漏。
这就是插件系统要解决的问题:将分散在多个子系统中的组件打包为一个可分发、可安装、可管理的模块。
插件的整体架构
Claude Code 的插件系统由三种核心组件构成,每种对应不同的扩展粒度:
| 组件 | 定义格式 | 运行时行为 | 典型场景 |
|---|---|---|---|
| Skills | Markdown + Frontmatter | 注入 System Prompt,不执行代码 | 工作流模板(如"提交前必须跑测试") |
| Commands | .md 文件 / TypeScript 模块 |
响应斜杠命令,本地即时执行 | /review、/deploy 等自定义命令 |
| Agents | Markdown Frontmatter | 启动子 Agent,拥有独立工具白名单 | 代码审查 Agent、测试 Agent |
三种组件的设计哲学截然不同:
-
Skills 是提示级扩展。本质上是结构化的 System Prompt 片段,通过
skillTool动态注入到对话上下文中。Skill 不执行任何代码,它只改变 Agent 的"思维方式"。 -
Commands 是行为级扩展。分为三种类型:
PromptCommand:最轻量,.md文件即命令,支持$ARGUMENTS占位符LocalCommand:用于/compact、/clear等无 UI 操作LocalJSXCommand:用于/config、/help等需要全屏界面的场景
所有命令都采用懒加载(
load: () => Promise<>),确保未使用的命令不消耗启动时间。 -
Agents 是编排级扩展。通过 Markdown Frontmatter 定义 Agent 类型——正文作为 system prompt,YAML header 声明工具白名单、模型配置等元数据。
插件的目录结构与清单
Claude Code 通过约定优于配置的目录结构定义插件:
my-plugin/
├── .claude-plugin/
│ ├── plugin.json # 插件清单(PluginManifest)
│ └── marketplace.json # Marketplace 入口
├── commands/ # 斜杠命令(.md 文件或 TypeScript 模块)
├── agents/ # Agent 定义(.md 文件 + Frontmatter)
├── skills/ # Skills(子目录 + SKILL.md)
├── hooks/ # 生命周期钩子(hooks.json)
├── output-styles/ # 输出样式定制
├── .mcp.json # 内嵌 MCP 服务器配置
└── .lsp.json # LSP 服务器配置
plugin.json 是插件的清单文件,声明插件的名称、版本、依赖关系和能力矩阵。关键字段包括:
- 依赖声明:指定插件依赖的其他插件,支持版本约束
- 能力声明:列出插件提供的 Commands、Agents、Skills、Hooks 和 Output Styles
- Marketplace 归属:标明插件来源的 Marketplace,用于安全策略评估
注意目录结构中包含了 .mcp.json——这意味着插件可以内嵌 MCP 服务器配置。这是一个精巧的设计:插件安装时自动注册其依赖的 MCP 服务器,卸载时自动清理,避免了手动管理 MCP 配置的麻烦。
发现、加载与注册
插件的生命周期包含三个阶段:发现 → 加载 → 注册。
发现阶段:pluginLoader.ts 扫描预定义的插件目录,查找包含 .claude-plugin/plugin.json 的子目录。发现过程是递归的,支持嵌套插件结构。
加载阶段:解析 plugin.json 清单,验证格式和版本兼容性。这个阶段的关键是依赖解析——dependencyResolver.ts 使用 **DFS(深度优先搜索)**遍历依赖闭包,具有三个安全规则:
- 循环检测:使用栈检测循环依赖 → 发现即报错
- 跨 Marketplace 阻断:默认阻止跨 Marketplace 依赖,除非在
allowCrossMarketplaceDependenciesOn中显式允许 - 裸名解析:无
@marketplace后缀的依赖继承声明插件的 Marketplace
跨 Marketplace 阻断是一个重要的安全决策。想象一个场景:企业内部 Marketplace 的插件 A 依赖了公共 Marketplace 的插件 B——如果 B 被恶意替换,A 也会受到影响。默认阻断这种跨域依赖,从源头切断供应链攻击。
注册阶段:加载完成的插件组件被注册到各自的子系统中:
插件加载完成 → 分发注册
├── Commands → 合并到全局命令注册表(loadPluginCommands)
├── Agents → 合并到 Agent Type Registry(loadPluginAgents)
├── Skills → 注册到 skill 发现目录(子目录扫描 SKILL.md)
├── Hooks → 合并到 Hook 配置(优先级999)
├── MCP → 注入 dynamicMcpConfig(复用现有连接管理)
└── Output Styles → 注册到输出样式表
注意 Hook 的注册优先级是 999(最低)。这确保了用户设置(优先级0)、项目设置(优先级1)和企业策略(优先级3)都能覆盖插件提供的 Hook。插件永远是最低优先级的配置来源。
插件安全模型
插件加载到主进程地址空间,比 MCP 的进程级隔离风险更大。Claude Code 通过三层安全机制进行防护:
第一层:企业策略过滤(pluginPolicy.ts)
企业管理员可以通过策略文件精确控制哪些插件允许安装:
策略评估链(按优先级):
1. blocklist — 明确阻止的插件(黑名单优先)
2. strictKnownMarketplaces — 仅允许已知来源的 Marketplace
3. hostPattern — 正则匹配允许的插件仓库域名
4. pathPattern — 正则匹配允许的插件路径
这四层策略构成了一个先否后允的裁决链:blocklist 一票否决,strictKnownMarketplaces 限制来源,hostPattern 和 pathPattern 提供细粒度的正则匹配。
第二层:信任边界隔离
| 信任级别 | 机制 | 隔离方式 | 适用场景 |
|---|---|---|---|
| 低(不可信) | MCP | 进程级隔离 | 第三方工具服务 |
| 中(可信生态) | Plugin | 主进程 + 策略过滤 | 社区贡献的扩展包 |
| 高(内部信任) | Skill | 纯 Prompt,无代码执行 | 团队工作流模板 |
Skill 内容即使被恶意注入,其影响范围也仅限于 Agent 的"思考",不会直接操作文件系统或网络。当然,Agent 可能因为恶意 Prompt 而执行危险操作,但这会被第5章的权限模型和第八章的安全纵深防御拦截。
第三层:Hook 命名空间隔离
每个插件的 Hook 使用独立的命名空间,通过 \0(空字符)分隔符的复合键实现隔离。这确保了不同插件的 Hook 不会产生命名冲突,也使得管理员可以精确地禁用或覆盖特定插件的特定 Hook。
2.6 跨模式协作全景
让我们退一步,看看第9章解析的九个设计模式如何协同工作:
Agent 核心循环(QueryEngine)
│
┌─────────────────┼─────────────────┐
│ │ │
工具编排(模式8) Hook事件总线(模式1) MCP工具(模式5/6/7)
│ │ │
├── 触发 Pre/PostToolUse Hook │
├── 发起 MCP 工具调用 │
│ │ │
▼ ▼ ▼
分区批处理 多态执行器 传输适配器
(模式9) (模式2) (模式6)
│ │ │
└─────────────────┼─────────────────┘
│
分级配置合并(模式4)
(Hook 和 MCP 统一仲裁)
- 左侧是 MCP 外部集成线(模式5/6/7):从传输适配到连接管理到认证处理,层层深入。
- 右侧是 Hook 内部扩展线(模式1/2/3):从事件总线到执行器到会话隔离,逐层细化。
- **模式4(分级配置合并)**横跨两侧,为 Hook 和 MCP 提供统一的配置解析。
- **模式8(工具编排)**位于顶层,既触发 Hook 事件,又发起 MCP 工具调用,是两条线的汇聚点。
而插件系统(模式9:模块化组合容器)则横跨两条线,扮演"组合容器"的角色。插件将 Hook 定义、MCP 配置、Agent 类型、Skill 模板、Commands 打包成一个可分发的模块。插件不引入新的运行时机制——它的每个组件最终都注册到已有的子系统中运行。
三、横向对比:MCP 协议栈 vs 其他集成方案
| 维度 | Claude Code MCP | LSP(语言服务器协议) | VS Code Extension API | OpenAI Function Calling |
|---|---|---|---|---|
| 协议类型 | JSON-RPC 2.0 over 8种传输 | JSON-RPC 2.0 over stdio/WebSocket | 直接 TypeScript API 调用 | JSON Schema 声明 |
| 传输灵活性 | 8种适配器,统一接口 | 2种(stdio/WebSocket) | 无(进程内调用) | 无(HTTP API) |
| 连接管理 | 四层熔断 + memoize 缓存 | 简单的断开重连 | 无(扩展生命周期管理) | 无(每次请求独立) |
| 认证 | OAuth 2.1 + XAA 双流程 | 无(进程级隔离) | 扩展自行处理 | API Key(明文) |
| 安全隔离 | 进程级(MCP)/ 主进程(Plugin) | 进程级 | 主进程 | 无(服务端验证) |
| 扩展性 | 插件系统打包分发 | 无(单个服务器) | Extension Pack | 无(手动集成) |
Claude Code 的 MCP 协议栈在传输灵活性和连接管理健壮性两个维度上显著超越其他方案。8 种传输适配器的设计虽然增加了复杂度,但换来了"同一个 MCP 服务器可以在任何环境下运行"的灵活性——这是 Agent 系统需要支持多样化部署场景的必然选择。
OpenAI Function Calling 最简单但也最脆弱——没有连接管理,没有认证状态机,每次请求都是独立的。这对于"一次性工具调用"足够,但对于"需要持久连接的 Agent 工作流"则力不从心。
四、实战启示
启示一:适配器模式的极端版本——协议无关性
当你需要支持多种通信协议时,不要试图"统一协议"(这通常需要所有实现方同时升级),而是"适配协议"——在客户端做协议转换,让上层逻辑看到统一的接口。
Claude Code 的 connectToServer 函数就是一个典范:8 种传输协议,统一收敛到一个 Client 接口。新增传输协议时,只需添加一个适配器类,不需要修改上层逻辑。
启示二:分级熔断比"重试 N 次"更智能
简单的"重试 N 次"策略对待所有错误一视同仁——网络抖动重试5次,认证失败也重试5次,服务器崩溃还是重试5次。这是不对的。
正确的设计是分级熔断:
- 轻故障(网络抖动)→ 自动重连,用户无感
- 中故障(认证过期)→ 熔断 + 提示用户操作
- 重故障(服务器崩溃)→ 标记 failed,停止重试
每一级都有明确的触发条件和恢复路径。这比"一刀切"的粗暴策略更智能,也比"为每个错误类型写特殊逻辑"更可维护。
启示三:判别联合类型比"状态字段 + 可选字段"更安全
OAuth 状态机的类型定义如果用"一个 status 字段 + 若干可选字段",会出现"忘记了处理某种状态"的 bug,而且编译器不会报错。
用判别联合类型(Discriminated Union),编译器会强制处理每个状态分支。这是 TypeScript 中最强大的类型安全工具之一,特别适合建模"有多种可能状态,每种状态携带不同数据"的场景。
启示四:插件系统 = 约定目录结构 + 清单文件
Claude Code 的插件系统没有用复杂的注册 API 或依赖注入框架,而是用了最简单的文件系统约定——特定的目录结构就是注册表,plugin.json 就是清单。
这种设计的好处是:插件可以纯手工创建(写一个目录 + 一个 JSON 文件),也可以由工具生成;插件的版本控制就是目录的版本控制;插件的调试就是看目录结构对不对。
VS Code 的 Extension 用了类似的思路,但 Claude Code 更极致——连 Skill 都是一个 .md 文件,开发者甚至不需要懂 TypeScript 就能创建 AI 命令。
五、本篇小结
| 概念 | 一句话总结 |
|---|---|
| 8种传输适配器 | stdio/sse/http/ws/sse-ide/ws-ide/sdk/claudeai-proxy,统一收敛到 Client 接口 |
| 连接缓存 | memoize + 本地/远程分组并发 + InProcessTransport 性能优化 |
| 四层熔断 | 指数退避 → 认证熔断(15min) → 终端错误计数(3次) → 会话过期检测 |
| OAuth状态机 | 判别联合类型建模,标准OAuth + XAA跨应用访问,Token操作系统级安全存储 |
| 分区批处理 | isConcurrencySafe 分区 + 并发/串行混合 + 延迟收集按序应用上下文修改 |
| 插件三组件 | Skills(Prompt级) + Commands(行为级) + Agents(编排级),约定目录结构打包 |
| 插件安全三层 | 企业策略过滤(4层裁决链) + 信任边界隔离 + Hook命名空间隔离 |
| 配置优先级 | 插件Hook固定999(最低),确保用户/企业策略可覆盖 |
下期预告
第16篇将深入第10章,解析 极简命令式 Store 与分层持久化——Agent 的"记忆宫殿"是如何构建的。30 行代码的 Store 实现、选择器驱动的细粒度订阅、单一 Diff 点的副作用闸门——这些设计体现了"不要为你不需要的能力付出复杂度税"的工程哲学。从"扩展架构"走向"状态管理",挑战从"连接外部"转向"组织内部"。
本篇思考题:插件系统将 Hook 优先级固定为999(最低)——这意味着用户和企业策略总能覆盖插件的 Hook 定义。你认为这个设计是否合理?在什么场景下,插件可能需要更高的优先级?
更多推荐


所有评论(0)