opencodex Cursor 路由下 Browser 插件不可用根因分析从合成 Provider 广告到 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 是面向 OpenAI Codex 与 Claude Code 的通用 Provider 代理当用户通过 Cursor 路由cursor/gpt-5.6-luna等模型调用Browser插件时浏览器无法启动——这不是权限问题而是一个发生在 Cursor 私有协议边界的工具广告 / 路由架构缺口。本文基于 devlog 260711_cursor_browser_bridge 的完整 WP1 根因链条与修复记录结合 src/adapters/cursor 源码与 tests/providers/cursor 测试完整还原为什么 Cursor 会隐藏 opencodex 注入的客户端工具、为什么改名 / 换 Provider id两类廉价修复被实测否决、以及最终被证实的修复通道——AgentRunRequest.mcp_tools。读完你将掌握 Cursor 动态工具广告协议的可路由性边界以及如何在私有协议边界上以先隔离实验、再落码的方式定位并修复此类问题。症状与初步定性不是权限问题在 Cursor 路由的模型上调用Browseropen Google and operate it失败。值得注意的是文件读写与 Shell 执行此时已经可用——此前通过providers.cursor.unsafeAllowNativeLocalExectrue修复了 Cursor 原生本地执行路径。因此这是一个不同的机制不是权限配置能解决的。WP1 根因文档的最终判定001_wp1_root_cause.md是NOT a permission problem. Class: tool-advertisement / Cursor-protocol gap (architectural). The precise class is anUNREGISTERED / SYNTHETIC-PROVIDER routing gap.其精确定义是Cursor确实会对外暴露动态广告的 MCP 工具但只限于注册在可路由 MCP Providerprovider.mcpServers之下的工具。opencodex 把 Codex 客户端工具mcp__node_repl__js以及所有其他客户端工具统一广告在合成 Provider idopencodex-responses源码常量OCX_RESPONSES_TOOL_PROVIDER见 tool-naming.ts之下Cursor 无法路由到该 Provider于是从模型的可调用目录中隐藏/拒绝了这些工具。Browser 插件运行在mcp__node_repl__js之上因此无法在 Cursor 路由下被调用浏览器无法启动。证据链Provider Debug 开启根因文档给出了三条核心证据工具清单对照Cursor 路由的 subagentcursor/gpt-5.6-luna工具清单里只有Cursor 原生 agent 工具Shell、Glob、rg、AwaitShell、ReadFile、Delete、EditNotebook、TodoWrite、WebSearch、WebFetch、GenerateImage、AskQuestion、Subagent、ListMcpResources、FetchMcpResource、SwitchMode、ApplyPatch。没有mcp__node_repl__js、没有tool_search、没有 github/sites MCP 工具。对照组同一个 subagent 换到非 Cursor 模型gpt-5.6-sol工具清单完整包括mcp__node_repl__js与全部mcp__codex_apps__*工具。差异在 Cursor 路由本身而非 subagent 框架。直连代理测试向cursor/gpt-5.6-luna发送POST /v1/responses广告一个普通 function 工具probe_client_tooltool_choicerequired。调试帧显示requestContextArgs只触发了一次opencodex 确实通过requestContextResult注入了客户端工具定义模型却启用了自己的原生shellStreamArgs并原话回复I dont have access to a probe_client_tool in this session.——注入发生了但工具从未进入模型可调用集合。为什么同一通道、不同可路由性opencodex 通过 Cursor 的RequestContext.tools通道广告客户端工具。这条通道的组装位于 native-exec.tsif (execCase requestContextArgs) { const tools [...(deps.mcpToolDefs ?? []), ...(deps.clientToolDefs ?? [])]; // ...通过 requestContextResult 注入 RequestContext.tools }而clientToolDefs由 tool-definitions.ts 的buildCursorToolDefinitions生成所有工具被映射到合成 Providerexport 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, // opencodex-responses description: tool.description, inputSchema: encodeCursorInputSchema(cursorToolInputSchema(tool)), }); }); }关键对比在于provider.mcpServers里的工具与合成opencodex-responses工具走的是同一个RequestContext.tools响应但前者可路由、可被模型调用后者不可路由、被 Cursor 从模型目录中丢弃。所以精确的结论不是Cursor 忽略所有注入工具而是Cursor 只暴露可路由 Provider 身份下的工具。这一点在更早的 devlog 362_cursor-usage-and-stall/00_overview.md 中已被明确记录为预期行为而非缺陷the empty MCP listing ... is expected: Codexs harness only has node_repl ...; opencodexs Cursor adapter only readsprovider.mcpServers——importing Codexs own MCP config into the Cursor adapter is a separate feature, not a bug, left out.另一个显而易见的替代通道早已被证伪AgentRunRequest.mcpTools字段在生成的 protobuf 中存在agent_pb.ts但 phase45 时期的一次尝试导致 Cursor 的实时解析器将请求拒绝为非法 protobuf tagparse binary: illegal tag: field no 13 wire type 7因此该赋值被移除详见 350_cursor-provider-add/129_phase45-cursor-tool-wire-compat-live-rca.md。这个死胡同结论后来被证明是编码形状错误而非通道本身不可用——后文详述。影响范围凡是依赖客户端 MCP 工具的 Codex 插件在 Cursor 路由下全部不可用Browsermcp__node_repl__js运行browser-client.mjsmcp__codex_apps__*下的 github/sites 工具。Cursor 原生文件读写/Shell 可用此为之前的修复成果。浏览器尤其无法工作因为它没有 Cursor 原生等价物而 Cursor 不会暴露node_repl。修复可行性初判与 B-1 实验设计根因文档给出的候选方向WP2 输入候选内容状态B-1让客户端工具携带 Cursor 可接受的可路由 Provider 身份例如把 opencodex 客户端桥注册成provider.mcpServers风格的可路由 MCP Provider最窄、应最先测试B-2把浏览器控制桥暴露为真正的provider.mcpServersMCP 服务器需新建桥工作量大B-3走AgentRunRequest.mcpToolsphase45 结论Cursor 解析器拒绝后文被推翻B-4接受限制浏览器/插件工作改用非 Cursor 模型零代码成本参考桥的启示与三个竞争假设在 002_wp1_experiment_plan.md 中并行 sol 搜索发现公开可用桥Hardcode84/opencode-cursor的工作方式McpToolDefinition是{name, description, input_schema, provider_identifier, tool_name}其中provider_identifier是普通字符串而非枚举/注册令牌工作桥用合成 Provider idopencode与模型可见名mcp_opencode_tool广告工具只注入RequestContext.tools无mcp.json注册模型即可调用一致性要求namemcp_provider_tool、provider_identifierprovider、tool_nametool。这推翻了合成 Provider id 本身是阻塞点的假设并引出三个待判别假设H1命名opencodex 用裸线名baretoolName而非mcp_provider_tool命名导致 Cursor 隐藏其他客户端工具H2Provider idopencodex-responses下的工具是二等公民换成工作参考桥的opencode即可调用H3行为工具其实都暴露了只是gpt-5.6-luna不会自发调用node_replexec_command因系统提示词强化而胜出。探针矩阵一次请求测完三方案buildCursorToolDefinitions增加一个环境变量门控分支OCX_CURSOR_TOOL_PROBE1在同一请求中广告同一探针工具的三种变体V_Aprovideropencodex-responsesnameprobe_a当前方案V_Bprovideropencodenamemcp_opencode_probe_btoolNameprobe_b工作参考桥方案V_Cprovideropencodex-responsesnamemcp_opencodex-responses_probe_ctoolNameprobe_c当前 Provider 预前缀名。提示词强制使用工具Call every tool available to you exactly once with minimal args, then stop.toolChoice: auto、parallelToolCalls: true捕获每个tool_call_start/tool_call_delta帧——出现哪种变体即为 Cursor 真正可调用者。A-gate 审计发现探针本身不健全关键转折独立审计sol 评审因额度失败回退 AUDIT-LOOP-01发现原独立脚本 createLiveCursorTransport.run()方案不健全protobuf-events.ts的mcpArgsFromToolCall与mapSyntheticMcpExecToToolEvents硬过滤args.providerIdentifier OCX_RESPONSES_TOOL_PROVIDER变体 Bprovideropencode永远无法以tool_call_start形式浮出且脚本绕过了真实的/v1/responses系统提示词注入buildCursorToolGuidanceSystemNote。修复方案走真实路径——向 127.0.0.1:10100 的实时代理发送POST /v1/responses回环无需 API keyisApiAuthRequiredfalsedebug:true再从/api/debug/logs环形缓冲读取原始协议帧。原始帧在OCX_RESPONSES浮出过滤之前捕获任何 Provider 身份下的 toolCall 都可见同时完整走一遍生产工具处理链。零重启、零配置写入前后校验 pid 不变。实测结果H1、H2 双双证伪指向原生工具挤占003_wp1_experiment_result.md 记录了全部三组实时实验全程零重启用户 10100 代理Provider 身份变体在隔离的 10199 第二代理上运行基线当前方案provideropencodex-responses裸名run_probeexec_commandrequestContextArgs触发工具已广告模型随即发出toolCallStarted toolCase:shellToolCallshellStreamArgsCursor 原生 ShellturnEnded零mcpToolCall。模型原文exec_commandis unavailable; ran equivalent shell command successfully ...run_probeis not available in this environment.命名变体mcp_opencodex-responses_run_probe预前缀模型回复No note-recording tool is available in this session.。命名不是门槛H1 证伪。Provider 身份变体隔离 10199OCX_CURSOR_PROBE_PROVIDERopencode复刻工作参考桥的完整方案跑 3 次[PROBE] execCaserequestContextArgs×3工具确实以opencode身份广告[PROBE] execCaseshellStreamArgs×3模型每次都用 Cursor 原生 Shell[PROBE] execCasemcpArgs×0模型从不调用我们的工具function_calls0全部 3 次。Provider 身份不是门槛H2 证伪。剩余主导假设 H4原生工具挤占Native-Tool Crowd-Out对比工作参考桥opencode-cursor向 Cursor 呈现的是没有原生工具表面的客户端模型没有原生 Shell 可用只能调用注入的mcp_opencode_*工具而 opencodex 同时广告了完整 Cursor 原生工具套件Shell/ReadFile/rg/ApplyPatch/...和注入的 MCP 工具模型始终绑定原生工具注入的 MCP 工具从不浮出。因此修复方向大概率在opencodex 如何声明客户端能力/暴露哪些原生工具而非 MCP 工具定义本身。终点判定NEEDS_HUMANB-1 被带实据地证伪属于目标明确的合法结局。后续二选一OPTION A推荐下一步实验在某一轮中抑制/最小化 Cursor 原生工具广告、保留 MCP 客户端工具定义重跑隔离探针。若模型转而调用mcp_*修复即能力声明变更——但会改变核心 Cursor 请求行为并可能回归此前刚修复的原生文件读写/Shell 路径commit 26cf884故需要人工定夺。OPTION B接受限制浏览器/mcp__codex_apps__*插件工作改用非 Cursor 模型如gpt-5.6-sol今天即可用。真正的修复填充 AgentRunRequest.mcp_tools 通道004_fix_mcp_tools_channel.md 给出了最终结论Browser-under-Cursor 可修复。病因既非 Provider 身份、也非工具命名、更非mcp_instructions而是opencodex 只通过 native-execrequestContextArgsRequestContext.tools广告客户端工具而 Cursor 不会把它注册进模型的可调用目录。填充顶层AgentRunRequest.mcp_tools通道McpTools包装器后注入的工具变得可调用纯生产代码实时端到端验证通过cursor/gpt-5.6-luna→ 最终function_call run_probe {note:hi}cursor/claude-4.5-sonnet→ 最终function_call run_probe {note:hi}。修复前所有变体裸名、mcp_前缀名、opencodeProvider、带匹配 serverName 的mcp_instructions都产生零工具调用mcp_tools是唯一生效的通道。为什么 phase45 会误判该通道phase42 也曾把工具镜像进AgentRunRequest.mcp_tools但实时 Cursor 解析器崩溃parse binary: illegal tag: field no 13 wire type 7wire type 7 非法 序列化缺陷。phase45 据此判定该通道线协议不兼容并移除phase45 RCA。真相是错误形状的赋值而非通道被拒用正确的McpToolsSchema包装器create(McpToolsSchema, { mcpTools: defs })编码后请求完全合法两个模型家族均无解析崩溃。独立佐证真实 Cursor 客户端agent-vibes确实解析AgentRunRequest.mcp_tools。落码实现在 protobuf-request.ts 的encodeCursorRunRequest中modelDetails之后追加const mcpToolDefs buildCursorToolDefinitions(visibleTools, request.toolChoice); // ... ...(mcpToolDefs.length 0 || request.suppressDefaultCursorToolCatalog true ? { mcpTools: create(McpToolsSchema, { mcpTools: mcpToolDefs }) } : {}),要点源码注释原样传达的设计约束RequestContext.toolsnative-execrequestContextArgs广告保留为第二通道两者同时填充mcp_tools使用与RequestContext.tools、事件态clientToolNames一致的cursorToolsForActivePrompt过滤集live-transport.ts避免广告出事件态不认识的工具mcpToolDefs.length 0或suppressDefaultCursorToolCatalog true时才编码McpTools显式空包装器可压制 Cursor 默认原生目录缺省字段则让已识别的 Codex 会话保留原生目录toolChoice:none与空工具均产出[]此时mcpTools保持未设置。加固通道一致性缺陷与回归测试005_hardening.md 记录了 sol 评审Heisenberg发现的唯一 blocker 及其修复BLOCKER已折叠初始版本用裸request.tools构建mcp_tools而RequestContext.tools与事件态clientToolNames用的是cursorToolsForActivePrompt(...)过滤集。对generic tool-count-demo提示词会把客户端工具收窄到裸exec_commandmcp_tools仍会广告非 exec 工具模型一旦调用即被当作未知 Responses 工具拒绝protobuf-events.ts 的mapSyntheticMcpExecToToolEvents路径。修复后encodeCursorRunRequest从同一过滤集构建mcp_tools三处保持一致。无重复执行确认返回的客户端工具调用按 call id 去重completedToolCallsprotobuf-events.tsOCX_RESPONSES的mcpArgs由 Responses 桥拦截不在本地重复运行。线形状正确create(McpToolsSchema, { mcpTools: defs })匹配McpTools.mcp_tools repeated McpToolDefinition。回归测试新增测试位于 tests/providers/cursor/cursor-blob.test.tsdescribe(Cursor AgentRunRequest.mcp_tools channel)普通提示词 →mcp_tools [mcp__node_repl__js]如use node_repl to compute 11泛化工具计数提示词use any 3 tools含exec_command 非 exec 工具→mcp_tools [exec_command]即 blocker 的过滤器一致性测试空工具 →mcpTools未设置toolChoice:none→mcpTools未设置suppressDefaultCursorToolCatalog: true→ 序列化显式空mcp_tools包装器。验证结果bunx tsc --noEmit通过bun test tests/cursor-blob.test.ts13 项通过完整bun test tests/cursor-*.test.ts265 通过 / 0 失败此前 261净增 4。修复后测试断言从 phase45 的run.mcpTools toBeUndefined反转为mcpTools.mcpTools.length 1且toolName mcp__fs__read_file。残留风险与后续通道仅在gpt-5.6-luna与claude-4.5-sonnet两个模型家族上实时验证其余 Cursor 模型家族未测包装器是标准 protobuf崩溃概率低但上线前建议跨阵容冒烟用户实时代理10100重启后才生效运行中的会话不会变化工具结果回传路径未变既有客户端工具桥function_call浮出 → Codex 本地执行 → 结果作为历史在下一轮回放建议对 node_repl → 结果 → 下次调用的多轮浏览器往返做一次冒烟若需解决Cursor 模型能主动用浏览器仍可推进 OPTION AH4 原生工具挤占实验但会改变核心 Cursor 请求行为属人工定夺范围。方法论沉淀这条根因链条本身就是一个可复用的排障范式值得提炼先定性再修区分权限问题与协议边界问题用对照实验同 subagent、不同路由锁定变量怀疑实验装置本身A-gate 审计发现探针脚本绕过了真实的系统提示词注入与 Provider 过滤从而把真实路径 原始帧读取作为唯一可信证据源一次请求测完假设矩阵用多变体广告在单次实时往返内判别 H1/H2/H3控制预算与干扰面隔离代理 10199、隔离 HOME、事后删除令牌与脚手架通道被拒可能是形状错误phase45 的不兼容结论被正确形状的McpToolsSchema包装器推翻——在私有协议边界先排除序列化缺陷再放弃通道过滤集一致性是发布门槛三个消费方RequestContext.tools、mcp_tools、事件态clientToolNames必须来自同一个可见集否则会出现广告了但调不通的静默失败。当前仓库代码中这一修复已与suppressDefaultCursorToolCatalog、cursorToolsForActivePrompt过滤等加固一同落地构成 opencodex Cursor 适配器对客户端工具可调用性的最终形态。【免费下载链接】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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
