MCP Apps: isError form deferral suppresses PR forms in Codex desktop
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 25/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- github, go
- Ambito
- ai-infra-agents, backend-api-design
Direzione di ricerca
Start by reading pkg/utils/result.go, especially NewToolResultAwaitingFormSubmission, and trace how form deferral sets IsError and structured status. Then follow the form result handler and host rendering lifecycle for pending, submitted, cancelled, and failed states; done means a deferred form renders and completes correctly without treating genuine tool failures as pending. The issue calls for testing submission, cancellation, failures, and final result delivery.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Describe the bug
On Codex desktop, GitHub MCP form deferral returns isError: true while instructing the assistant to wait for a form submission. The host classifies the call as failed and excludes the corresponding MCP App from rendering. The user therefore has no form to submit, the requested GitHub mutation never executes, and the assistant may end its turn waiting for an interaction that is unavailable.
This is a concrete mismatch between the server's pending-form signaling and the host's error-rendering policy. Related reports describe invisible or collapsing forms in Claude: #2823 and #3415. #3455 discusses retaining an opt-out. This report adds a Codex reproduction and a replay of the installed client's rendering gate; I have not established that the Claude reports have the same cause.
Affected version
- Server: hosted remote GitHub MCP at
https://api.githubcopilot.com/mcp/, not a local Docker deployment. - Version reported by MCP initialization during the controlled reproduction:
github-mcp-server/remote-a5f0ed2ba9b09e7e6bd87d7e8adb559158f83ff5. - Client: Codex desktop on macOS, version
26.1027.61615, build24141, production channel. - The app's updater reported
up_to_date; no desktop upgrade was applied during diagnosis. - Observed on November 3, 2026. Both PR creation and PR update encountered form deferral.
- The controlled MCP client advertised the
io.modelcontextprotocol/uiextension with MIME typetext/html;profile=mcp-app.
Steps to reproduce the behavior
- Connect the hosted GitHub MCP server to the affected Codex desktop version with MCP Apps support enabled and without the
mcp_apps_disable_form_deferralfeature flag. - Use an existing test PR that the authenticated account can edit. Read its current title.
- Call
update_pull_requestwith onlyowner,repo,pullNumber, and that same title. Using the unchanged title avoids an intentional content change. Example tool arguments:
{
"owner": "YOUR_OWNER",
"repo": "YOUR_TEST_REPO",
"pullNumber": 123,
"title": "THE_CURRENT_PR_TITLE"
}
- Observe a result with
isError: truewhose text asserts that a form has been shown and directs the assistant to wait silently for submission. - In the client, the call is marked failed and no usable form remains available to submit. The PR update has not executed.
The problem also occurred with create_pull_request. Reproducing with an existing PR is preferable to repeatedly attempting creation.
Expected vs actual behavior
Expected: Deferring to a form leaves a visible, usable form, accurately reports that the GitHub mutation is still pending, and eventually delivers submission success, failure, or cancellation to the assistant.
Actual: The pending-form response is treated as a failed tool result, which prevents form rendering. The response text asserts UI visibility without confirmation from the host. The assistant can then wait or stop while the user has nothing to submit.
Logs
Sanitized excerpt from an actual completed create-PR event; identifiers, arguments, and message text are omitted:
{
"type": "McpToolCall",
"server": "github",
"tool": "create_pull_request",
"mcpAppResourceUri": "ui://github-mcp-server/pr-write",
"status": "failed",
"result": {
"isError": true
}
}
The original result also contained a text block telling the assistant that a form was already displayed and to wait for submission. The corresponding resource-read RPC returned no protocol error, but that alone does not prove successful UI rendering.
Root-cause evidence
NewToolResultAwaitingFormSubmission deliberately sets IsError: true to stop the agent continuing. Its comment assumes the host will still render UI from the tool's metadata regardless of the result. The helper also supplies an awaiting_user_submission structured status in this source revision.
That assumption does not hold in the installed Codex build. Inspection of the installed JavaScript bundle found this chain:
- The tool-event projection passes the recorded
failedstatus into result normalization. - Normalization produces a result with
type: "error". - The MCP App eligibility/renderability logic explicitly excludes error results.
- The resource renderer returns its fallback branch when
shouldRenderMcpAppis false, even if valid HTML is available.
A local replay used the actual captured event and the unchanged normalization, error-detection, renderability, and resource-selection functions extracted from that installed bundle:
| Replay input | Normalized result | Form renderable | Resource selection |
|---|---|---|---|
Original recorded failed status |
error |
false |
fallback |
Only the recorded status changed to completed |
success |
true |
html |
This isolates a sufficient rendering blocker. The control changes the projected call status, not the live server response; it is not an end-to-end test of changing isError upstream. Unrelated eligibility predicates were allowed, text normalization was an identity operation for the captured text-only fixture, and the resource selector received synthetic valid HTML. No app binaries were modified. No live DOM instrumentation was performed, and additional UI problems are not ruled out.
The linked source revision is not claimed to be identical to the deployed remote build; the captured response independently establishes the problematic isError: true behavior.
Suggested fix
Please separate a successful handoff to a pending form from an actual tool error. One candidate is a non-error result carrying an explicit pending status and a clear indication that the GitHub mutation has not executed:
{
"isError": false,
"structuredContent": {
"status": "awaiting_user_submission",
"operationExecuted": false
}
}
The status already present in the helper is a useful starting point. Agents must not interpret a non-error handoff as a completed PR mutation. The client, form, and agent lifecycle should agree on pending, submitted, cancelled, and failed states. Also consider changing the response wording to describe a requested form handoff rather than asserting that the form is already visible.
This is a proposed direction, not a verified one-line fix: please test the form's own result handler, host rendering, submission, cancellation, genuine tool failures, and delivery of the final result. Simply allowing all failed-tool UIs or automatically executing an unsubmitted mutation would not address the underlying contract cleanly.
Verified workaround
The following request header avoids form deferral:
X-MCP-Features: mcp_apps_disable_form_deferral
Against the same remote server and the same unchanged-title PR update, the baseline request deferred with isError: true; the flagged request executed successfully. After restarting Codex to reload the header, an actual in-chat GitHub MCP PR update also succeeded without waiting for a form. This restores writes but does not repair form rendering.
- Lingua principale
- Go
- Stelle
- 34.2k
- Fork
- 5.3k
- Merge medio
- 5g 18h
- PR unite (30g)
- 13
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di github/github-mcp-server
-
update_issue_labels is annotated destructiveHint: false but replaces (removes) existing labelsAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 69/100
github/github-mcp-server#3760 ·
I maintainer di solito rispondono entro 2 giorni
-
docs(install-claude): "environment variable" examples put the PAT in argv and the saved configAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
github/github-mcp-server#3758 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 69/100
github/github-mcp-server#3729 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
github/github-mcp-server#3722 ·
I maintainer di solito rispondono entro 2 giorni
-
Insiders Feedback: PR created UI doesn't link to the PRForse già presa @genius-0963 l’ha presa 5 giorni fa. Apertabug insiders user-experience
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
github/github-mcp-server#3658 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di github/github-mcp-server
Issue simili
-
Update the mise toolsApertaready-for-agent
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
hexlet-basics/hexlet-basics#962 ·
I maintainer di solito rispondono entro 1 giorno
-
imapproxy closeForMaintenance grace timer calls clientConn.Close() before closeMaintenanceTransportForse già presa @dejanstrbac l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
-
Renovate health check failedApertarenovate-health
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
Netcracker/qubership-network-latency-exporter#267 ·
I maintainer di solito rispondono entro 1 giorno
-
Network capture does not workForse già presa @KSpaceer l’ha presa oggi. Apertakind/bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
aquasecurity/tracee#5395 ·