ChatGPT MCP Apps bridge drops custom _meta from tool results in ui/notifications/tool-result

Hi people,

I’m seeing an inconsistency between documented behavior and runtime behavior in ChatGPT Dev for MCP Apps.

According to docs, tool results should include structuredContent + _meta, where _meta is widget-only data (not added to model context).
Docs references:

  • developers.openai. com/apps-sdk/build/mcp-server

  • github. com/modelcontextprotocol/ext-apps/blob/main/specification/2026-01-26/apps.mdx

My server returns this from load_project:

{
"content": [{ "type": "text", "text": "Loaded project \"test\"." }],
"structuredContent": {
"project": {
"id": "yeu5lfsg36nfzpcp65mvvhyt",
"name": "test",
"type": "email",
"createdAt": "2026-03-28T10:33:56.832Z",
"updatedAt": "2026-03-28T10:33:56.832Z"
},
"projectUrl": "https://.../project/yeu5lfsg36nfzpcp65mvvhyt"
},
"_meta": {
"projectData": { "...large json..." }
}
}

Inside the MCP app (onToolResult), ChatGPT delivers:

{
"content": [
{
"type": "text",
"text": "{\"project\":{...},\"projectUrl\":\"https://...\"}"
}
],
"structuredContent": {
"project": { ... },
"projectUrl": "https://..."
}
}

Observed problems:

  1. Custom _meta is missing entirely in ui/notifications/tool-result.

  2. content[0].text appears rewritten to a JSON string of structuredContent instead of the original text.

We intentionally keep large projectData in _meta to avoid inflating model-visible context. Duplicating projectData into structuredContent is not viable (payload can be MBs).

Expected behavior:

  • ui/notifications/tool-result should preserve custom _meta fields from the MCP tool result (eg _meta.projectData) as documented.

Can you confirm whether this is a known limitation/regression in ChatGPT MCP Apps, and whether custom _meta forwarding is expected to be supported?

Also, an important note, the same app works correctly in a regular MCP App inspector based on MCP App standard. I’m using the official bridge (`@modelcontextprotocol/sdk` and `@modelcontextprotocol/ext-apps`)

Same here.

Raised it almost a month ago, no response.

1 Like

Thanks @nico9

At the moment this seems to work for the UI widget as a workaround:

app.ontoolresult = params => {
  loadPayload({
    // Patch to get metadata from ChatGPT
    _meta: { ...window.openai?.toolResponseMetadata },
    ...params
  });
};

We experienced the same issue. Our app rejected because the structured content included an ID, but since _meta always returns empty, we are forced to send the required data within the structured content. We sent an explanatory email, and they informed us that it will be reviewed again within this context, still waiting the result.

1 Like

Thanks for the detailed report. We’re tracking the reports around MCP Apps tool result metadata, including cases where custom `_meta` from `CallToolResult` is not appearing in `ui/notifications/tool-result`.

Because deeper troubleshooting may require app-specific or account-specific details, please don’t post user IDs, org/workspace IDs, API keys, HAR files, private logs, request traces, or account-specific data in this thread.

For now, please email support@openai.com with this forum URL, the related repro links, and any minimal non-sensitive reproduction details you can share privately. After you’ve emailed support, reply here with the Case ID or exact subject line so we can locate it quickly.

As a temporary development workaround, avoid depending only on `CallToolResult._meta` for widget restore state. If it is safe for your app, use a small non-secret opaque state key in `structuredContent`, then have the widget re-fetch or rebuild state on startup. Do not put secrets, user data, large private payloads, or account-specific debug artifacts into model-visible fields.

1 Like