OpenCodex Cursor 路由下 Browser 插件失效的根因分析与修复:打通 AgentRunRequest.mcp_tools 工具注册通道

发布时间:2026/9/23 21:49:33
OpenCodex Cursor 路由下 Browser 插件失效的根因分析与修复:打通 AgentRunRequest.mcp_tools 工具注册通道
【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载导读在 OpenCodex 的多 Provider 代理体系中把流量路由到 Cursor 模型如cursor/gpt-5.6-luna后Browser插件会静默失效——模型声称没有可用工具随后退回到 Cursor 原生 Shell。本篇基于仓库内 devlog 系列 260711_cursor_browser_bridge 的完整调查记录还原从症状 → 机制地图 → 根因定位 → 实弹证伪 → 修复 → 加固的全过程真正的原因并非权限配置而是 Cursor 二进制协议中AgentRunRequest.mcp_tools通道未被正确填充修复后在gpt-5.6-luna与claude-4.5-sonnet两个模型家族上均实测可用。读完本文你将理解客户端 MCP 工具在 Cursor 路由下的注册与调用链路、McpTools包装层的正确线格式以及如何规避线格式错误被误判为通道不可用的典型排查陷阱。问题现象Cursor 路由模型上Browser失效且不是权限问题在 OpenCodex 的 Cursor 适配器src/adapters/cursor/**中Browser插件在 Cursor 路由模型上表现为让模型打开 Google 并操作它会失败模型反馈工具不可用。早期的排查曾把原因归到权限上并通过配置providers.cursor.unsafeAllowNativeLocalExectrue放开了 Cursor 本地执行权限文件读写、Shell 等均走 Cursor 原生工具。该开关的实现位于 exec-policy.ts 与 native-exec.tscursorUnsafeNativeLocalExecEnabled仅在provider.unsafeAllowNativeLocalExec true时返回on。但注意——它只管辖 Cursor 原生 read/write/shell 执行路径与 Browser 插件的驱动机制完全不同。文件读写修复后 Browser 依旧失败说明存在另一个独立的机制缺口。机制地图Browser 插件如何寄生在客户端 MCP 工具上深入代码阅读后调查组确认了一个关键事实Browser 插件并不是一组专用工具而是通过客户端 MCP 工具mcp__node_repl__js运行browser-client.mjs来驱动的。要让 Cursor 路由的模型使用它OpenCodex 必须允许 Cursor 模型调用一个客户端 Responses/MCP 工具其 provider 标识为OCX_RESPONSES_TOOL_PROVIDER定义在 tool-naming.tsexport const OCX_RESPONSES_TOOL_PROVIDER opencodex-responses;在src/adapters/cursor内部存在两条可能的调用路径流式 tool_callCursor 发出 interactiontoolCall由protobuf-events.ts呈现为tool_call_start/tool_call_delta事件Codex 本地执行结果在下一个请求中以历史回放返回。原生 mcpArgsCursor 服务端希望同步执行 MCP 工具。对于OCX_RESPONSES_TOOL_PROVIDERlive-transport.ts的planMcpArgsHandling会把它呈现为 tool_call 事件、结束 turn-1并期待真实结果出现在下一次/v1/responses请求中而 native-exec-mcp.ts 中tool not found是带类型的toolNotFound返回而非抛错。客户端工具定义通过buildCursorToolDefinitions生成并对外广告tool-definitions.tsexport function buildCursorToolDefinitions( tools: readonly OcxTool[] | undefined, toolChoice?: OcxRequestOptions[toolChoice], ): McpToolDefinition[] { if (!tools?.length) return []; return tools.filter(tool cursorToolAllowedByChoice(tool, toolChoice, tools)).map(tool { const wireName cursorToolWireName(tool); return create(McpToolDefinitionSchema, { name: wireName, toolName: wireName, providerIdentifier: OCX_RESPONSES_TOOL_PROVIDER, description: tool.description, inputSchema: encodeCursorInputSchema(cursorToolInputSchema(tool)), }); }); }McpToolDefinition的五个字段来自对可工作公开桥接实现的线协议分析为name、description、input_schema、provider_identifier、tool_name其中provider_identifier是普通字符串而非枚举/注册令牌。当时的开放问题是像mcp__node_repl__js这样的客户端 MCP 工具是否真的被广告给了 Cursor如果从未广告模型自然无法调用浏览器。根因定位合成 Provider 不可路由导致的工具广告缺口WP1 阶段通过三组带 provider debug 的实验把根因锁定详见 001_wp1_root_cause.md工具清单对比cursor/gpt-5.6-luna子代理的工具清单里只有 Cursor 原生工具Shell、Glob、rg、ReadFile、ApplyPatch、WebSearch、Subagent 等没有mcp__node_repl__js对照组在非 Cursor 模型gpt-5.6-sol上则是完整 MCP 套件。差异来自 Cursor 路由本身而非子代理环境。直接代理测试向cursor/gpt-5.6-luna直接 POST/v1/responses广告一个普通函数工具probe_client_tooltool_choice必选。debug 帧显示requestContextArgs确实触发了一次OpenCodex 通过requestContextResult注入了客户端工具定义但模型仍回复I dont have access to a probe_client_tool in this session——注入发生了工具却没有进入模型可调用目录。结论被精炼为这是一个UNREGISTERED / SYNTHETIC-PROVIDER 路由缺口。Cursor 确实会呈现动态广告的 MCP 工具但只限于注册在可路由 MCP providerprovider.mcpServers下的工具。OpenCodex 把 Codex 客户端工具全部挂在合成 provider idopencodex-responses下Cursor 无法路由到该 provider因此从模型可调用目录中隐藏/拒绝了这些工具。unsafeAllowNativeLocalExec开关对这类工具无效——它只管辖原生执行属于不同机制。此前的 devlog 362_cursor-usage-and-stall 也明确记载Cursor 适配器只读取provider.mcpServers导入 Codex 自身的 MCP 配置是独立功能而非 bug。而另一条候选通道AgentRunRequest.mcpTools曾被尝试过但被放弃详见后文 phase45 复盘。WP1 实弹实验逐一证伪廉价假设在进入修复前调查组设计了严格的实验矩阵来区分三种假设决策表见 002_wp1_experiment_plan.md假设内容若成立修复方向H1命名模型面对的名字未遵循mcp_provider_tool约定被 Cursor 丢弃统一前缀命名H2provider idopencodex-responses是二等 provider换用参考实现同款opencodex即可更换 provider 标识H3行为工具其实都可见只是模型不主动调用 node_repl系统提示强化而非协议修复实验的关键方法学A-gate 审计修正后的版本是必须走真实路径——向 127.0.0.1:10100 的 live 代理 POST/v1/responsesdebug:true并从/api/debug/logs环形缓冲区读取原始协议帧。原始帧在OCX_RESPONSES呈现过滤器之前就被捕获因此任何 provider 标识下的 toolCall 都可观测同时系统提示注入、cursorToolsForActivePrompt过滤等生产路径被如实执行。provider 身份变体实验则在隔离的第二代理端口 10199独立OPENCODEX_HOME/CODEX_HOME上运行绝不干扰 live 会话。三组实验结果003_wp1_experiment_result.md基线live 10100requestContextArgs触发、工具已广告但模型发出的是toolCallStarted toolCase:shellToolCallshellStreamArgsCursor 原生 Shell零次mcpToolCall并回复 exec_commandis unavailable; ran equivalent shell command。命名变体live 10100工具名改为mcp_opencodex-responses_run_probe与 Cursor 展示约定前缀一致——仍不可调用。H1 证伪。Provider 身份变体隔离 10199通过 env 门控脚手架OCX_CURSOR_PROBE_PROVIDERopencode完全复刻可工作参考桥接provideropencode、namemcp_opencode_tool——3 次运行中requestContextArgs均触发、模型 3 次都走原生shellStreamArgs、mcpArgs零次、function_calls0。H2 证伪。由此得出provider 标识字符串和命名前缀都不是问题所在合成 provider 的广告通道本身工作正常requestContextArgs会触发并携带定义。剩余的首要假设 H4 是原生工具挤出效应native-tool crowd-out每次探测中模型都拥有并优先绑定 Cursor 原生工具套件把注入的 MCP 工具视为不存在参考桥接之所以可用是因为它对 Cursor 呈现为没有原生工具面的客户端模型别无选择只能用注入的mcp_opencode_*。按目标验收标准B-1 被带有可信 live 证据地证伪是一个合法终态处置标记为 NEEDS_HUMAN。真正修复填充AgentRunRequest.mcp_tools顶层通道在 004_fix_mcp_tools_channel.md 中调查组找到了被遗漏的真相Browser-under-Cursor 是可以修复的。原因不是 provider 身份、不是命名、不是mcp_instructions而是 OpenCodex 此前只通过 native-exec 的requestContextArgs即RequestContext.tools广告客户端工具而 Cursor不会把该通道的内容注册进模型可调用目录。填充顶层AgentRunRequest.mcp_tools通道McpTools包装层后注入的工具即可被调用。为什么 phase45 错误地放弃了这条通道此前 devlog _fin/350_cursor-provider-add 的 phase42 也把工具镜像进过AgentRunRequest.mcp_tools但 live Cursor 解析器直接崩溃parse binary: illegal tag: field no 13 wire type 7wire type 7 是非法值说明是序列化缺陷。phase45 因此判定该通道线不兼容并移除。复盘证明那是赋值形状错误不是通道被拒绝——用正确的McpToolsSchema包装层create(McpToolsSchema, { mcpTools: defs })编码后请求合法gpt-5.6-luna与claude-4.5-sonnet均无解析崩溃。修复代码已合入当前仓库在 protobuf-request.ts 的encodeCursorRunRequest中先基于过滤后的可见工具集构建定义该逻辑被提到散播点之外以便做精确的字节估算// Hoisted out of the mcp_tools spread below so the estimate can read the same // filtered definitions the wire carries. Both helpers are pure. const mcpToolDefs buildCursorToolDefinitions(visibleTools, request.toolChoice);然后在构造AgentRunRequest时protobuf-request.ts// Mirror the client (Responses) tool definitions into the top-level AgentRunRequest.mcp_tools // channel. Advertising them ONLY via native-exec requestContextArgs (RequestContext.tools) is // insufficient: cursor models report those tools as unavailable and fall back to native tools. // Populating mcp_tools registers them into the models callable catalog (verified live: the // model actually calls the injected tool on gpt-5.6-luna and claude-4.5-sonnet). ... // An explicitly empty McpTools wrapper (bare API callers) suppresses Cursors default // native catalog; an absent field lets identified Codex sessions keep it (devlog 260826 040). ...(mcpToolDefs.length 0 || request.suppressDefaultCursorToolCatalog true ? { mcpTools: create(McpToolsSchema, { mcpTools: mcpToolDefs }) } : {}),要点双通道并存RequestContext.tools广告native-execrequestContextArgs保留为第二通道两条通道同时填充McpTools.mcp_tools repeated McpToolDefinition的线形状与create(McpToolsSchema, ...)完全匹配。空与toolChoice:none的处理两者都产生[]此时mcpTools字段保持不设置除非显式要求抑制默认目录。验证结果修复后gpt-5.6-luna与claude-4.5-sonnet均产生最终function_call run_probe {note:hi}修复前的所有变体裸名、mcp_前缀名、provideropencode、mcp_instructions匹配 serverName全部零工具调用。独立佐证真实 Cursor 客户端如 agent-vibes确实解析AgentRunRequest.mcp_tools通道。加固让三条通道共享同一份可见工具集修复合入后紧接着做了生产化加固005_hardening.mdsol 评审发现并折叠了一个 blocker问题mcp_tools最初由原始request.tools构建而RequestContext.toolslive-transport.ts与事件状态clientToolNameslive-transport.ts都用cursorToolsForActivePrompt(...)过滤后的集合构建。对generic tool-count demo这类会把可见客户端工具收窄到裸exec_command的提示词mcp_tools若仍广告非 exec 工具模型一旦调用就会被protobuf-events.ts当作未知 Responses 工具拒绝。修复encodeCursorRunRequest改为从同一个cursorToolsForActivePrompt(request.tools, activePromptText(request), request.toolChoice)可见集合构建mcp_tools保证三条通道mcp_tools、RequestContext.tools、事件状态名一致。边界情况返回的客户端工具调用只呈现一次并按 call id 去重completedToolCalls见 protobuf-events.ts 中mcpArgsFromToolCall仅放行OCX_RESPONSES_TOOL_PROVIDER的过滤器以及mapSyntheticMcpExecToToolEvents的同款过滤OCX_RESPONSES的 mcpArgs 由 Responses 桥拦截、不本地执行因此无双重执行。性能影响可忽略小规模同步过滤 编码。回归测试与验证新增的回归测试位于 tests/providers/cursor/cursor-blob.test.ts 的 Cursor AgentRunRequest.mcp_tools channel 描述块覆盖四条边界普通提示词 →mcp_tools [mcp__node_repl__js]浏览器工具正常广告generic tool-count 提示词use any 3 tools含exec_command 非 exec 工具→mcp_tools [exec_command]过滤一致性即 blocker 的测试空工具 →mcpTools不设置toolChoice:none→mcpTools不设置。验证结果bunx tsc --noEmit退出码 0bun test tests/cursor-blob.test.ts13 项通过完整bun test tests/cursor-*.test.ts265 项通过 / 0 失败加固前为 261 项新增 4 项。live 代理10100在整个过程中未被重启无新增 live Cursor 探测消耗。残余风险与落地注意模型覆盖mcp_tools通道在gpt-5.6-luna与claude-4.5-sonnet上端到端验证通过其他模型家族未实测。McpTools包装层是标准 protobuf崩溃概率低但大规模发布前建议对 Cursor 全家桶做一次宽泛 live 冒烟。生效时机live 代理10100需要重启后才加载该修复运行中的会话在重启前行为不变。返回路径未变工具结果的返回链路function_call呈现 → Codex 执行 → 结果作为历史在下一轮回放没有改动仅建议对完整多轮浏览器往返node_repl→ 结果 → 下一次调用做一次冒烟。实验卫生所有临时脚手架OCX_CURSOR_PROBE_*env 分支、探针脚本在提交前已移除git status干净。结论一次线格式 vs 通道可用性的方法论启示这条调查链的价值在于两处其一问题被精确归类为合成 provider 路由缺口——Cursor 只把注册在可路由 provider 下的工具放进模型目录opencodex-responses这个合成标识不足以让mcp__node_repl__js可调用其二通道曾被拒绝不等于通道不可用——phase45 的崩溃源于mcp_tools字段赋值形状错误非法的 wire type改用正确的McpToolsSchema包装层后同一通道完全可用。修复打通后所有依赖客户端 MCP 工具的 Codex 插件Browser 的mcp__node_repl__js、mcp__codex_apps__*的 github/sites 工具在 Cursor 路由下均可注册进模型可调用目录而unsafeAllowNativeLocalExec管辖的 Cursor 原生读/写/Shell 路径保持原策略不变。参考路径调查记录000_plan.md、001_wp1_root_cause.md、002_wp1_experiment_plan.md、003_wp1_experiment_result.md、004_fix_mcp_tools_channel.md、005_hardening.md核心实现protobuf-request.ts、tool-definitions.ts、tool-naming.ts、live-transport.ts、protobuf-events.ts、native-exec.ts、exec-policy.ts回归测试tests/providers/cursor/cursor-blob.test.ts关联历史350_cursor-provider-add、362_cursor-usage-and-stall/00_overview.md赞分享【免费下载链接】opencodexUniversal provider proxy for OpenAI Codex Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code项目地址https://gitcode.com/gh_mirrors/ope/opencodex点击查看免费下载相关推荐opencodex Cursor 路由下 Browser 插件不可用根因分析从合成 Provider 广告到 AgentRunRequest.mcp_tools 通道修复opencodex Cursor 路由下 Browser 插件不可用根因分析从合成 Provider 广告到 AgentRunRequest.mcp_toolMoneyPrinterTurbo 离线语音合成3 步本地部署批量生成 AI 短视频MoneyPrinterTurbo 离线语音合成3 步本地部署批量生成 AI 短视频 MoneyPrinterTurbo 把选题写稿、配音、找素材、压字幕Cursor Provider 工具调用静默失败与 MCP 空列表opencodex 根因分析RCA与修复规格全解Cursor Provider 工具调用静默失败与 MCP 空列表opencodex 根因分析RCA与修复规格全解 本文基于 opencodex 仓库内创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考