MCP Apps
    Preparing search index...
    • Getting Started

    Troubleshooting

    The most common causes, in the order you should check them:

    1. Uncaught JavaScript error. Open browser developer tools inside the iframe: right-click the App area, choose Inspect, then switch the console context dropdown (top-left of the Console tab) from top to the sandboxed frame. An uncaught error stops the App before it paints.

    2. CSP violation. Look for Refused to connect to… or Refused to load… in the console. Any network request, including to localhost during development, must be declared in _meta.ui.csp.connectDomains or resourceDomains. See the CSP & CORS guide.

    3. Resource URI mismatch. The _meta.ui.resourceUri on the tool must match the URI passed to registerAppResource exactly. A trailing slash or case difference prevents the host from finding the HTML.

    4. Wrong MIME type. The resource's mimeType must be text/html;profile=mcp-app (exported as RESOURCE_MIME_TYPE). Plain text/html is not recognized as an App resource.

    • Handlers registered too late. Attach app.ontoolresult before calling connect(). If the handler is attached after connect() resolves, the notification may have already been delivered and discarded. The React useApp hook handles this ordering automatically.
    • Tool was not called. If the model chose a different tool, or none, there is no result to deliver. Check the host's tool-call log.
    • SDK version mismatch. Older SDK versions used stricter schemas for host notifications. If the App was built against a significantly older @modelcontextprotocol/ext-apps than the host expects, the initialize handshake can fail silently. Keep the SDK version current.

    MCP Apps are portable only if they use the SDK exclusively. Common portability mistakes:

    • Host-specific globals. Do not reference window.openai, window.claude, or any other host-injected object. Use the App class from this SDK, which speaks the standard protocol to any compliant host.
    • Hardcoded CDN URLs. Bundle assets into the App or declare their origins in resourceDomains.
    • Hardcoded sandbox origin. The origin that serves the App varies by host. Use _meta.ui.domain to request a stable origin rather than hardcoding one in CORS allowlists. See CSP & CORS.

    See Controlling App height. The most common cause is height: 100vh combined with the default autoResize: true.

    CSP and CORS are separate controls with different error messages and different fixes:

    • CSP (Refused to connect): The browser blocked the request because the domain is not in connectDomains. Add the domain to _meta.ui.csp on the MCP server.
    • CORS (No 'Access-Control-Allow-Origin' header): The API server rejected the request because it does not recognize the sandbox origin. Add the origin to the API server's allowlist, or use _meta.ui.domain to get a predictable origin that can be allowlisted.

    See the CSP & CORS guide for configuration examples.

    If the App declares color-scheme: light dark (or color-scheme: dark) and the host document does not, browsers insert an opaque backdrop behind the iframe to prevent cross-scheme bleed-through. Remove the color-scheme declaration and use the [data-theme] attribute pattern from the host context guide.

    • Test against the reference host: run npm start in this repository to serve examples/basic-host at http://localhost:8080. It logs all protocol traffic to the console.
    • Search GitHub Discussions for similar issues.
    • File a bug with a minimal reproduction in GitHub Issues.