Skip to main content
MCP Apps SDK

Overview

Resource _meta.ui controls security, rendering, and sandbox behavior for MCP App Views. All fields are optional. This metadata is set on resources registered via registerAppResource.

Where to Set _meta

Set _meta.ui on individual contents[] items returned by the registerAppResource read callback when the host needs to enforce CSP, permissions, stable domains, or border preferences for the rendered View.
When using registerAppResource, you can set _meta in two places:
  1. Listing-level — in the config object. Hosts see this in the resources/list response at connection time.
  2. Content-item level — on individual contents[] items returned by the read callback. Content-item values take precedence.
Use content-item metadata for values that affect the rendered iframe. Listing-level metadata is useful as a static hint during discovery, but a host that renders a View reads the resource content and should apply the content-item metadata.

Fields

csp — Content Security Policy

McpUiResourceCsp
Declares which external origins your View needs. The host uses these to build CSP headers for the sandboxed iframe.
MCP App HTML runs in a sandboxed iframe with no same-origin server. You must declare all origins — including where your bundled JS/CSS is served from (localhost in dev, your CDN in production).
All fields accept arrays of origin strings. Wildcard subdomains are supported (e.g., https://*.example.com). Empty or omitted fields default to no external access — this is the secure default.

connectDomains

Origins for network requests — fetch(), XMLHttpRequest, and WebSocket connections. Maps to the CSP connect-src directive. If omitted, no network connections are allowed from the View (secure default).

resourceDomains

Origins for static resources — images, scripts, stylesheets, fonts, and media files. Maps to CSP img-src, script-src, style-src, font-src, and media-src directives. If omitted, no external resources can be loaded (secure default).

frameDomains

Origins for nested iframes within your View. Maps to the CSP frame-src directive. Use this for embedding third-party content like YouTube or Vimeo players. If omitted, nested iframes are blocked (frame-src 'none').

baseUriDomains

Allowed base URIs for the document. Maps to the CSP base-uri directive. If omitted, only the same origin is allowed (base-uri 'self').

permissions — Sandbox Permissions

McpUiResourcePermissions
Requests browser capabilities for the View’s iframe. Each permission is declared as an empty object {} — its presence requests the capability.
Hosts MAY honor these permissions by setting appropriate iframe allow attributes, but are not required to. Your View should use JavaScript feature detection as a fallback and degrade gracefully when permissions are not granted.

domain — Stable Sandbox Origin

string
Requests a stable, dedicated origin for the View’s sandbox iframe. The value is not your server’s domain — it’s a subdomain within the host’s sandbox domain space.
By default, hosts assign each View an ephemeral sandbox origin (typically per-conversation). Setting domain tells the host to use a stable, deterministic origin instead — useful when external services need to recognize your app by origin. Use cases:
  • OAuth callbacks — redirect URIs require a stable origin on the allowlist
  • CORS policies — API servers that check Origin headers need a known value to allowlist
  • API key restrictions — external services that restrict by origin
This field is host-specific. The value is a subdomain within the host’s own sandbox domain — not your server’s domain. Each host has its own format:A cross-platform server must compute different values per host. For APIs using Access-Control-Allow-Origin: * or API key auth, you don’t need domain at all.

Cross-platform servers

A server that supports multiple hosts needs different domain values per host. The sunpeak framework accepts a map of clientInfo.name to domain string, with an optional default fallback for unmatched hosts:
Without sunpeak, detect the host in your resources/read handler and return the appropriate string. The MCP initialize handshake includes clientInfo.name, which identifies the connecting host. If omitted, the host uses its default sandbox origin.

prefersBorder — Visual Boundary

boolean
Controls whether the host renders a visible border and background around the View.
Explicitly set prefersBorder rather than relying on the host default, since defaults vary between ChatGPT and Claude.

Complete Example

TypeScript Types

In the sunpeak framework, resource metadata is co-located with resource components. See the Tool File Reference.