新闻详情

新闻详情

首页 / 资讯中心 / 详情

codex cli 源码教程 | 第十三篇:MCP、Skills、插件与 Hooks 的配置拆解与验证

发布时间:2026/10/2 12:11:01来源:尧图网络
codex cli 源码教程 | 第十三篇:MCP、Skills、插件与 Hooks 的配置拆解与验证
1. 从一次 Turn 说起MCP、Skills、插件与 Hooks 到底谁在干活如果你正在读 codex cli 源码大概率已经看过命令执行、审批策略和沙箱那几篇。那套机制解决的是「模型已经决定调用某个能力之后Codex 如何安全地执行真实副作用」。但往前追问一步除了改 Codex Core外部能力是怎么进入一条 Thread 和 Turn 的答案就是四类最容易混淆的扩展机制——MCP、Skills、插件、Hooks。它们会在同一个 Turn 中相遇但绝不是四种等价的「插件」。MCP 负责连接外部服务并暴露 Tool、Resource、Template是真正执行能力的协议层Skill 提供可发现、按需读取的操作说明本身不执行任何能力Plugin 是打包、安装并归属多类能力的安装单元Hook 则拦截生命周期事件并返回策略结果只把上下文、反馈或续写片段注入。一个 Plugin 可以同时携带 Skills、MCP Servers、Apps、Hooks 和 Interface Metadata但它不会创建一套新的工具执行协议只是把包内资源投影到既有子系统Plugin Skill 进 SkillsServicePlugin MCP Server 进 McpManagerPlugin App 进 ConnectorSnapshotPlugin Hook 进 ClaudeHooksEngine。这篇面向本地开发调试场景交付可复制的配置片段与逐项验证动作MCP 服务注册、Skills 目录挂载、插件启用开关、Hooks 触发点检查并说明如何把 endpoint 与 auth.json 改到统一 Key/API 通道完成联调。读完后你应该能判断一个新能力该用哪种机制跟踪 MCP 配置从多来源合并到连接管理器的完整调用链解释 Skill 元数据与 SKILL.md 正文的两阶段加载说清 Plugin 从 Marketplace 到 Store 再到各能力子系统的过程以及区分 PreToolUse、PermissionRequest、PostToolUse 和 Stop 的不同能力。2. 四种扩展机制不是同一抽象层选型决策与源码地图最先要避免的错误是MCP、Skill、Plugin、Hook 都可以扩展 Codex所以它们只是四种插件格式。实际分层是——安装与分发层是 Plugin知识与流程层是 Skill远程能力协议层是 MCP生命周期策略层是 Hook。Plugin 位于最外层解决「一个能力包从哪里发现、是否允许安装、安装了哪个版本、包内有哪些能力、这些能力属于哪个包」MCP 解决「如何启动或连接服务、如何初始化协议、服务暴露哪些 Tool 和 Resource、如何发起调用并接收结构化结果」Skill 解决「模型何时需要一组专门说明、如何先只看到摘要再按需读完整正文、说明附带的脚本和模板在哪里」Hook 解决「某个生命周期事件发生时是否需要运行外部策略、注入上下文、阻断或续写」。因此不存在一个统一的trait Extension { async fn run(self); }它们有不同的加载时机、执行模型和安全边界。新增能力时先用下面的决策表判断需求首选机制原因让模型调用外部 API 或数据库MCP需要结构化 Tool 协议与运行时连接教模型遵循项目工作流Skill主要交付说明不需要新执行协议在工具执行前做组织级检查Hook需要拦截生命周期并允许阻断分发一组 Skill、MCP 与 HookPlugin需要安装、版本和能力归属给模型提供只读文档资源MCP Resource内容由外部服务按 URI 提供给一个 Skill 附带脚本Skill Resource脚本服务于该工作流不是通用 Tool执行后向模型反馈审计结果PostToolUse Hook需要观察工具输入和结果在模型准备结束时要求补做检查Stop Hook需要阻止结束并生成续写 Prompt还有四条实用规则只有说明没有新协议走 Skill只有远端能力不需要打包走 MCP需要多个能力一起安装走 Plugin需要影响已有执行链的某个时点走 Hook。如果一个需求同时满足多项可以组合而不是强行选择唯一机制。例如 Plugin Skill 告诉模型何时使用工单系统MCP 真正查询和修改工单Hook 阻止关闭未填写审计字段的工单。源码地图可以按四块记。MCP 配置与运行时core/src/mcp.rs合并配置、插件、扩展与 Codex Apps MCPcore/src/session/mcp.rs负责 Session 初始化、按 Step 投影和 Runtime 刷新core/src/session/mcp_runtime.rs提供请求级 McpRuntimeSnapshotcodex-mcp/src/connection_manager.rs负责 MCP Client 启动、聚合、调用和关闭codex-mcp/src/catalog.rs做多来源 Server 注册、优先级和冲突解析。Skillscore-skills/src/loader.rs加载 Skill Root、Frontmatter 和 Metadatacore-skills/src/service.rs管理快照、缓存、禁用规则与额外 Rootcore-skills/src/injection.rs处理显式选择和正文注入。Plugins 与 Appscore-plugins/src/loader.rs加载 Skill、MCP、App 和 Hook 能力core-plugins/src/manager.rs做缓存、安装、远端同步与能力解析core-plugins/src/store.rs管理 Plugin 版本目录和持久数据目录。Hooks 与刷新hooks/src/engine/discovery.rs做多来源发现、信任和 Handler 构建hooks/src/engine/dispatcher.rs做 Matcher、并发执行和稳定排序app-server/src/skills_watcher.rs监听 Skill Root 文件变化app-server/src/mcp_refresh.rs为所有活跃 Thread 排队 MCP 刷新。3. 可复制配置MCP 注册、Skills 挂载、插件开关与 Hooks 触发点这一节给出可以直接粘贴的配置片段。先区分四个术语避免把「发现」都叫「加载」Discover 是找到候选配置或资源Load 是解析并形成内部结构Inject 是把信息放进模型上下文Execute 是启动进程、请求服务或运行 Hook。不同机制的生命周期不同——MCP 是 Discover Config → Load Runtime Projection → Execute Server Startup → Inject Tool Spec → Execute Tool CallSkill 是 Discover SKILL.md → Load Frontmatter Metadata → Inject Metadata List → Select Skill → Load Body → Inject BodyPlugin 是 Discover Marketplace Entry → Install Bundle → Load Manifest → Project CapabilitiesHook 是 Discover Config → Validate Trust → Load Handler → Match Event → Execute Command → Inject or Block。这也解释了为什么 Skill 被发现不等于正文已占用上下文Plugin 已安装也不等于它的所有 MCP Server 都已连接。MCP 配置严格区分 Stdio 与 Streamable HTTP反序列化不是「哪个字段有值就尽量猜」TryFromRawMcpServerConfig会拒绝非法组合。Stdio 不允许 url、bearer_token_env_var、http_headers、oauth、oauth_resourceStreamable HTTP 不允许 args、env、env_vars、cwd。下面是一个可复制的config.toml片段注册一个只读 MCP Server[mcp_servers.readonly-demo] command python3 args [/absolute/path/readonly_mcp.py] enabled true required false startup_timeout_sec 10 tool_timeout_sec 30 enabled_tools [repository_summary] default_tools_approval_mode auto几个字段容易误解。required表示初始化失败时等待 Required Server 的调用方应把 Session 初始化视为错误它不是「这个 Server 的每个 Tool 都必须被模型调用」。supports_parallel_tool_calls是 Server 级能力承诺配置者必须保证线程安全。enabled_tools与disabled_tools是 Tool Filter先应用 Allow List 再应用 Deny List而且 Filter 不只影响模型可见列表call_tool在真正调用前还会再次检查不能靠伪造 Tool Name 绕过可见性过滤。Skills 目录挂载方面Skill Root 来自配置层、用户目录、插件与仓库。用户安装位置是$HOME/.agents/skills$CODEX_HOME/skills是兼容旧位置仓库级发现会先寻找 Project Root再按 Project Root 到 cwd 逐级加入存在的.agents/skills。一个最小 SKILL.md 必须有 YAML Frontmatter--- name: repository-map description: Inspect a repository and produce a source-backed architecture map. metadata: short-description: Build a repository architecture map --- # Repository Map 1. Read the root build and workspace files first. 2. Identify executable entry points before internal modules. 3. Trace one complete request path with exact source paths.name缺失时默认使用 SKILL.md 所在目录名description为空会导致该 Skill 加载失败。当前限制包括 name ≤ 64 字符、qualified name ≤ 128 字符、description ≤ 1024 字符。可选扩展元数据放在agents/openai.yaml解析采用 Fail Open缺失或无效就忽略不阻止合法 SKILL.md 被发现。插件启用开关方面Plugin ID 由名称和 Marketplace 组成配置中使用的 Plugin Key 表示plugin-namemarketplace-name。Manifest 路径必须以./开头、不能包含..、不能是绝对路径、解析后仍以 Plugin Root 为前缀。一个最小 Manifest{ name: repository-tools, version: 0.1.0, description: Repository inspection workflows and tools., skills: ./skills, mcpServers: ./.mcp.json, hooks: ./hooks/hooks.json, interface: { displayName: Repository Tools, shortDescription: Inspect repositories with source-backed workflows } }Hooks 触发点检查方面Hook 共有十类事件PreToolUse、PermissionRequest、PostToolUse、PreCompact、PostCompact、SessionStart、UserPromptSubmit、SubagentStart、SubagentStop、Stop。只有八类使用 MatcherUserPromptSubmit 和 Stop 忽略 Matcher。一个最小 PreToolUse Hook{ description: Block destructive recursive deletion., hooks: { PreToolUse: [ { matcher: ^(Bash|shell_command|exec_command)$, hooks: [ { type: command, command: python3 ${PLUGIN_ROOT}/hooks/check_command.py, timeout: 5, statusMessage: Checking command policy } ] } ] } }未受管 Hook 必须建立内容信任每个 Command Hook 会生成规范化 Identity 再通过 Config Fingerprint 形成sha256:hash信任状态是 Managed、Trusted、Modified、Untrusted。Enabled 与 Trusted 是两条独立状态只有Enabled and (Managed or Trusted or explicit bypass)才执行。最后是把 endpoint 与 auth.json 改到统一 Key/API 通道。Codex CLI 的认证信息通常落在~/.codex/auth.json你可以把 base URL 指向统一入口Key 用同一套{ OPENAI_API_KEY: sk-你的统一Key, OPENAI_BASE_URL: https://taotoken.net/api }如果你用的是 Claude Code 或 Cline 这类客户端配置三件套要写全Base URL 填https://taotoken.net/apiKey 填统一 KeyModel ID 按你实际要用的模型填。需要拿 Key 或看接入文档去 API Keys 管理 和 接入文档。长期跑编码或 Agent 任务可以看 Coding Plan。4. 验证请求与成功结果从 MCP 启动到 Skill 两阶段加载配置写完必须逐项验证否则你无法判断能力到底进没进 Turn。先验证 MCP。注册命令codex mcp add readonly-demo -- \ python3 /absolute/path/readonly_mcp.py查看配置和全部 Servercodex mcp get readonly-demo --json codex mcp list --json启动 Codex 后要求它「使用 repository_summary 查看当前仓库的一级目录不要运行 Shell 命令」。你应该观察到这些事件McpStartupUpdate Starting、McpStartupUpdate Ready、McpStartupComplete、Tool Call、Tool Result。McpConnectionManager 构造时对每个启用 Server 会记录 Metadata、派生 Cancellation Token、发布 Starting、构造 AsyncManagedClient、放入 clients、在 JoinSet 中并发等待启动结果全部结束后再发布 McpStartupComplete带 ready、failed、cancelled 三个列表。默认超时是启动 30 秒、Tool 300 秒两者约束不同阶段不能因为某个业务 Tool 允许运行五分钟就把 Server 启动也等五分钟。验证 Skill 的两阶段加载。先通过 App Server 的skills/list或对应客户端界面确认元数据已出现name、description、path。此时模型上下文只需要 Skill 列表项。然后在用户输入中明确提及$repository-map或使用客户端生成的UserInput::Skill观察 Turn Input → SkillInstructions → 完整 SKILL.md 正文。SkillMetadata 不保存正文只保存元数据和定位符真正注入某个 Skill 时再读取完整文件。模型可见 Skill 列表受独立上下文预算约束Core Host Skill Renderer 默认预算是有 Context Window 时取 2%、无 Context Window 时 8000 字符预算不足时按阶段降级优先尝试绝对路径、必要时尝试路径别名、截短 Description、极端情况下移除 Description、最后省略额外 Skill并生成 Warning。验证 Plugin 能力进入 Turn 的完整链Marketplace Entry → PluginsManager::install → PluginStore Atomic Install → User Config enabled → PluginsManager Cache Invalidate → load_plugin → load_plugin_skills / load_plugin_mcp_servers / load_plugin_hooks → Skill Root 进 SkillsService、MCP Registration 进 McpCatalog、Hook Source 进 Hook Discovery → Session 发布新 MCP Runtime → 下一个 Turn 看到 Skill Metadata → 匹配的生命周期事件执行可信 Hook。其中没有一步会把整个 Plugin 对象直接交给模型模型只看到投影后的能力表面。验证 Hook 触发点。安装 Plugin Hook 后普通 Plugin Source 不是 Managed SourceHook 可以被hooks/list发现但默认 Trust Status 可能是 Untrusted。客户端应展示 key、command、source、plugin id、current hash、trust status用户确认后把trusted_hash current_hash写入 User Hook State。Plugin 升级改变 Command 或 Matcher 后状态会变为 Modified需要重新确认。同一事件的多个 Hook 并发执行完成后记录 completion_order再按 configured_order 排序结果用于稳定展示。PreToolUse 多个输入改写有特殊规则最后实际完成的 Rewrite 胜出。验证 Stop Hook 续写。让 Stop Hook 第一次返回decision block、reason Run the focused tests before finishing.第二次看到stop_hook_active true后允许结束。确认 Turn 只额外采样一次不形成无限循环。如果 Hook 请求 Block 却没有有效 ReasonCore 无法构造 HookPromptMessage会记录 Warning 并忽略这次 Block——只告诉模型「不能结束」却不告诉它还缺什么容易形成无信息的无限循环。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth排障时先按「MCP Tool 不可见」「Skill 不可见」「Hook 不执行」三条线走再对照真实报错。MCP Tool 不可见依次检查Server 是否进入 Resolved CatalogServer 是否因 Auth Gate 被移除Startup 是否 ReadyTool 是否被 enabled_tools / disabled_tools 过滤Tool Meta visibility 是否包含 modelApp Connector 是否 AccessibleApp Tool Policy 是否 EnabledTool Search 是否把它放入 Deferred。注意 Configured、Projected 与 Effective MCP Server 是三种不同视图Catalog 中存在不保证 ConnectionManager 中有 Client。Skill 不可见依次检查Root 是否注册扫描是否达到上限MAX_SCAN_DEPTH6、MAX_SKILLS_DIRS_PER_ROOT2000、MAX_SKILLS_ENTRIES_PER_ROOT20000、MAX_CONCURRENT_SKILL_LOADS64SKILL.md Frontmatter 是否有效Skill 是否 DisabledProduct Restriction 是否匹配allow_implicit_invocation 是否为 falseMetadata Budget 是否省略了该项当前走 Legacy Selector 还是 Skills Extension Selector名称是否与其他 Skill 或 Connector 冲突。Hook 不执行依次检查Hook Feature 是否启用Source 是否被 allow_managed_hooks_only 排除Event Name 是否正确Matcher 是否匹配 Canonical Name 或 AliasHandler 是否 EnabledTrust Status 是否 Trusted 或 Managed是否声明了暂不支持的 Async/Prompt/Agent CommandCommand 是否超时或启动失败。对照真实报错报错常见原因处理401 UnauthorizedKey 无效、过期或 base URL 与 Key 不匹配检查 auth.json 的 OPENAI_API_KEY 与 OPENAI_BASE_URL 是否同源重新生成 Keylocal proxy failed本地代理端口未监听或进程已退出确认代理进程存活、端口一致重启客户端reading choices响应体不是预期 JSON多为 base URL 指错或返回了 HTML 错误页用 curl 直接请求 base URL 的 /v1/models 看返回结构OAuth 相关失败Stdio 不进入 OAuth 发现或 Bearer Env 与 OAuth 竞争OAuth 只适用于没有 Bearer Env 配置的 Streamable HTTP二选一OAuth 候选必须满足 Transport Streamable HTTP 且 bearer_token_env_var 未配置Stdio 不进入 OAuth 发现。Scope 来源按 CLI 显式 Scope → Configured Scope → Discovery Scope → Empty 解析只有 Discovered Scope 被 Provider 拒绝时 Codex 才可重试一次空 Scope用户显式传入或配置指定的 Scope 不能静默丢弃。Auth Status 对所有 Server 并发计算远端 Environment 的 HTTP Server 不应绕回本地网络做 OAuth 探测。如果你在 Claude Code 里遇到 OAuth 或认证问题先确认三件套写全Base URL 填https://taotoken.net/apiKey 填统一 KeyModel ID 按实际模型填。需要重新拿 Key 去 API Keys 管理配置细节看 接入文档。想先在网页里验证模型是否通用 模型对话 发一条消息最快。6. 把四类扩展接进统一通道验证模型与长期编码配置和排障都跑通后最后一步是把四类扩展接进统一 Key/API 通道做联调。MCP Server 的 endpoint、auth.json 的 base URL、Skill 声明的 MCP 依赖最终都指向同一个入口。验证模型是否通用 模型对话 发一条消息确认返回正常再回到 CLI。长期跑编码或 Agent 任务用 Coding Plan 更省心。需要管理 Key 或看接入文档去 API Keys 管理 和 接入文档。实测下来最容易踩的坑是重名 Skill 的纯名称选择。Legacy Selector 会统计 enabled skill name counts 和 connector slug counts纯名称只有在唯一时才可解析如果 Repo Skill 和 Plugin Skill 都叫 deploy只写$deploy会被跳过。但当 Skills Extension 已接管正文注入时当前实现可能选中 Catalog 顺序中的第一个启用项这不是适合调用方依赖的稳定冲突策略。跨两条实现路径都稳定的做法是使用UserInput::Skill或显式skill://Locator。后续如果两个 Selector 统一冲突语义应增加覆盖重名 Skill 与 Connector Slug 的回归测试。另一个坑是 Plugin 安装不等于当前 Turn 立刻拥有新 Tool。安装成功只保证 Bundle 已进入 Store、Config 已记录 Enablement、相关 Cache 已失效、MCP Refresh 已排队当前 Sampling 已经构造的 ToolRouter、McpRuntimeSnapshot、Skill Snapshot 不会在中途被修改新能力通常在后续 Step、后续 Sampling 或显式 Refresh 完成后出现。同理Skill 热更新不会修改正在构建的 PromptTurn 使用的是 HostSkillsSnapshot文件变化只会清 Service Cache 并通知客户端已经取得旧 Snapshot 的 Turn 仍继续使用旧元数据视图。测试命令按 crate 跑cargo test -p codex-mcp验证 MCP Catalog 与连接cargo test -p codex-rmcp-client验证 RMCP Transportcargo test -p codex-core-skills验证 Skills Loader、Render 与 Injectioncargo test -p codex-core-plugins验证 Plugin Manifest、Store 与 Managercargo test -p codex-hooks验证 Hookscargo test -p codex-core mcp验证 Core MCP 与 Tool 集成cargo test -p codex-app-server mcp_refresh验证 App Server Refresh 与 Catalog API。实际开发中先运行修改所属 crate再扩大到 Core 和 App Server 集成测试。下一篇进入多智能体与远程执行环境分析父子 Thread、Agent Control Tool、Selected Capability Roots以及多个 Environment 如何改变文件系统、MCP 和工具调用。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

AI Agent 架构设计:安全与可控性设计(OpenClaw、Claude Code、Hermes Agent 对比)——用 TaoToken 统一 Key 通道做权限边界验证 2026/10/2 15:25:57

AI Agent 架构设计:安全与可控性设计(OpenClaw、Claude Code、Hermes Agent 对比)——用 TaoToken 统一 Key 通道做权限边界验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
企业AI大模型统一接入平台有哪些?TaoToken 统一 Key 与 API 通道实测 2026/10/2 15:25:49

企业AI大模型统一接入平台有哪些?TaoToken 统一 Key 与 API 通道实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Flask生产级应用开发实战:从零搭建到部署优化指南 2026/10/2 15:25:42

Flask生产级应用开发实战:从零搭建到部署优化指南

先聊点实在的。Flask这个框架,在Python社区里几乎是无人不知。有人把它当玩具,有人拿它写原型,但真正把它用到极致的人,会发现这其实是一把非常趁手的轻量级瑞士军刀。我这两年用Flask做了不少内部工具、自动化平台的管理后台&…

阅读更多 →
从单模型服务到LLM推理平台:模型部署框架全景复盘 2026/10/2 15:25:36

从单模型服务到LLM推理平台:模型部署框架全景复盘

模型部署框架这个词,前两年还只是后端工程师和算法工程师交界地带的小众话题,现在几乎每个做 AI 的团队都得直面它:从把单个模型包装成生产服务,到搭起支撑多模型、多租户、大规模并发的 LLM 推理平台,这中间的跨越比想…

阅读更多 →
从LLM到Agent:核心循环、工具调用与记忆管理实战 2026/10/2 15:25:36

从LLM到Agent:核心循环、工具调用与记忆管理实战

1. 从"会聊天的模型"到"能办事的系统":Agent到底在解决什么问题很多人第一次接触Agent这个概念,脑子里冒出来的画面是"一个更聪明的聊天机器人"。这个理解不算错,但差得有点远。聊天机器人解决的是"信息问…

阅读更多 →
AI智能体Office套件设计与实现:从毕设选题到系统落地 2026/10/2 15:25:03

AI智能体Office套件设计与实现:从毕设选题到系统落地

AI智能体Office套件设计与实现:从毕设选题到可落地系统如果你正在为计算机科学与技术专业的毕业设计选题发愁,或者已经决定做“AI智能体 Office套件”这个方向,那这篇文章应该能帮你省下不少踩坑的时间。这个选题最大的好处是:它…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉