fix(codex): Handle mcpServer/elicitation/request#381
fix(codex): Handle mcpServer/elicitation/request#38191ac0m0 wants to merge 7 commits intotiann:mainfrom
Conversation
There was a problem hiding this comment.
Findings
- [Major] MCP elicitation parsing currently reads a flattened payload, but the new request type declares the actual app-server shape under
params.request. That means realmcpServer/elicitation/requestcalls will hitInvalid MCP elicitation request: missing modebefore the UI/RPC bridge is reached. Evidencecli/src/codex/codexRemoteLauncher.ts:258,cli/src/codex/appServerTypes.ts:161,cli/src/codex/codexRemoteLauncher.test.ts:222.
Suggested fix:const requestRecord = asRecord(params.request) ?? {} const mode = asString(requestRecord.mode) const message = asString(requestRecord.message) ?? '' const requestedSchema = asRecord(requestRecord.requestedSchema) const url = asString(requestRecord.url) const elicitationId = asString(requestRecord.elicitationId)
- [Major] The web flow cannot satisfy
formelicitations yet: accepting always posts{}, while the UI only renders the schema instead of collecting values. Any MCP that expects actual user input will still fail after approval. Evidenceweb/src/components/ToolCard/CodexMcpElicitationFooter.tsx:81,web/src/components/ToolCard/views/CodexMcpElicitationView.tsx:27.
Suggested fix:if (parsed.mode === 'form') { setError('This MCP request requires form input before it can be accepted') return }
Summary
Review mode: initial.
The new bridge wiring is incomplete in two places: the CLI side does not read the nested request payload it just typed, and the web side accepts form elicitations without any way to provide schema-defined values.
Testing
- Not run (automation environment lacks
bunon PATH). - Coverage gap: not found in repo/tests for the real nested
params.requestpayload or an end-to-endformelicitation that submits non-empty content.
HAPI Bot
| }); | ||
|
|
||
| const parseMcpElicitationRequest = (params: McpServerElicitationRequestParams) => { | ||
| const paramsRecord = asRecord(params) ?? {}; |
There was a problem hiding this comment.
[MAJOR] McpServerElicitationRequestParams puts the actual elicitation payload under params.request, but this parser reads mode/message/requestedSchema/url from the top level. With the typed app-server shape, mode stays null here and the request is rejected before it ever reaches the hub/web bridge.
Suggested fix:
const requestRecord = asRecord(params.request) ?? {}
const mode = asString(requestRecord.mode)
const message = asString(requestRecord.message) ?? ''
const requestedSchema = asRecord(requestRecord.requestedSchema)
const url = asString(requestRecord.url)
const elicitationId = asString(requestRecord.elicitationId)| if (loading) return | ||
| setLoading('accept') | ||
|
|
||
| let content: unknown | null = null |
There was a problem hiding this comment.
[MAJOR] Accepting form elicitations always sends {}. The dialog shows requestedSchema, but there is no way to enter schema-defined values, so any MCP that needs real user input will still fail after approval.
Suggested fix:
if (parsed.mode === 'form') {
setError('This MCP request requires form input before it can be accepted')
return
}
problem
current codex service does not register the mcpServer/elicitation/request method, which causes MCP server-initiated elicitation requests to be rejected by default.
When an MCP server requires user confirmation (e.g., title modification MCPs, stdio MCPs, etc.), the requests are directly rejected or cancelled due to the absence of corresponding handling logic.
The related error log is as follows:
change
To address this issue, this change implements support for handling mcpServer/elicitation/request, based on the Codex documentation
Related Issue: tiann/hapi#287