Skip to content

fix(mcp): render the widget in ChatGPT (window.openai runtime) - #135

Merged
windoze95 merged 1 commit into
mainfrom
fix/mcp-widget-chatgpt-render
Jul 7, 2026
Merged

fix(mcp): render the widget in ChatGPT (window.openai runtime)#135
windoze95 merged 1 commit into
mainfrom
fix/mcp-widget-chatgpt-render

Conversation

@windoze95

Copy link
Copy Markdown
Owner

Problem

In ChatGPT, SaltyBytes tool calls succeed (the model gets the recipe data) but the interactive widget sits on its Warming up the kitchen… loading note forever and never renders the recipe cards.

Root cause: the widget only implemented the MCP Apps postMessage bridge and awaited a ui/initialize response. ChatGPT's Apps runtime (a) never answers that handshake (so the await hangs) and (b) delivers the tool's structured output via window.openai (window.openai.toolOutput + the openai:set_globals event), which the widget never read. Confirmed live in ChatGPT Developer Mode.

Fix (internal/mcpserver/widget/app.html)

  • Add the window.openai render path — render from window.openai.toolOutput on mount and re-render on openai:set_globals (event.detail.globals.toolOutput); apply theme from the globals.
  • Route widget-initiated actions (tap-to-preview, open saved, Save button, source link) through window.openai.callTool / window.openai.openExternal when present.
  • Make the ui/initialize handshake non-blocking (.then/.catch, no await) so a host that never answers it can't freeze the widget.
  • The Claude / MCP-Apps postMessage path is otherwise unchanged (dual-bridge: window.openai for ChatGPT, postMessage for Claude).

Verification

JS syntax-checked (node --check), go build/go vet/go test ./internal/mcpserver/... pass. Will re-test live in ChatGPT after deploy.

🤖 Generated with Claude Code

The widget only spoke the MCP Apps postMessage bridge, and blocked on an awaited ui/initialize response. In ChatGPT the tool CALLS worked but the widget sat on its 'Warming up the kitchen…' loading note forever, because ChatGPT's Apps runtime delivers tool output via window.openai (globals + the 'openai:set_globals' event), not that bridge — and it never answers ui/initialize, so the await hung.

- Add a window.openai path: render from window.openai.toolOutput on mount and on 'openai:set_globals' (event.detail.globals.toolOutput); apply theme from the globals.

- Route widget-initiated tool calls through window.openai.callTool and link-opens through window.openai.openExternal when present.

- Make the MCP Apps ui/initialize handshake NON-BLOCKING (.then/.catch instead of await) so a host that never answers it can't freeze the widget. Claude/MCP-Apps rendering path is otherwise unchanged.

JS syntax-checked; go build/vet + mcpserver tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@windoze95
windoze95 merged commit ae3fb1f into main Jul 7, 2026
1 check passed
@windoze95
windoze95 deleted the fix/mcp-widget-chatgpt-render branch July 7, 2026 23:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant