Skip to content

Run an MCP App in Claude, ChatGPT and VS Code

Spec
2026-07-28
Evidence
E1From official docs
MCP Apps SDK
@modelcontextprotocol/ext-apps@2.0.4

Your App from the first App guide works in basic-host. Real hosts add their own rules on top of the spec. This page collects what each host’s own documentation says.

These come from the stable spec (2026-01-26):

  • Sandboxed iframe. The View always runs in a sandboxed iframe and talks to the host only through postMessage. A web-based host must put a sandbox proxy on a different origin between itself and the View.
  • Content Security Policy. If your resource declares nothing, the host must apply a restrictive default: no network requests (connect-src 'none'), and scripts, styles and images only from the View itself or inline. To load anything from outside, declare it in the resource’s _meta.ui.csp:
Field Allows CSP directive
connectDomains fetch, XHR and WebSocket requests connect-src
resourceDomains Scripts, styles, images, fonts, media script-src, style-src, img-src, font-src, media-src
frameDomains Nested iframes frame-src (otherwise 'none')
baseUriDomains The document’s base URI base-uri (otherwise 'self')

The host may restrict further but must not allow domains you did not declare.

  • Permissions. _meta.ui.permissions can request camera, microphone, geolocation or clipboardWrite. Hosts may grant them, so check with feature detection.
  • Visibility. A tool’s _meta.ui.visibility defaults to ["model", "app"]. Set ["app"] for tools only the View should call; the host then hides them from the model.
  • Fallback. Hosts without MCP Apps support treat the tool as a plain tool, so the text content must make sense on its own.

From Anthropic’s documentation:

  • Try it in Claude Desktop by adding an example server from the ext-apps repository to claude_desktop_config.json (Settings → Developer → Edit Config), for example npx -y @modelcontextprotocol/server-map --stdio, then restarting. Claude asks for permission before it displays an App.
  • Testing a remote server locally: Anthropic suggests a proxy such as mcp-remote.
  • ui.domain gives your View a stable origin, which you need for your own OAuth flow or for API allowlists. For Claude the value must be the first 32 hex characters of the SHA-256 of your full connector URL, followed by .claudemcpcontent.com:
Terminal window
node -e 'const yourServerUrl = "https://example.com/mcp"; console.log(require("crypto").createHash("sha256").update(yourServerUrl).digest("hex").slice(0,32) + ".claudemcpcontent.com")'

We ran it: https://example.com/mcp gives c3d80a4ed901ee05b21755a88273b4a4.claudemcpcontent.com, matching the documentation. With a trailing slash (https://example.com/mcp/) the result is completely different, which is the most common cause of a mismatch.

  • Errors: when the value is wrong, Claude shows Invalid ui.domain format or ui.domain mismatch instead of the App. Local stdio connectors have no URL, so ui.domain is not available for them.
  • App does not appear: the documented causes are a missing app.connect() call and a View with zero height.
  • Large results: on claude.ai and Claude Desktop, a tool result over roughly 150,000 characters may be written to the code sandbox instead of passed inline, and the View never receives its data. Keep the first result small and load details with View-initiated tool calls.
  • iOS: the Claude iOS app omits the Referer header on cross-origin requests from the View. Allow requests by Origin (*.claudemcpcontent.com), not by Referer.
  • Debugging: in Claude Desktop, Help → Troubleshooting → Enable Developer Mode, then open the developer tools. The View is the inner of two nested iframes.

From OpenAI’s documentation:

  • ChatGPT implements the MCP Apps standard: _meta.ui.resourceUri on the tool, a resource served as text/html;profile=mcp-app, JSON-RPC over postMessage.
  • _meta["openai/outputTemplate"] is still honored as an alias for _meta.ui.resourceUri, and the older window.openai calls map to the standard ones (for example window.openai.callTool to tools/call). OpenAI recommends the standard methods for new code.
  • Declare the exact domains in _meta.ui.csp. Nested frames are blocked by default, and the declared policy is checked against what the UI really does when an app is reviewed.
  • OpenAI advises treating each resource URI as a cache key: publish a new URI for a breaking change to the View.

The VS Code team announced MCP Apps support on 2026-01-26, first in VS Code Insiders. Apps render in the agent chat. The announcement names no setting or flag; check the current VS Code documentation for your version.

  • Return meaningful text content from every App tool.
  • Declare every outside domain in _meta.ui.csp; test with the restrictive default first.
  • Set _meta.ui.prefersBorder explicitly; the spec notes that hosts’ defaults vary.
  • Only set ui.domain if you need a stable origin, and compute it per host.

Sources

MCPDev is community documentation. It is not affiliated with the Model Context Protocol project or with the vendors of the clients it covers.