最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Codex 是否支持 MCP 的 notifications/tools/list_changed 通知?
时间:2026-09-16 10:24:01 编辑:袖梨 来源:一聚教程网
截至当前公开资料与 openai/codex issue #10105 所反映的实现状态,Codex 可以接收 MCP 的 `notifications/tools/list_changed`,但不会因此自动重新获取并更新该 Server 的工具列表。相关处理函数只记录通知参数,没有触发 `tools/list` 刷新。这个结论不等于 Codex 不支持 MCP,而是运行期动态工具变更这一环尚未形成完整闭环;对应 issue 仍处于开放 enhancement 状态。
“支持 MCP”与“支持动态工具刷新”不是同一件事
一个 MCP 客户端支持连接 Server、初次列出工具和调用工具,并不代表它实现了所有可选通知。动态工具更新至少包含四个环节:初始化时识别 `tools.listChanged` 能力、订阅或接收通知、收到通知后重新调用 `tools/list`、把新快照同步到当前会话和模型上下文。
Codex 已经能够使用 MCP 工具,问题集中在最后两个步骤。issue 报告给出的源代码片段显示,`handle_tool_list_changed` 收到参数后执行 tracing 日志,未调用列表刷新逻辑。因此服务端日志和网络抓包可以证明事件到达,但 Codex 仍继续使用初始化时获取的工具定义。
官方文档能证明什么,不能证明什么
OpenAI Docs 公开说明了 Codex 和 OpenAI 平台可集成 MCP 工具,也描述了工具发现与调用能力。但目前没有一份公开产品文档承诺 Codex 会处理 `notifications/tools/list_changed` 并在运行中热替换工具集合。不能仅凭“支持 MCP”推导出“支持所有 MCP 通知”。
更直接的产品实现证据来自 openai/codex 官方仓库的 issue #10105。该 issue 标题就是请求支持该通知,标签为 enhancement 与 mcp,状态为 Open。报告指向处理函数,说明当前行为是记录事件而不更新列表。issue 是问题跟踪信息,不是稳定 API 合同,因此文章结论必须绑定时间和版本,未来合并修复后需要重新验证。
为什么服务端发送成功,Codex 仍看不到新工具
按照 MCP 语义,list-changed 通知只表示缓存过期,不包含新的完整工具定义。客户端必须再发起 `tools/list`。若 Codex 只打印:
notifications/tools/list_changed -> params: ...
那么协议链路只完成了“通知到达”。动态启用的新工具不会自动出现在模型可用工具集合中,被禁用的工具也可能继续保留在旧快照中。模型通常无法凭一条日志自行发起协议级重发现,因为这属于客户端基础设施职责,而不是模型决策。
如何复现和确认当前行为
准备一个能动态启用或禁用工具的 MCP Server。首次连接时只暴露 `tool_a`,让 Codex 完成发现。随后在不重启连接的情况下增加 `tool_b`,服务端发送标准通知。观察三类证据:Server 确实发布了事件;Codex 日志出现对应方法;通知之后是否产生新的 `tools/list` 请求。
若前两项存在而第三项缺失,问题就在客户端刷新逻辑。进一步让 Codex 尝试调用 `tool_b`,它通常不会把该工具视为当前可用能力。断开并重新连接 MCP Server 后,初始化发现重新运行,`tool_b` 才可能出现,这也是常见临时绕过方式。
测试时要记录 Codex 版本、传输方式、MCP 协议版本和 Server SDK 版本。只看 UI 没有更新不够,因为 UI、内部缓存和模型实际工具集可能是三个不同状态;最有力的证据是通知后没有新的 list 请求。
服务端是否需要改变通知格式
不需要为了 Codex 自定义一个带完整 tools 数组的通知。标准方法名和空参数结构已经足够表达列表失效。把差异塞进 params 会形成私有协议,其他客户端不会理解,也可能在 Codex 正式支持标准通知后产生兼容问题。
服务端仍应正确声明 `tools: { listChanged: true }`,先更新权威注册表,再发送通知,并保证通知后的 `tools/list` 返回新集合。这样既满足规范,也能被已支持动态刷新功能的客户端使用。Codex 当前未重拉不应成为破坏标准实现的理由。
当前可用的工程绕过方案
第一种方案是断开并重新连接 MCP Server,让 Codex 重新执行初始化发现。这适合低频配置变化,但会中断连接状态和在途调用。第二种方案是保持工具集合稳定,把动态条件放进工具参数或调用结果中,例如始终暴露 `run_task`,调用时再判断工作区是否满足条件。
第三种方案是暴露稳定的能力查询工具,让模型在执行前读取当前功能状态。不过查询工具不能让一个未被发现的新工具突然可调用,它更适合对既有工具做可用性说明。第四种方案是由外部编排器检测 Server 版本变化,并显式重建 Codex 的 MCP 连接。
选择绕过方式时要考虑风险。如果旧快照包含已经撤销权限的工具,服务端必须在每次 `tools/call` 时重新鉴权,不能依赖客户端及时刷新。动态删除工具后,调用路由也应返回明确的不可用错误,而不是继续执行旧委托。
不建议用动态增删表达瞬时业务状态
工具集合适合表达长期可发现的能力,不适合表示每秒变化的对象状态。例如文件是否存在、测试是否通过或设备是否在线,通常应作为工具调用时的验证条件或 Resource 内容,而不是不断添加和删除工具。否则客户端需要频繁重建模型上下文,容易产生通知风暴和竞态。
若某个工具只在特定工作区成立,可以保持名称和 schema 稳定,在描述或调用结果中返回当前前置条件;真正涉及权限收回时,服务端在调用阶段强制拒绝。只有插件安装、功能模块启停或 schema 版本切换这类能力层变化,才更适合使用 tools list changed。
实现完整支持需要改哪些部分
客户端处理函数不能只写日志。它需要把对应 Server 的工具缓存标记为陈旧,合并重复事件,重新获取所有分页,验证名称与 schema,然后原子替换缓存。若刷新发生在模型回合中,还需要定义新工具从哪个回合开始可见,以及已经生成但尚未执行的旧工具调用如何处理。
on tools_list_changed(server_id):
invalidate(server_id)
tools = list_all_pages(server_id)
validate(tools)
replace_snapshot(server_id, tools)
rebuild_model_tool_view()
刷新失败时应保留旧快照并标记 stale,按退避重试;高风险工具可以暂停调用。多个 MCP Server 存在同名工具时,重建过程还要保持稳定的消歧名称,避免一次刷新改变模型看到的其他 Server 工具。
会话中的动态工具存在额外一致性问题
即使未来实现重拉,通知到达的时机仍需谨慎处理。模型可能已经基于旧工具列表开始推理,或者已输出一个即将调用的工具。客户端不应在执行途中悄悄把同名工具替换成不兼容 schema。更安全的方式是在回合边界应用新快照,或为工具定义附加版本并验证调用所基于的版本。
工具被删除时,在途调用可按服务端策略完成或取消;新调用必须按最新授权判断。工具新增时,可以在下一次模型请求中加入定义,不必修改已经提交的推理请求。这些策略应有日志和测试,而不是简单在共享向量上原地修改。
如何跟踪支持状态
应同时查看 OpenAI Docs、Codex 版本发布信息和官方仓库 issue。OpenAI Docs 用于确认公开支持范围,issue 用于观察具体缺口与实现进度。只有 issue 关闭还不够,需要检查关闭原因、关联变更和实际发布版本;随后用动态 Server 做一次端到端复测。
不要依据其他 MCP 客户端已经支持该通知,推断 Codex 也支持。不同客户端独立实现协议可选能力。也不要把日志中出现方法名视为功能完成,真正的验收标准是通知后发生新的 `tools/list`,且下一次模型回合看到正确工具集合。
测试清单
客户端支持测试应覆盖新增、删除、禁用、启用和 schema 修改;连续通知应合并,刷新中再变化应补拉一轮;分页列表必须完整替换;刷新失败不能清空全部工具;断线重连应恢复最新状态。还要验证权限收回后旧工具即使留在缓存中也无法被成功调用。
对于 Codex 的当前行为,可保留一份最小复现 Server 和日志,以便新版本发布后重复测试。若观察到通知后出现 list 请求,再进一步确认工具真正进入模型上下文,而不是只更新内部缓存。
结论
当前公开证据表明,Codex 能接收到 `notifications/tools/list_changed`,但尚未完成自动刷新工具列表的处理。指定 issue 仍是开放的 enhancement,OpenAI Docs 也没有给出该动态能力的正式承诺。因此,生产系统不应依赖通知让 Codex 在现有连接中立即获得新工具。
服务端应继续遵守标准通知,并在调用阶段保持鉴权;应用可暂时通过重连、稳定工具接口或外部编排刷新规避。未来判断是否已经支持时,要以官方文档、实际发布版本和端到端网络证据共同验证,而不是只看通知日志。