claude.ai MCP-Apps host silently drops `_meta.ui.csp.frameDomains`, blocking all third-party inline iframe embeds (YouTube, Salesforce, etc.)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
<html><head></head><body><h1>MCP Apps <code inline="">frameDomains</code> Are Not Applied to Effective <code inline="">frame-src</code> CSP, Blocking Standard Third-Party Embeds</h1><h2>Summary</h2><p>The MCP Apps feature allows custom connectors to return HTML resources that Claude renders inline within a sandboxed iframe. According to the MCP Apps API surface (<code inline="">@mcp-ui/server</code> / <code inline="">@modelcontextprotocol/ext-apps</code>), developers can declare allowed iframe destinations using:</p><p><code inline="">_meta.ui.csp.frameDomains</code></p><p>However, <code inline="">frameDomains</code> currently appears to be ignored by the claude.ai host runtime.</p><p>As a result, standard iframe embeds fail even when:</p><ul><li><p>the destination explicitly supports embedding;</p></li><li><p>the destination origin is correctly declared in <code inline="">frameDomains</code>;</p></li><li><p>the same embed works on a normal web page;</p></li><li><p><code inline="">connectDomains</code> and <code inline="">resourceDomains</code> are propagated successfully.</p></li></ul><p>This blocks an entire category of MCP App use cases including analytics dashboards, video embeds, design tools, maps, collaborative documents, and internal enterprise applications.</p><p>We reproduced the issue using:</p><ol><li><p>a minimal YouTube embed (public, no auth, no CORS complications);</p></li><li><p>Salesforce / Tableau Next dashboards (our production integration target).</p></li></ol><p>Both fail identically at the CSP <code inline="">frame-src</code> layer.</p><hr><h2>Expected Behavior</h2><p>When an MCP App declares:</p><p><code inline="">_meta.ui.csp.frameDomains</code></p><p>those origins should be forwarded into the effective <code inline="">frame-src</code> CSP policy applied to the rendered MCP App iframe.</p><p>A child iframe such as:</p><pre><code class="language-html"><iframe src="https://www.youtube-nocookie.com/embed/...">
</code></pre><p>should load normally if the origin is declared in <code inline="">frameDomains</code>.</p><hr><h2>Actual Behavior</h2><p>The child iframe navigation is blocked by the host CSP.</p><p>The iframe element renders in the DOM, but its document resolves to:</p><p><code inline="">chrome-error://chromewebdata/</code></p><p>with Chrome’s standard blocked-content page.</p><p><code inline="">connectDomains</code> and <code inline="">resourceDomains</code> are propagated correctly, but <code inline="">frameDomains</code> is not.</p><hr><h1>Reproduction #1 — Minimal YouTube Embed</h1><p>This reproduction intentionally removes all confounding variables:</p><ul><li><p>no authentication;</p></li><li><p>no Salesforce dependencies;</p></li><li><p>no SDKs;</p></li><li><p>no server-side complexity.</p></li></ul><h3>MCP Server Configuration</h3><p>The MCP App declares:</p><pre><code class="language-ts">resourceProps: {
_meta: {
ui: {
csp: {
frameDomains: [
'https://www.youtube.com',
'https://www.youtube-nocookie.com'
],
connectDomains: [
'https://www.youtube.com',
'https://www.youtube-nocookie.com',
'https://i.ytimg.com',
'https://yt3.ggpht.com'
],
resourceDomains: [
'https://www.youtube.com',
'https://www.youtube-nocookie.com',
'https://i.ytimg.com',
'https://yt3.ggpht.com',
'https://fonts.gstatic.com'
]
}
}
}
}
</code></pre><p>The HTML body is intentionally minimal:</p><pre><code class="language-html"><!DOCTYPE html>
<html lang="en">
<body style="margin:0;background:#000">
<iframe
src="https://www.youtube-nocookie.com/embed/aqz-KE-bpKQ?rel=0"
title="Big Buck Bunny"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
referrerpolicy="strict-origin-when-cross-origin"
style="width:100%;height:100vh;border:0">
</iframe>
</body>
</html>
</code></pre><h3>Observed Result</h3><p>The embedded iframe is replaced with Chrome’s blocked-content placeholder:</p><blockquote><p>“This content is blocked. Contact the site owner to fix the issue.”</p></blockquote><p>The iframe exists in the DOM with the correct <code inline="">src</code>, but the inner document resolves to:</p><p><code inline="">chrome-error://chromewebdata/</code></p><p>which indicates a browser-side iframe navigation block.</p><hr><h2>Key Diagnostic Evidence</h2><p>The rendered MCP App iframe URL includes forwarded values for:</p><ul><li><p><code inline="">connect-src</code></p></li><li><p><code inline="">resource-src</code></p></li></ul><p>but NOT <code inline="">frame-src</code>.</p><p>Observed URL pattern:</p><pre><code class="language-text">https://<id>.claudemcpcontent.com/mcp_apps
?connect-src=...
&resource-src=...
</code></pre><p>No equivalent <code inline="">frame-src</code> parameter is present.</p><h3>Forwarding Behavior</h3>
CSP Field | Forwarded
-- | --
connectDomains | ✅
resourceDomains | ✅
frameDomains | ❌
<p>This appears to be the root cause.</p><h3>DOM Evidence</h3><pre><code class="language-html"><iframe src="https://<id>.claudemcpcontent.com/mcp_apps?...">
<iframe src="https://<id>.claudemcpcontent.com/mcp_apps?...">
<body>
<iframe src="https://www.youtube-nocookie.com/embed/...">
#document (chrome-error://chromewebdata/)
</code></pre><p>The destination iframe is created correctly, but navigation is blocked before content loads.</p><h3>Browser Diagnostics</h3><pre><code class="language-json">{
"responseStatus": 0,
"transferSize": 0,
"duration": 649
}
</code></pre><p>Combined with:</p><p><code inline="">chrome-error://chromewebdata/</code></p><p>this strongly suggests CSP-level navigation blocking rather than:</p><ul><li><p>a YouTube-side rejection;</p></li><li><p>a network failure;</p></li><li><p>CORS issues;</p></li><li><p>authentication problems.</p></li></ul><hr><h1>Reproduction #2 — Salesforce / Tableau Next</h1><p>We reproduced the same issue using Salesforce-hosted Tableau Next dashboards.</p><p>The implementation pattern is identical:</p><pre><code class="language-html"><iframe src="https://<org>.lightning.force.com/...">
</code></pre><p>We also tested with the broadest possible CSP request:</p><pre><code class="language-ts">csp: {
frameDomains: ['https:'],
connectDomains: ['https:'],
resourceDomains: ['https:']
}
</code></pre><p>The embed still fails.</p><h3>Salesforce-Side Embedding Configuration</h3><p>The Salesforce org already permits embedding:</p><ul><li><p><code inline="">*.claudemcpcontent.com</code> added to CORS allowlists;</p></li><li><p>CSP Trusted Sites configured;</p></li><li><p><code inline="">frame-ancestors</code> verified;</p></li><li><p>embedding confirmed outside claude.ai.</p></li></ul><p>Observed failure:</p><pre><code class="language-text">violatedDirective: "frame-src"
effectiveDirective: "frame-src"
blockedURI: "https://<org>.salesforce.com/..."
</code></pre><p>Again indicating that the host CSP does not include the requested frame origin.</p><hr><h1>Broader Impact</h1><p>Without working <code inline="">frameDomains</code>, MCP Apps cannot support standard iframe-based integrations such as:</p><ul><li><p>YouTube / Vimeo / Loom;</p></li><li><p>Figma / Notion / Coda;</p></li><li><p>Google Maps / Mapbox;</p></li><li><p>Spotify / SoundCloud;</p></li><li><p>Tableau / Power BI / Looker;</p></li><li><p>GitHub Gists / CodePen / StackBlitz;</p></li><li><p>internal enterprise tools.</p></li></ul><p>This effectively disables the entire “interactive embedded app” category that MCP Apps are intended to support.</p><hr><h1>Business Impact</h1><p>This currently blocks a GA-track Tableau Next ↔ Claude integration.</p><p>The intended workflow is:</p><blockquote><p>“Ask Claude about a Tableau dashboard and interact with the live visualization inline inside the conversation.”</p></blockquote><p>The integration architecture is otherwise complete, but the current CSP behavior prevents rendering the embedded dashboard.</p><hr><h1>Requested Changes</h1><h2>1. Fix <code inline="">frameDomains</code> Forwarding</h2><p>Please treat:</p><p><code inline="">_meta.ui.csp.frameDomains</code></p><p>symmetrically with:</p><ul><li><p><code inline="">connectDomains</code></p></li><li><p><code inline="">resourceDomains</code></p></li></ul><p>and propagate it into the effective <code inline="">frame-src</code> policy applied to the MCP App iframe.</p><h2>2. Document the Effective Host-Side <code inline="">frame-src</code> Ceiling</h2><p>If claude.ai enforces an upper-bound allowlist for iframe destinations, please document:</p><ul><li><p>which origins are permitted;</p></li><li><p>whether wildcard HTTPS origins are supported;</p></li><li><p>whether developers can request additional origins.</p></li></ul><h2>3. Salesforce / Tableau Next Allowlist (If Needed)</h2><p>If the host maintains a closed allowlist, please add support for:</p><pre><code class="language-text">*.salesforce.com
*.my.salesforce.com
*.lightning.force.com
*.force.com
*.tableau.com
*.tableau-next.com
*.pc-rnd.salesforce.com
*.lightning.pc-rnd.force.com
*.my.pc-rnd.salesforce.com
*.pc-rnd.force.com
</code></pre><h2>4. Standard YouTube Embed Support</h2><p>Please ensure standard embed domains work as expected:</p><pre><code class="language-text">*.youtube.com
*.youtube-nocookie.com
</code></pre><p>These are widely used public iframe embed hosts and would serve as strong validation targets for the fix.</p><hr><h1>Additional Notes</h1><p>We are happy to:</p><ul><li><p>provide a minimal reproducible repository;</p></li><li><p>demo the issue live;</p></li><li><p>share screen recordings;</p></li><li><p>assist with validation once a fix is available.</p></li></ul><p>This issue appears isolated specifically to <code inline="">frameDomains</code> handling within the MCP App host CSP layer.</p></body></html>
Proposed Solution
All the details are added in Problem Statement
Alternative Solutions
All the details are added in Problem Statement
Priority
Critical - Blocking my work
Feature Category
MCP server integration
Use Case Example
All the details are added in Problem Statement
Additional Context
All the details are added in Problem Statement
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗