背景
在处理 #667(Claude native permissionMode observed projection 漂移)时,已确认:
- Claude runtime 发起的 MCP tool approval 属于
can_use_tool 同一 permission family,已纳入 #667。
mcp_server_elicitation 是独立 request family,用于 MCP server 的表单补充、URL/OAuth continue 等动作,不属于 #667 的 permission-mode drift 修复范围。
后续调研基于 upstream openai/codex main(9e552e9d15ba52bed7077d5357f3e18e330f8f38, 2026-07-12 复核)确认:
- 本仓库已经有 dedicated
mcp_server_elicitation request typing / render / response flow,不存在“还把它当成 generic approval 没接住”的问题。
- 当前主题真正剩余的两个执行面已经拆成子单:
#669:mcpServer/elicitation/request 承载 MCP tool approval 时的 _meta.codex_approval_kind / persist contract。
#670:mcpServer/oauth/login -> mcpServer/oauthLogin/completed 独立 app-server lifecycle。
当前状态:#669 已实现、验证、关闭并回卷;#670 已完成计划闭包并切到 status:implementable-now,成为下一步执行 worker。
目标
- 单独审视
mcp_server_elicitation request family 与相邻 MCP OAuth lifecycle 的产品语义、桥接 contract 和前台展示边界。
- 确认它与
can_use_tool / permissions_request_approval 的职责分层在代码与文档里都保持清晰。
- 把剩余执行面拆成稳定子单,避免后续再次把不同 request/RPC family 混模。
- 在子单完成后收拢总结果,并判断本父单是否可关闭。
范围
mcpServer/elicitation/request 的 request type / semantic kind / prompt 构造 / render / response flow 后续 contract 审视。
mcpServer/oauth/login -> mcpServer/oauthLogin/completed lifecycle 的本地承接缺口。
- 与 Feishu 卡片、orchestrator request routing、adapter metadata、远端状态机文档的契约边界。
非目标
- 不并入
#667 的 Claude permissionMode observed projection 修复。
- 不把
mcp_server_elicitation 改造成通用权限审批流。
- 不处理
permissions_request_approval 或 can_use_tool 的主链改造。
- 不在本父单直接承载生产补丁实现;生产变更在子单完成。
完成标准
- 父单不再停留在 raw follow-up 状态,研究结论、边界和下一步执行面已写回 issue。
mcp_server_elicitation 相关剩余问题被拆成边界清晰的子 issue,而不是继续混在一个大而泛的提醒单里。
- 父单明确记录:
- 当前实现已经覆盖了哪些部分。
- 真正仍未覆盖的 contract / lifecycle 是什么。
- 推荐的执行顺序和依赖关系。
- 相关子单关闭后,本父单可据此做结果收拢和 close judgment。
相关文档
docs/general/codex-mcp-app-server-protocol.md
docs/inprogress/codex-app-server-state-machine-audit.md
docs/general/remote-surface-state-machine.md
docs/general/feishu-card-ui-state-machine.md
- upstream app-server README:
https://github.com/openai/codex/blob/main/codex-rs/app-server/README.md
涉及文件
internal/adapter/codex/translator_helpers_request.go
internal/adapter/codex/translator_requests_test.go
internal/adapter/codex/translator_commands.go
internal/adapter/codex/translator_observe_server.go
internal/core/agentproto/types.go
internal/core/orchestrator/service_request.go
internal/core/orchestrator/service_request_mcp.go
internal/core/orchestrator/service_request_presentation.go
internal/core/control/feishu_request_semantics.go
internal/core/control/feishu_request_bridge.go
internal/core/control/feishu_commands.go
internal/adapter/feishu/projector/request.go
internal/app/daemon/app_ingress.go
docs/general/codex-mcp-app-server-protocol.md
docs/inprogress/codex-app-server-state-machine-audit.md
docs/general/remote-surface-state-machine.md
docs/general/feishu-card-ui-state-machine.md
调研结论
- 本仓库已经把
mcpServer/elicitation/request 作为 dedicated request type 接入:translator 会产出 requestType=mcp_server_elicitation,orchestrator 会进一步分成 mcp_server_elicitation_form / url / approval,Feishu 侧已有专门 render/response 流和测试覆盖。
- 当前
mcp_server_elicitation 并没有被错误并回 generic approval;它只是和其他 request family 共享同一 pending-request substrate,但卡面语义和 response payload 已由 orchestrator 单点区分。
#669 已消费 approval-carrying elicitation 的 _meta.codex_approval_kind=mcp_tool_call 与 persist=session contract,支持“允许本次 / 本会话允许”,persist=always 仅提示暂不支持跨会话持久授权。
mcpServer/oauth/login -> mcpServer/oauthLogin/completed 是独立 client-initiated RPC + async notify,不属于 pending request substrate;当前执行单元为 #670。
架构归因
当前真正的风险不再是“request family 根本没接住”,而是两类细分 contract 缺口:
- 同一 request family 内部的新语义层未被本地消费。
典型例子:mcp_server_elicitation 承载 MCP approval 时的 _meta.codex_approval_kind / persist。这一点已由 #669 收口。
- 与 request family 相邻、但不属于同一 substrate 的 sibling lifecycle 未建模。
典型例子:mcpServer/oauth/login -> mcpServer/oauthLogin/completed。这一点由 #670 承接。
也就是说:现有 generic pending-request substrate 不是 bug 本身,真正需要 guard 的是不要把“approval-carrying elicitation”、“普通 form/url elicitation”和“独立 OAuth RPC lifecycle”继续混成一件事。
拆分结构
#669 [Follow-up] MCP approval elicitation:codex_approval_kind / persist contract refresh
#670 [Follow-up] MCP OAuth login lifecycle:mcpServer/oauth/login -> oauthLogin/completed
推荐顺序
#669:已完成并关闭。
#670:已完成计划闭包,当前可开工。
- 两个子单都关闭后回到本父单做总结果回卷和 close judgment。
可并行组
#669 与 #670 理论上可以并行,因为一个是 pending request family 内部语义层,一个是 client-initiated RPC + async notify lifecycle。
- 当前实际状态是
#669 已完成,#670 是唯一剩余 worker,不再需要并行调度。
当前风险
#670 不能被普通 mcp_server_elicitation URL 卡片替代;它是独立 command/notification lifecycle。
#670 的 completion notification 没有 request id,必须按协议字段 name + threadId 和 pending command state 做相关,不能用时间窗口或“当前 thread”猜测。
- Feishu API 调用有限制,
#670 不应实现打字机/流式展示;只展示完整授权 URL 和最终完成/失败结果。
- 若
#670 触及 Feishu card payload、command menu、remote route/gate,需要按仓库规则运行对应 guardrail 并同步 canonical docs。
总调度表
| 单元 |
类型 |
当前状态 |
依赖 |
可并行组 |
当前闭包等级 |
下一步建议 |
备注 |
结果回卷 |
verifier 状态 |
当前结论 |
| #668 |
父 issue |
finish-ready |
- |
- |
调度闭包完成 |
commit / safe-push 后关闭父单 |
不直接承载生产补丁;负责结果收拢 |
#669 与 #670 均已回卷 |
独立 verifier:pass |
可关闭 |
| #669 |
子 issue |
closed |
#668 拆分结论 |
A |
执行闭包完成 |
无 |
已支持 approval-carrying elicitation once/session;always 仅提示不支持 |
子 issue #669 已完成并关闭,结果回卷如下:approval-carrying elicitation 支持 _meta.codex_approval_kind=mcp_tool_call 与 once/session persist;persist=always 保持非目标并提示暂不支持 |
独立 verifier:pass |
已完成并回卷 |
| #670 |
子 issue |
finish-ready |
#668 拆分结论;#669 已关闭 |
B |
执行闭包完成 |
commit / safe-push 后关闭 |
OAuth login RPC lifecycle,独立于 elicitation request |
子 issue #670 已完成并关闭,结果回卷如下:新增 CommandMCPOAuthLogin 与 OAuth URL/completed events;translator 支持 mcpServer/oauth/login、authorization_url response、JSON-RPC error、mcpServer/oauthLogin/completed;Feishu/daemon 支持 /mcpoauth <server> 与 /mcp-oauth <server>,只向发起 surface append URL/完成/失败 notice,未相关 completion 不广播 |
独立 verifier:pass |
已完成,等待 close-out |
低优先级待办
- 对复杂/nested MCP form schema,当前仍只提供 JSON fallback;后续如要提升表单体验,可另起 issue,不与
#669/#670 混做。
建议范围
- 本父单只负责调研闭环、拆分和结果跟踪,不直接承载生产补丁。
- 真正实现与验证在子单里完成;父单在子单关闭后负责 roll-up 和 close judgment。
- 当前可推进项是
#670;父单本身继续保持 status:needs-plan,因为它是调度单,不是直接 worker。
实现参考
#669 已完成:参考其关闭结果和相关提交,不在父单重复编码。
#670 实现参考已写入子单 body:优先做 agentproto.CommandMCPOAuthLogin、translator request/response/notification,再接 Feishu /mcpoauth <server> 最小入口。
- 父单层面只需在
#670 关闭前检查其结果是否完整回卷,并确认两个 request/RPC family 的边界在文档里仍清楚。
检查参考
- 检查
mcp_server_elicitation 是否仍保留 dedicated request type / semantic kind / response flow。
- 检查 approval-carrying elicitation 是否继续消费
_meta.codex_approval_kind / persist,且没有并入 can_use_tool / permissions_request_approval。
- 检查
#670 是否新增 mcpServer/oauth/login command path 与 mcpServer/oauthLogin/completed event path。
- 检查相关状态机文档是否同步记录父/子边界和 OAuth lifecycle 承接策略。
收尾参考
执行决策
- 是否拆分:是。
- 当前执行单元:子 issue
#670。
- 当前父单职责:本 issue 自身作为父单,只负责调研闭环、拆分、跟踪和最终结果收拢,不直接写生产补丁。
- 当前推荐子单:
#670。
- verifier:父单当前不需要独立 verifier;真正编码子单
#670 实现完成后默认需要 verifier。
- 状态判断:父单继续保持
status:needs-plan,因为它不是直接实现单;当前实际可执行 worker 是 #670。
当前阶段
finish-ready(两个子单均已完成并回卷;父单等待 commit / safe-push / finish-close)
当前执行点
#669 已完成并关闭,结果已回卷。
#670 已完成实现、验证、文档同步与独立 verifier,结果已回卷。
- 父单当前不再有未实现子单;剩余工作是 commit、safe-push、关闭
#670,再关闭本父单。
已完成
- 已核对本仓库现代码,确认
mcp_server_elicitation 已是 dedicated request family,而不是 generic approval fallback。
- 已核对 orchestrator / Feishu render / response / tests,确认 form/url 两种语义已有本地承接。
- 已核对 upstream
openai/codex main,确认 codex_approval_kind / persist contract 与 mcpServer/oauth/login -> mcpServer/oauthLogin/completed lifecycle 的现状。
- 已完成拆分并创建子单:
#669、#670。
- 子 issue
#669 已完成并关闭,结果回卷:新增 mcp_server_elicitation_approval 语义,支持“允许本次 / 本会话允许”,allow once 不回显 request _meta.persist 广告,acceptForSession 回写 top-level _meta.persist=session,persist=always 仅提示暂不支持跨会话持久授权。
#669 已完成独立 verifier:pass。
- 子 issue
#670 已完成:新增 MCP OAuth login lifecycle 的 agentproto command/event、Codex translator request/response/notification、Feishu /mcpoauth <server> 最小入口、URL-ready 与 completed success/failure notice。
#670 已完成独立 verifier:pass。
- 已同步协议与状态机文档,明确 OAuth login 不进入
mcp_server_elicitation / request-card flow,不做流式 patch。
- 独立 verifier 结果:pass。
下一步
commit 当前代码,使用 ./safe-push.sh 推送;随后关闭 #670,再关闭本父单。
最后一致状态
mcp_server_elicitation 主链已接住;approval-carrying elicitation 的 once/session contract 已由 #669 完成。
mcpServer/oauth/login -> oauthLogin/completed 的最小主动链路已由 #670 完成。
- 当前剩余 upstream backlog 是非本父单目标:guardian review 可见性、MCP tool result 富展示、MCP server picker / account UI、
app/list / startup status / skills 等管理面。
- 本地验证已通过:focused packages、
go test ./...、git diff --check、bash scripts/check/go-file-length.sh。
当前 blocker
无硬 blocker。
未完成尾项
- commit / safe-push。
- 关闭
#670。
- 关闭
#668。
恢复步骤
- 运行
git status --short --branch 确认工作区只包含 #668/#670 相关改动。
- 如需重验,运行
go test ./...、git diff --check、bash scripts/check/go-file-length.sh。
- 提交并通过
./safe-push.sh 推送。
- 运行
issuectl close-plan --issue 670,通过后 issuectl finish --issue 670 --close。
- 运行
issuectl close-plan --issue 668,通过后 issuectl finish --issue 668 --close。
背景
在处理
#667(Claude native permissionMode observed projection 漂移)时,已确认:can_use_tool同一 permission family,已纳入#667。mcp_server_elicitation是独立 request family,用于 MCP server 的表单补充、URL/OAuth continue 等动作,不属于#667的 permission-mode drift 修复范围。后续调研基于 upstream
openai/codexmain(9e552e9d15ba52bed7077d5357f3e18e330f8f38, 2026-07-12 复核)确认:mcp_server_elicitationrequest typing / render / response flow,不存在“还把它当成 generic approval 没接住”的问题。#669:mcpServer/elicitation/request承载 MCP tool approval 时的_meta.codex_approval_kind / persistcontract。#670:mcpServer/oauth/login -> mcpServer/oauthLogin/completed独立 app-server lifecycle。当前状态:
#669已实现、验证、关闭并回卷;#670已完成计划闭包并切到status:implementable-now,成为下一步执行 worker。目标
mcp_server_elicitationrequest family 与相邻 MCP OAuth lifecycle 的产品语义、桥接 contract 和前台展示边界。can_use_tool/permissions_request_approval的职责分层在代码与文档里都保持清晰。范围
mcpServer/elicitation/request的 request type / semantic kind / prompt 构造 / render / response flow 后续 contract 审视。mcpServer/oauth/login -> mcpServer/oauthLogin/completedlifecycle 的本地承接缺口。非目标
#667的 Claude permissionMode observed projection 修复。mcp_server_elicitation改造成通用权限审批流。permissions_request_approval或can_use_tool的主链改造。完成标准
mcp_server_elicitation相关剩余问题被拆成边界清晰的子 issue,而不是继续混在一个大而泛的提醒单里。相关文档
docs/general/codex-mcp-app-server-protocol.mddocs/inprogress/codex-app-server-state-machine-audit.mddocs/general/remote-surface-state-machine.mddocs/general/feishu-card-ui-state-machine.mdhttps://github.com/openai/codex/blob/main/codex-rs/app-server/README.md涉及文件
internal/adapter/codex/translator_helpers_request.gointernal/adapter/codex/translator_requests_test.gointernal/adapter/codex/translator_commands.gointernal/adapter/codex/translator_observe_server.gointernal/core/agentproto/types.gointernal/core/orchestrator/service_request.gointernal/core/orchestrator/service_request_mcp.gointernal/core/orchestrator/service_request_presentation.gointernal/core/control/feishu_request_semantics.gointernal/core/control/feishu_request_bridge.gointernal/core/control/feishu_commands.gointernal/adapter/feishu/projector/request.gointernal/app/daemon/app_ingress.godocs/general/codex-mcp-app-server-protocol.mddocs/inprogress/codex-app-server-state-machine-audit.mddocs/general/remote-surface-state-machine.mddocs/general/feishu-card-ui-state-machine.md调研结论
mcpServer/elicitation/request作为 dedicated request type 接入:translator 会产出requestType=mcp_server_elicitation,orchestrator 会进一步分成mcp_server_elicitation_form / url / approval,Feishu 侧已有专门 render/response 流和测试覆盖。mcp_server_elicitation并没有被错误并回 generic approval;它只是和其他 request family 共享同一 pending-request substrate,但卡面语义和 response payload 已由 orchestrator 单点区分。#669已消费 approval-carrying elicitation 的_meta.codex_approval_kind=mcp_tool_call与persist=sessioncontract,支持“允许本次 / 本会话允许”,persist=always仅提示暂不支持跨会话持久授权。mcpServer/oauth/login -> mcpServer/oauthLogin/completed是独立 client-initiated RPC + async notify,不属于 pending request substrate;当前执行单元为#670。架构归因
当前真正的风险不再是“request family 根本没接住”,而是两类细分 contract 缺口:
典型例子:
mcp_server_elicitation承载 MCP approval 时的_meta.codex_approval_kind / persist。这一点已由#669收口。典型例子:
mcpServer/oauth/login -> mcpServer/oauthLogin/completed。这一点由#670承接。也就是说:现有 generic pending-request substrate 不是 bug 本身,真正需要 guard 的是不要把“approval-carrying elicitation”、“普通 form/url elicitation”和“独立 OAuth RPC lifecycle”继续混成一件事。
拆分结构
#669[Follow-up] MCP approval elicitation:codex_approval_kind / persist contract refresh#670[Follow-up] MCP OAuth login lifecycle:mcpServer/oauth/login -> oauthLogin/completed推荐顺序
#669:已完成并关闭。#670:已完成计划闭包,当前可开工。可并行组
#669与#670理论上可以并行,因为一个是 pending request family 内部语义层,一个是 client-initiated RPC + async notify lifecycle。#669已完成,#670是唯一剩余 worker,不再需要并行调度。当前风险
#670不能被普通mcp_server_elicitationURL 卡片替代;它是独立 command/notification lifecycle。#670的 completion notification 没有 request id,必须按协议字段name + threadId和 pending command state 做相关,不能用时间窗口或“当前 thread”猜测。#670不应实现打字机/流式展示;只展示完整授权 URL 和最终完成/失败结果。#670触及 Feishu card payload、command menu、remote route/gate,需要按仓库规则运行对应 guardrail 并同步 canonical docs。总调度表
always仅提示不支持_meta.codex_approval_kind=mcp_tool_call与 once/session persist;persist=always保持非目标并提示暂不支持CommandMCPOAuthLogin与 OAuth URL/completed events;translator 支持mcpServer/oauth/login、authorization_urlresponse、JSON-RPC error、mcpServer/oauthLogin/completed;Feishu/daemon 支持/mcpoauth <server>与/mcp-oauth <server>,只向发起 surface append URL/完成/失败 notice,未相关 completion 不广播低优先级待办
#669/#670混做。建议范围
#670;父单本身继续保持status:needs-plan,因为它是调度单,不是直接 worker。实现参考
#669已完成:参考其关闭结果和相关提交,不在父单重复编码。#670实现参考已写入子单 body:优先做agentproto.CommandMCPOAuthLogin、translator request/response/notification,再接 Feishu/mcpoauth <server>最小入口。#670关闭前检查其结果是否完整回卷,并确认两个 request/RPC family 的边界在文档里仍清楚。检查参考
mcp_server_elicitation是否仍保留 dedicated request type / semantic kind / response flow。_meta.codex_approval_kind / persist,且没有并入can_use_tool/permissions_request_approval。#670是否新增mcpServer/oauth/logincommand path 与mcpServer/oauthLogin/completedevent path。收尾参考
#669已完成并回卷。#670完成后,需要把实现结果、验证结果、verifier 判断和剩余非目标回卷到本父单。执行决策
#670。#670。#670实现完成后默认需要 verifier。status:needs-plan,因为它不是直接实现单;当前实际可执行 worker 是#670。当前阶段
finish-ready(两个子单均已完成并回卷;父单等待 commit / safe-push / finish-close)
当前执行点
#669已完成并关闭,结果已回卷。#670已完成实现、验证、文档同步与独立 verifier,结果已回卷。#670,再关闭本父单。已完成
mcp_server_elicitation已是 dedicated request family,而不是 generic approval fallback。openai/codexmain,确认codex_approval_kind / persistcontract 与mcpServer/oauth/login -> mcpServer/oauthLogin/completedlifecycle 的现状。#669、#670。#669已完成并关闭,结果回卷:新增mcp_server_elicitation_approval语义,支持“允许本次 / 本会话允许”,allow once不回显 request_meta.persist广告,acceptForSession回写 top-level_meta.persist=session,persist=always仅提示暂不支持跨会话持久授权。#669已完成独立 verifier:pass。#670已完成:新增 MCP OAuth login lifecycle 的 agentproto command/event、Codex translator request/response/notification、Feishu/mcpoauth <server>最小入口、URL-ready 与 completed success/failure notice。#670已完成独立 verifier:pass。mcp_server_elicitation/ request-card flow,不做流式 patch。下一步
commit 当前代码,使用
./safe-push.sh推送;随后关闭#670,再关闭本父单。最后一致状态
mcp_server_elicitation主链已接住;approval-carrying elicitation 的 once/session contract 已由#669完成。mcpServer/oauth/login -> oauthLogin/completed的最小主动链路已由#670完成。app/list/ startup status / skills 等管理面。go test ./...、git diff --check、bash scripts/check/go-file-length.sh。当前 blocker
无硬 blocker。
未完成尾项
#670。#668。恢复步骤
git status --short --branch确认工作区只包含#668/#670相关改动。go test ./...、git diff --check、bash scripts/check/go-file-length.sh。./safe-push.sh推送。issuectl close-plan --issue 670,通过后issuectl finish --issue 670 --close。issuectl close-plan --issue 668,通过后issuectl finish --issue 668 --close。