MCP Apps
    Preparing search index...
    • Security

    CSP & CORS

    Unlike regular web apps, MCP Apps HTML is served as an MCP resource and runs in a sandboxed iframe with no same-origin server. Any app that makes network requests must configure Content Security Policy (CSP) and possibly CORS.

    CSP controls what the browser allows. You must declare all origins in _meta.ui.csp (McpUiResourceCsp) — including localhost during development. Declare connectDomains for fetch/XHR/WebSocket requests and resourceDomains for scripts, stylesheets, images, and fonts.

    CORS controls what the API server allows. Public APIs that respond with Access-Control-Allow-Origin: * or use API key authentication work without CORS configuration. For APIs that allowlist specific origins, use _meta.ui.domain to give the app a stable origin that the API server can allowlist. The format is host-specific, so check each host's documentation for its supported format.

    // Computes a stable origin from an MCP server URL for hosting in Claude.
    function computeAppDomainForClaude(mcpServerUrl: string): string {
    const hash = crypto
    .createHash("sha256")
    .update(mcpServerUrl)
    .digest("hex")
    .slice(0, 32);
    return `${hash}.claudemcpcontent.com`;
    }

    const APP_DOMAIN = computeAppDomainForClaude("https://example.com/mcp");

    registerAppResource(
    server,
    "Company Dashboard",
    "ui://dashboard/view.html",
    {
    description: "Internal dashboard with company data",
    },
    async () => ({
    contents: [
    {
    uri: "ui://dashboard/view.html",
    mimeType: RESOURCE_MIME_TYPE,
    text: dashboardHtml,
    _meta: {
    ui: {
    // CSP: tell browser the app is allowed to make requests
    csp: {
    connectDomains: ["https://api.example.com"],
    },
    // CORS: give app a stable origin for the API server to allowlist
    //
    // (Public APIs that use `Access-Control-Allow-Origin: *` or API
    // key auth don't need this.)
    domain: APP_DOMAIN,
    },
    },
    },
    ],
    }),
    );

    Note that _meta.ui.csp and _meta.ui.domain are set in the contents[] objects returned by the resource read callback, not in registerAppResource()'s config object.

    Note

    For full examples that configures CSP, see: examples/sheet-music-server/ (connectDomains) and examples/map-server/ (connectDomains and resourceDomains).