Skip to content

[Follow-up] MCP server elicitation 独立 request family:表单 / OAuth 继续流审视 #668

Description

@kxn

背景

在处理 #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 main9e552e9d15ba52bed7077d5357f3e18e330f8f38, 2026-07-12 复核)确认:

  1. 本仓库已经有 dedicated mcp_server_elicitation request typing / render / response flow,不存在“还把它当成 generic approval 没接住”的问题。
  2. 当前主题真正剩余的两个执行面已经拆成子单:
    • #669mcpServer/elicitation/request 承载 MCP tool approval 时的 _meta.codex_approval_kind / persist contract。
    • #670mcpServer/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_approvalcan_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_callpersist=session contract,支持“允许本次 / 本会话允许”,persist=always 仅提示暂不支持跨会话持久授权。
  • mcpServer/oauth/login -> mcpServer/oauthLogin/completed 是独立 client-initiated RPC + async notify,不属于 pending request substrate;当前执行单元为 #670

架构归因

当前真正的风险不再是“request family 根本没接住”,而是两类细分 contract 缺口:

  1. 同一 request family 内部的新语义层未被本地消费。
    典型例子:mcp_server_elicitation 承载 MCP approval 时的 _meta.codex_approval_kind / persist。这一点已由 #669 收口。
  2. 与 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

推荐顺序

  1. #669:已完成并关闭。
  2. #670:已完成计划闭包,当前可开工。
  3. 两个子单都关闭后回到本父单做总结果回卷和 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/loginauthorization_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=sessionpersist=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 --checkbash scripts/check/go-file-length.sh

当前 blocker

无硬 blocker。

未完成尾项

  • commit / safe-push。
  • 关闭 #670
  • 关闭 #668

恢复步骤

  1. 运行 git status --short --branch 确认工作区只包含 #668/#670 相关改动。
  2. 如需重验,运行 go test ./...git diff --checkbash scripts/check/go-file-length.sh
  3. 提交并通过 ./safe-push.sh 推送。
  4. 运行 issuectl close-plan --issue 670,通过后 issuectl finish --issue 670 --close
  5. 运行 issuectl close-plan --issue 668,通过后 issuectl finish --issue 668 --close

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:codexCodex protocol translation and wrapper integrationarea:daemonDaemon server, admin API, and runtime controlarea:feishuFeishu/Lark integration, gateway, projector, or previewenhancementNew feature or requeststatus:needs-planTechnical investigation is sufficient, but the staged plan is not yet execution-ready

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions