We migrated our ChatGPT App from the OpenAI Apps SDK to the MCP Apps standard, following the MCP Apps compatibility guide. The migration went fine. Tools, resources, ontoolresult, callServerTool, sendMessage, and app-only tool visibility all work correctly.
However, when implementing the documented viewUUID pattern for persisting view state, we discovered that ChatGPT strips _meta from tool results before forwarding them to the widget.
Steps to reproduce
- Server returns
_meta: { viewUUID: crypto.randomUUID() }in a tool’sCallToolResult - Widget reads
result._metain theontoolresultcallback result._metaisundefined
Expected
result._meta should be forwarded to the widget as part of ui/notifications/tool-result, per the MCP Apps spec (McpUiToolResultNotification.params is CallToolResult, which extends ResultSchema containing _meta).
Actual
result._meta is undefined. The viewUUID never reaches the widget, so localStorage-based state persistence cannot work.
Code
Server (tool handler):
return {
content: [{ text: "...", type: "text" }],
structuredContent: { /* ... */ },
_meta: { viewUUID: crypto.randomUUID() },
};
Client (widget):
app.ontoolresult = (result) => {
console.log("_meta:", result._meta); // undefined
console.log("viewUUID:", result._meta?.viewUUID); // undefined
};
Logs
[App] ontoolresult _meta: undefined
[App] viewUUID: undefined
This is the only MCP Apps pattern we’ve found that doesn’t work in ChatGPT. Everything else from the migration guide works as expected.
Update: This pattern works correctly in Claude — result._meta.viewUUID is forwarded as expected. The issue is specific to ChatGPT’s host implementation.