ChatGPT App widget becomes blank after refreshing the conversation webpage

Hi everyone,

I’m seeing a reproducible issue with a ChatGPT App built using the Apps SDK and MCP.

Steps to reproduce

  1. Open a ChatGPT conversation.
  2. Call an MCP tool that has an attached UI widget.
  3. The tool completes and the widget renders correctly.
  4. Refresh the entire ChatGPT webpage using F5 or Cmd+R.
  5. Return to the tool result in the conversation.

Actual result

The widget area is blank after the page refresh.

The tool and UI work correctly before refreshing. The problem only appears when ChatGPT restores the existing conversation after a full webpage reload.

Expected result

The existing widget should render again using the saved tool result when the conversation is restored.

Has anyone else seen an existing widget become completely blank after refreshing the ChatGPT webpage?

OpenAI’s troubleshooting docs mention using setWidgetState / widgetState if the widget relies on persisted UI state. If the UI can be reconstructed from the tool result, I’d make that the primary path; if it needs local UI changes after render, then persisting/restoring widget state may be needed too.

Thanks. This can currently be reproduced with any ChatGPT app that displays a UI widget, so it does not appear specific to our state handling. The widget works initially, but after refreshing the ChatGPT webpage, the existing widget becomes blank. This appears to be a ChatGPT host-level widget restoration issue.

Confirming this, with the underlying cause and a partial workaround — we chased it all day today.

**Reproduced** on two unrelated apps with different widgets, on conversations both minutes and days old. Live renders are fine; only refresh / revisit breaks. The same apps rehydrate correctly in another MCP Apps host.

**What actually happens.** We instrumented our renderer to report the shape of the tool result it receives (keys only). On a refresh of a conversation that rendered correctly seconds earlier:

- `content` is still there, with a `text` block — but the block parses to an **empty object** (`{}`)

- `structuredContent` is there too, and is **also empty**

- there is no `_meta` on the replayed result

A caution for anyone testing: a check like `if (result.structuredContent)` passes on `{}`. We wasted hours believing structuredContent survived. **Count the keys.**

Intermittently the widget’s `ontoolresult` does not fire at all and the widget just sits on its initial state — matching openai/openai-apps-sdk-examples#195. Same conversation, different reloads, different behaviour.

**Partial workaround that got our UI back.** Put the widget’s markup in the `ui://` resource that `outputTemplate` points at, rather than shipping it inside the tool result. The template pointer *is* persisted and re-fetched on reload, so the UI reliably returns. This is the canonical arrangement anyway — worth doing regardless of the bug.

That fixes the UI, not the data. Since neither carrier survives, our widget now re-requests its data from our own server when it mounts with none. If you do the same, gate it: re-running a tool on mount can re-trigger side effects, so restrict it to read-only tools that take no arguments — otherwise reopening a chat can silently repeat an action.

One gotcha: the resource pointer is resolved when the app is connected, so a change like this only takes effect after the app is refreshed in ChatGPT (app page → ⋯ → Manage → Refresh). Existing conversations keep the old pointer until then.

Related: openai/openai-apps-sdk-examples#195 and #144.

I’m having the same issue with pretty much all MCP apps - it used to work just fine. It looks like ChatGPT does not persist MCP tool results anymore.