adapters: write a unique evox-product MCP config and stdio shim - #619
adapters: write a unique evox-product MCP config and stdio shim#619autogame-17 wants to merge 1 commit into
Conversation
Desktop Connect already shells out to setup-hooks, but the installer only wrote hooks. External Claude/Codex need a managed evox-product stdio proxy that fails closed until Desktop publishes a loopback grant.
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Sentinel 已审核此变更,并发现 4 个已核验问题。 另有 14 个需要人工确认的风险;它们不阻塞合并,但开发 agent 必须 review advisory 评论并逐条确认。 开发 agent 查询详情: 调用 MCP 工具 由 Sentinel 审核 · 目标提交 df5dcb6e5095 |
|
Sentinel 保留了 14 个尚未确认的审核候选。它们不阻塞合并;单一猜测、缺少变更行证据或纯 checklist 的候选会统一降为 P3。
需要完整证据时,可用行末 由 Sentinel 审核 · 目标提交 df5dcb6e5095 |
| if (!req || req.jsonrpc !== '2.0' || !req.method) { | ||
| return rpcError(req && req.id, 'invalid JSON-RPC request'); | ||
| } | ||
| if (req.id === undefined) return null; |
There was a problem hiding this comment.
所有 JSON-RPC 通知都被静默丢弃
🟠 严重程度:中(P2)
dispatch() 在发现 req.id === undefined 时直接返回,导致所有 JSON-RPC 通知都不会经过 readGrant() 和 postJson()。因此 Desktop 桥接端只能收到带 ID 的请求,收不到用于推进或回滚会话状态的初始化、取消等通知。
Finding:finding_0186b48a46b22a089ee1c1dd
| try { | ||
| if (fs.existsSync(filePath)) data = readJsonFile(filePath); | ||
| } catch { | ||
| data = { mcpServers: {} }; |
There was a problem hiding this comment.
JSON 解析失败时安装会静默覆盖整个现有配置
🟠 严重程度:中(P2)
readJsonFile 的任意解析异常都会把 data 重置为仅含空 mcpServers 的默认值,随后正常写回;原文件中的其他服务器配置和原始内容被不可逆覆盖,返回值仍报告 changed: true。
Finding:finding_66bd0497b647cbf97f3537e7
| } catch { | ||
| data = { mcpServers: {} }; | ||
| } | ||
| if (!data || typeof data !== 'object') data = {}; |
There was a problem hiding this comment.
顶层 JSON 数组会导致安装假成功但配置未写入
🟠 严重程度:中(P2)
顶层结构校验只检查 typeof data === 'object',没有排除数组。代码向数组对象添加 mcpServers 命名属性,但 JSON.stringify 不序列化数组的命名属性,因此落盘仍为 [],安装函数却返回成功。
Finding:finding_60637b4baaca2fcd216cb06a
| lines.splice(start, section.end - start, ...blockLines); | ||
| } else { | ||
| // Prepend so a later user append still lands in the existing [features] | ||
| // table, and so our ownership comment is never inside that table. |
There was a problem hiding this comment.
重复安装 Codex 配置会删除 managed table 中的用户扩展字段
🟠 严重程度:中(P2)
找到已托管 section 后,安装逻辑用新 block 替换从 section 开始到下一 section 的全部行,而新 block 仅包含 command 和 args。同一 table 内的 startup_timeout_sec 等非 Evolver 字段会被静默删除。
Finding:finding_3f1d8cba3d74220ae42b5fd9
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Summary
setup-hooks now owns a unique evox-product MCP writer for Claude Code and Codex, plus a stdio shim that proxies to Desktop only after a loopback grant file exists.
What changed
.mcp.jsonmcpServers.evox-productand Codex[mcp_servers.evox-product]with an ownership markerevox-product-shim.jsas an on-demand stdio proxy; it never listens on a port~/.evox/product-bridge.json(orEVOX_PRODUCT_BRIDGE_GRANT_FILE) is missing, not loopback, or has the wrong schemaX-Evox-Product-Bridge-Granton every RPC and a fresh nonce only ontools/callHow to test
node --test test/productBridgeMcp.test.js test/adapters.test.js test/adaptersSyntax.test.jsevolver setup-hooks --runtime=claude-code --root="$PWD" --forcethen inspect.mcp.jsonevox-productcommand points atsrc/adapters/scripts/evox-product-shim.jsRisk
Medium -- this changes the adapter execution bridge used by Claude Code and Codex setup-hooks. It writes a new MCP server entry into user runtime configs and introduces a loopback HTTP proxy. Desktop still does not write
.mcp.json.Harness/evaluator governance
Upstream governance surface: adapter execution bridge (
src/adapters/*setup-hooks install/verify/uninstall plus the evox-product stdio shim)Downstream EvoX impact: desktop AgentBridge Connect can now get a real
evox-productMCP entry from setup-hooks; Desktop later publishes~/.evox/product-bridge.jsonand should treatevox-productas the connected needleRollout-local scope: opt-in operator command only; existing installs stay unchanged until the operator reruns setup-hooks
Promotion boundary: lands as default setup-hooks behavior on merge; no shadow cohort and no automatic rewrite of existing user MCP servers
Evaluator mismatch sets: verification now distinguishes missing, user-owned, and managed evox-product entries; observation/action/repair/evidence/belief evaluator sets are unchanged
Non-regression evidence:
test/productBridgeMcp.test.jscovers merge/uninstall ownership, loopback grant rejection, grant/nonce headers, and stdio fail-closed;test/adapters.test.jsstill covers Claude/Codex hook install and Codex TOML [features] editsFix-severity review: medium
Owner approval: adapter/setup-hooks owner review required before merge
Security boundary: writes only a marked evox-product MCP entry; shim refuses non-loopback URLs, symlink grant files, and oversized bodies; grant token is sent as a header and not logged; no new secrets store
Rollback: revert this PR; operators can rerun
setup-hooks --uninstallto remove only managed evox-product entriesLive promotion: no
Autonomous evaluator self-editing: no
Test plan
node --test test/productBridgeMcp.test.js test/adapters.test.js(92 passed)node --test test/adaptersSyntax.test.js(entry-point scripts parse)Self-check
src/, matching sibling hook scripts.public.manifest.jsonis not present in this checkout or git tree;package.jsonalready includessrc/.Related
Stacked on #618