MCP Apps in ChatGPT are fundamentally broken - 2 critical bugs
OpenAI Developer Community
May 6, 2026
If it’s of any help, here’s what I see when testing:
And my test code:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
const server = new McpServer({
name: "meta-probe",
version: "1.0.0",
});
const TEMPLATE_URI = "ui://widget/meta-probe.html";
const widgetHtml = `<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: system-ui, sans-serif;
margin: 0;
padding: 16px;
color: #111;
background: #fff;
}
h1 { font-size: 18px; margin: 0 0 8px; }
pre {
white-space: pre-wrap;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 6px;
padding: 12px;
}
</style>
</head>
<body>
<h1>Widget rendered</h1>
<p>If you can see this, the iframe received template HTML.</p>
<pre id="debug">Waiting for bridge data...</pre>
<script>
const debug = document.getElementById("debug");
function snapshot(label) {
const data = {
label,
hasOpenAI: Boolean(window.openai),
toolOutput: window.openai?.toolOutput ?? null,
toolResponseMetadata: window.openai?.toolResponseMetadata ?? null,
widgetState: window.openai?.widgetState ?? null
};
debug.textContent = JSON.stringify(data, null, 2);
}
snapshot("initial");
window.addEventListener("openai:set_globals", (event) => {
snapshot("openai:set_globals");
});
window.addEventListener("message", (event) => {
const msg = event.data;
if (msg?.method === "ui/notifications/tool-result") {
debug.textContent = JSON.stringify(
{
label: "ui/notifications/tool-result",
params: msg.params
},
null,
2
);
}
});
</script>
</body>
</html>`;
server.registerResource("meta-probe-widget", TEMPLATE_URI, {}, async () => ({
contents: [
{
uri: TEMPLATE_URI,
mimeType: "text/html",
text: widgetHtml,
_meta: {
"openai/widgetDescription": "Validates MCP _meta delivery.",
"openai/widgetPrefersBorder": true,
"openai/widgetCSP": {
connect_domains: [],
resource_domains: [],
},
},
},
],
}));
server.registerTool(
"show_meta_probe",
{
title: "Show meta probe",
description: "Render a read-only widget that verifies MCP tool result metadata.",
inputSchema: {},
annotations: {
readOnlyHint: true,
destructiveHint: false,
openWorldHint: false,
},
_meta: {
"openai/outputTemplate": TEMPLATE_URI,
"openai/toolInvocation/invoking": "Running meta probe...",
"openai/toolInvocation/invoked": "Meta probe ready",
},
},
async () => ({
content: [
{
type: "text",
text: "hello from the MCP server",
},
],
structuredContent: {
visibleMessage: "hello from the MCP server",
structuredOnlyValue: 12345,
},
_meta: {
secretProbeValue: "private meta reached widget",
largePrivateState: {
hydratedFromMeta: true,
timestamp: new Date().toISOString(),
},
},
})
);
export default server;
Discussion in the ATmosphere