AI Engineer

Why MCP and ChatGPT Apps Use Double Iframes — Frédéric Barthelet, Alpic

2851 summary words 13 min summary Watch video

Start with the signal

13 min read

Summary

At-a-Glance

  • Verdict: Watch fully
  • Core thesis: ChatGPT and Claude use double-nested iframes to safely render third-party MCP app UIs while preventing malicious access to parent DOM, local storage, and cookies—solving the security dilemma of running untrusted code inside a trusted conversational agent.
  • Why it matters: Understanding double iframe architecture is critical for building MCP apps that work in production; missing Content Security Policy (CSP) declarations cause app store rejections and runtime failures.
  • Best use: Technical reference for anyone building MCP apps or similar embedded third-party UI systems; explains the security trade-offs and developer tooling needed to ship production apps.

Executive Summary

Fred Barthelet (CTO, Alpik) explains why ChatGPT and Claude use a double iframe mechanism to render MCP app UIs inside conversational agents. The root problem: how to safely embed third-party HTML/JS views without allowing malicious apps to access the host's cookies, local storage, or DOM. Single iframe solutions fail because they either share the parent origin (allowing escapes) or break origin-dependent APIs like localStorage when sandboxed.

The chosen architecture uses two nested iframes: an outer iframe served on a unique subdomain per app (e.g., abc123.openaiusercontent.com) and an inner iframe with srcdoc that contains the actual app HTML. The outer iframe isolates origins so apps can't collide or access ChatGPT's storage; the inner iframe injects dynamic content. This mirrors the solution Facebook pioneered for its app marketplace in the 2010s.

For developers, the key implication is declaring every external domain your app calls (APIs, scripts, images) in MCP metadata so they're included in the nested iframe's CSP. Missing domains cause app store rejections and silent production failures. OpenAI's developer mode historically disabled CSP enforcement, hiding issues until production. Fred demos SkyBridge, an open-source framework from Alpik, featuring a CSP Inspector that live-checks declared vs. actual domains during development, preventing submission rejections.

Key Takeaways

  • Claim: MCP apps use double nested iframes to safely render third-party UI inside ChatGPT and Claude while preventing security exploits. | Evidence: An outer iframe on a unique subdomain per app (e.g., abc123.openaiusercontent.com) isolates origins; an inner iframe with srcdoc injects the app's HTML. This prevents apps from accessing ChatGPT's localStorage, cookies, or DOM, while still allowing each app to use origin-indexed APIs like localStorage without collisions. | Caveat: This architecture requires developers to explicitly declare all external domains (APIs, scripts, images) in MCP metadata; missing declarations break functionality in production. | Implication: If you're building MCP apps or similar embedded systems, you must understand CSP and origin isolation. Misconfigurations lead to app store rejections and silent runtime failures. This is a hard requirement, not optional polish. | Timestamp: timestamp unavailable
  • Claim: Single iframe approaches fail due to the security/functionality dilemma: same-origin iframes allow escapes; sandboxed iframes break localStorage/cookies. | Evidence: Using iframe srcdoc shares the parent's origin and CSP, letting malicious scripts access ChatGPT's localStorage. Sandboxing the iframe with an opaque origin (null) blocks localStorage/cookies for the app itself. Adding 'allow-same-origin' to sandbox brings back the parent origin, re-enabling escapes. | Caveat: The speaker does not discuss alternative sandboxing strategies like WebAssembly or restrictive CSP nonces for inline scripts; focus is purely on iframe isolation. | Implication: Any platform embedding third-party UI faces this trade-off. Double iframes are the proven solution from Facebook's app marketplace days. If you're designing a plugin/app system, plan for this complexity upfront. | Timestamp: timestamp unavailable
  • Claim: Using a proxy domain (openaiusercontent.com) for all apps avoids updating ChatGPT's frame-src CSP for every new app but requires OpenAI to host untrusted code on its domain. | Evidence: A single proxy domain (e.g., openaiusercontent.com) is added to ChatGPT's frame-src CSP once. Each app gets a unique subdomain. The outer iframe script (same for all apps) loads the app's HTML into the inner iframe, isolating origins without requiring CSP updates per app. | Caveat: This means OpenAI serves third-party code on its own domain, which is a security concern. The speaker notes this is 'not a very good position to be in' but necessary for scale. | Implication: If you run a platform with a plugin marketplace, you'll likely need a user-content domain and infrastructure to serve outer iframe scripts. This is non-trivial infra work but unavoidable for sandboxing at scale. | Timestamp: timestamp unavailable
  • Claim: Developers must declare all external domains their MCP app depends on in metadata (connect-src, script-src, img-src) or the app will fail silently in production. | Evidence: Fred encountered this when adding a fetch call to an IP location API; the CSP Inspector immediately flagged the missing domain. OpenAI's developer mode previously disabled CSP, so developers only discovered missing declarations after app store submission or in production. | Caveat: The speaker does not mention whether wildcards (e.g., *.example.com) are supported or how to handle dynamic third-party domains (e.g., user-uploaded content URLs). | Implication: Build a checklist or automated tooling to audit every external call in your app before submission. Missing CSP declarations are the top cause of app store rejections, per Fred's observation. | Timestamp: timestamp unavailable
  • Claim: SkyBridge (Alpik's open-source framework) provides end-to-end type safety, polyfills for host-specific APIs, and a CSP Inspector that live-checks declared vs. actual domains during development. | Evidence: In the demo, Fred runs a Magic 8 Ball app with SkyBridge. The CSP Inspector shows green when all domains are declared. Adding an undeclared fetch to an IP API immediately flags the domain as missing. Adding it to metadata turns the inspector green. | Caveat: SkyBridge is a superset on top of OpenAI's official app SDK; vendor lock-in risk if Alpik stops maintaining it or if the SDK diverges significantly. No mention of pricing or support model. | Implication: If you're building multiple MCP apps, SkyBridge's CSP Inspector could save significant debugging time and prevent rejections. Evaluate it against the official SDK for your use case. The CSP Inspector alone could justify adoption for teams shipping to ChatGPT/Claude. | Timestamp: timestamp unavailable

Detailed Brief

MCP Apps: New UI Surface for Conversational Agents

  • Claims: MCP and ChatGPT apps are a new acquisition channel for businesses, exposing products/services inside ChatGPT and Claude via discoverable connectors.; Apps are browsable in ChatGPT's app store and auto-suggested in chat when contextually relevant.; Apps add interactive UI (views) to conversational agents, moving beyond text-only interactions.; Views are HTML documents (with JS/CSS) rendered in iframes, triggered by tool calls from the conversational agent.
  • Evidence: ChatGPT app store and Claude connectors are the two main ecosystems.; Views were first prototyped with MCP UI, released by OpenAI in October, then standardized in MCP's app extension.; Views are discovered via tool list calls at conversation start; each tool that supports UI advertises the resource needed to render it.; View resources can be cached ahead of time or fetched on-demand when the tool is called.
  • Caveats: No discussion of view rendering performance or latency trade-offs between caching vs. on-demand fetching.; No mention of view size limits or best practices for keeping views lightweight.
  • Implications: MCP apps are a strategic channel for SaaS/B2B products to reach ChatGPT's massive user base. If your product can add context or actions to conversations, this is a new GTM lever.; Understanding the iframe architecture is non-negotiable for shipping production apps; security constraints shape what you can build.

Why Single Iframes Fail: CSP and Origin Isolation Dilemmas

  • Claims: Rendering third-party HTML directly in a single iframe with srcdoc shares the parent's origin and CSP, allowing escapes.; ChatGPT's CSP requires all scripts to be signed with a per-request nonce; third-party scripts are blocked.; Relaxing CSP to allow arbitrary scripts breaks security by letting apps access ChatGPT's localStorage and cookies.; Sandboxing the iframe creates an opaque (null) origin, blocking access to parent resources but also breaking localStorage/cookies for the app itself.; Adding 'allow-same-origin' to the sandbox attribute brings back the parent origin, re-enabling escapes.
  • Evidence: Fred walks through each approach step-by-step, showing why iframe srcdoc alone fails due to shared origin and CSP conflicts.; ChatGPT's CSP includes script-src directives requiring nonces, preventing execution of unsigned third-party JS.; Sandboxed iframes with opaque origins can't use localStorage, IndexedDB, or cookies because those APIs are origin-indexed.
  • Caveats: No discussion of Content Security Policy Level 3 features like trusted types or stricter sandboxing options.; No exploration of Service Workers or other browser APIs as alternative isolation mechanisms.
  • Implications: Single iframe solutions are non-starters for third-party app marketplaces. If you're designing a plugin system, plan for double iframes or equivalent isolation from day one.; This is a solved problem architecturally (Facebook did it a decade ago), but requires careful CSP configuration and developer education.

Double Iframe Architecture: The Production Solution

  • Claims: The double iframe approach uses an outer iframe on a unique subdomain per app (e.g., abc123.openaiusercontent.com) to isolate origins.; The outer iframe loads a single, static script loader (same content for all apps) that creates an inner iframe with srcdoc containing the app's HTML.; Unique subdomains prevent localStorage/cookie collisions between apps while keeping outer iframe infrastructure simple (same script everywhere).; This mirrors Facebook's app marketplace architecture from the 2010s.; The outer iframe can include a meta tag specifying a CSP for the inner iframe, allowing apps to control their own security posture.
  • Evidence: Fred describes the exact implementation: outer iframe on unique subdomains, inner iframe with srcdoc injecting app HTML.; Using the same script loader across all subdomains minimizes infrastructure complexity; no per-app serving logic.; CSP for the inner iframe is declared in MCP metadata and injected as a meta tag by the outer iframe script.
  • Caveats: No mention of fallback mechanisms if the outer iframe script fails to load or if subdomains are misconfigured.; No discussion of how unique subdomains are generated or whether there's a limit (e.g., 100k apps = 100k subdomains).
  • Implications: If you're building a platform with third-party UIs, budget for a user-content domain and subdomain provisioning system. This is foundational infra, not a nice-to-have.; The double iframe pattern is battle-tested. Don't reinvent; adapt Facebook's approach and focus on developer tooling (like CSP validation) instead.

CSP Declaration Requirements and Common Pitfalls

  • Claims: Developers must declare all external domains their app depends on in MCP metadata (connect-src for APIs, script-src for scripts, img-src for images).; Missing domain declarations cause silent failures in production and app store rejections.; OpenAI's developer mode historically disabled CSP enforcement, hiding issues until production deployment.; CSP errors are the top cause of ChatGPT app store submission rejections, per Fred's experience.
  • Evidence: Fred cites personal experience building apps and seeing rejections due to missing CSP domains.; In the demo, adding an undeclared fetch call immediately triggers a CSP violation in the inspector.; OpenAI has since improved developer mode to enforce CSP during development.
  • Caveats: No guidance on handling dynamic third-party domains (e.g., user-uploaded images on CDNs).; No mention of CSP reporting APIs or tools to catch violations post-deployment.
  • Implications: Treat CSP declarations as a pre-flight checklist, not an afterthought. Build or use tooling (like SkyBridge's inspector) to catch missing domains during development.; If you're advising startups building MCP apps, emphasize CSP auditing upfront to avoid wasted submission cycles.

SkyBridge Framework and CSP Inspector Demo

  • Claims: SkyBridge is an open-source framework from Alpik, built on top of OpenAI's official app SDK.; It provides end-to-end type safety between MCP servers and app views, polyfills for host-specific APIs, and modern dev features.; The CSP Inspector compares declared domains in metadata against actual network calls made by the app, flagging missing declarations live.; Fred demos a Magic 8 Ball app; adding an undeclared API call immediately flags the domain as missing in the inspector.
  • Evidence: In the demo, the CSP Inspector shows green when all domains are declared. Adding a fetch to an IP location API without declaring it triggers a red flag. Adding the domain to metadata resolves it.; SkyBridge includes a dev tool accessible in the browser with tool execution, live view rendering, and CSP validation.; Fred mentions many rejections from ChatGPT's app store due to missing CSP domains, which SkyBridge aims to prevent.
  • Caveats: No discussion of SkyBridge's pricing, support, or long-term maintenance commitment.; No comparison of SkyBridge vs. official SDK performance or feature gaps.; Fred works for Alpik (SkyBridge's creator), so there's a promotional angle; no independent validation of claims.
  • Implications: If you're building multiple MCP apps, SkyBridge's CSP Inspector alone could justify adoption by preventing rejection cycles and production bugs.; Evaluate SkyBridge's type safety and polyfills against your team's existing tooling. If you're in TypeScript and shipping to multiple hosts (ChatGPT, Claude), this could streamline development.; Consider forking or building a similar CSP validator if you prefer not to depend on Alpik's framework; the core idea (compare metadata to network calls) is straightforward.

Notable Concepts & Terms

  • MCP Apps / ChatGPT Apps: New surface area for businesses to expose products/services inside conversational agents (ChatGPT, Claude) via discoverable connectors and interactive UIs (views). Apps are triggered by tool calls and rendered in iframes.
  • Views: Small HTML/JS/CSS snippets rendered in iframes inside conversational agents. Triggered by tool calls, served by MCP servers, and displayed to users as interactive UI beyond text-only responses.
  • Content Security Policy (CSP): HTTP response headers defining which scripts, styles, images, and APIs a browser can load/execute for a given page. Critical for preventing XSS attacks. In MCP apps, CSP directives must be declared in metadata to allow external domains in nested iframes.
  • Double Iframe Architecture: A security pattern where an outer iframe (unique subdomain per app) loads a static script that creates an inner iframe (srcdoc) with the app's HTML. Isolates origins to prevent malicious access to parent DOM/storage while preserving per-app localStorage/cookies. Based on Facebook's app marketplace design.
  • Opaque Origin / Sandbox Attribute: An iframe with the 'sandbox' attribute gets an opaque (null) origin, isolating it from the parent DOM. However, this breaks origin-indexed APIs like localStorage unless 'allow-same-origin' is added, which re-enables escapes. Double iframes solve this by using unique subdomains instead.
  • SkyBridge: Open-source framework from Alpik, built on OpenAI's app SDK. Provides end-to-end type safety, polyfills for host-specific APIs, and a CSP Inspector that validates declared vs. actual domains during development, preventing app store rejections.
  • CSP Inspector (SkyBridge): A dev tool in SkyBridge that live-checks declared CSP domains in MCP metadata against actual network calls made by the app. Flags missing domains immediately, preventing silent production failures and app store rejections.

Operator Notes / Why Ken Should Care

  • If you're building agent systems that embed third-party UIs (e.g., Cursor plugins, Replit extensions, custom AI tools), double iframe architecture is the proven pattern. Plan for a user-content domain and CSP tooling upfront.
  • For startups targeting ChatGPT/Claude app stores, CSP declaration is a hard gate. Build or adopt tooling (like SkyBridge's inspector) to catch missing domains during development, not after submission.
  • This talk is technical depth on a narrow but critical issue. If you're advising teams on MCP app development, share this as required reading to avoid costly submission rejections.
  • SkyBridge's CSP Inspector is a strong example of developer tooling that solves a real pain point (CSP errors are the top rejection cause). Consider similar patterns for other hidden failure modes in agent workflows.
  • The Facebook app marketplace parallel is instructive: this problem was solved a decade ago, but each new platform (ChatGPT, Claude) must re-implement it. If you're designing a plugin/app system, study Facebook's and OpenAI's approaches before building.
  • For AI ops: if you're orchestrating multiple MCP servers or tools, understand that views are rendered client-side in iframes. This limits server-side control over UI but enables rich, interactive experiences beyond text.

Watch Map

  • timestamp unavailable: Introduction: Fred introduces MCP/ChatGPT apps and the double iframe problem. Quick recap of MCP apps as a new UI surface for conversational agents.
  • timestamp unavailable: CSP and iframe basics: Explains Content Security Policy, iframe srcdoc vs. src attributes, and why single iframes fail due to origin sharing and CSP conflicts.
  • timestamp unavailable: Why sandboxing alone doesn't work: Demonstrates how sandboxed iframes break localStorage/cookies, and adding 'allow-same-origin' re-enables escapes.
  • timestamp unavailable: Double iframe architecture explained: Details the production solution using unique subdomains for the outer iframe and srcdoc for the inner iframe. Compares to Facebook's app marketplace.
  • timestamp unavailable: CSP declaration requirements: Emphasizes the need to declare all external domains in MCP metadata. Discusses common pitfalls and OpenAI's developer mode changes.
  • timestamp unavailable: SkyBridge demo: Live demo of the CSP Inspector validating declared vs. actual domains for a Magic 8 Ball app. Shows how missing domains are flagged and resolved.
  • timestamp unavailable: Conclusion and Q&A: Wraps up with QR codes for slides and SkyBridge repo. Mentions a lottery for a Skigoro mask (prize for starring the repo).

Source/Metadata

  • Title: Why MCP and ChatGPT Apps Use Double Iframes — Frédéric Barthelet, Alpic
  • Transcript words: 4475
  • Duration seconds: 1211
  • Timestamp note: Timestamps were unavailable in the transcript; watch map notes are based on content flow rather than exact timecodes.
Full transcript 3276 words · 20 min read
0:14

SPEAKER_00

Hi everyone, my name is Fred. I'm the CTO and co-founder of Alpik, the MCP hosting company. And today I would like to share with you an adventure deep diving into the double iframe mechanism that we have on ChatGPT and MCP app and why it matters when we build apps.

0:26

SPEAKER_00

First thing first, if you haven't had the chance to listen to Ido and Léa talks just before about MCP apps, a quick sum up of what those MCP and ChatGPT apps are. That's a new surface area for your business to expose product and services with a new acquisition channel that has two main criteria. First one being discoverability. So you will have ecosystems of connectors and apps available in consumer generalistic agents like ChatGPT and Claude. So ChatGPT app store and Claude connectors. Those apps are browsable inside the store but they are also discoverable in chat. So if you're having a conversation that's relevant for an app to be brought into to add additional context and feature some nice additional actions, they will be brought into the conversation. And the second part, which is the biggest part and what we will be focusing on in this talk, which is the addition of interactive UI inside those conversational agents where you used to add text only. Apps adds a new layer of UI that could be provided by the MCP server but could be generated or generative UI as well. They were first using MCP UI that was developed by Lea Danido just before, then released by OpenAI with an apps SDK back in October last year and standardized across multiple clients on the first official extension of MCP called the app extension.

0:33

SPEAKER_00

How does it work down the hood? If we take a little bit closer look at how this UI is brought into the conversation, those are brought using views. Views are the name that we use for those small snippets of UI that appears inside the conversation. Views are always rendered as a result of a tool call. So if your server exposed multiple tools to be used, you can actually add metadata on some of them to say this tool is best used when the results will be displayed using a specific UI. And if the host supports MCP apps, it will use the relevant view corresponding to this tool call to display the results. Views are simple HTML documents. You can include JS and CSS inside. Nothing new under the sun here. It's just a way to package those small snippets of application. And they are discoverable ahead of time because all views are described on the tool list calls that happens at the beginning of the conversation between the host and your MCP server or MCP app. So each tool that supports UI will advertise the resource that's needed to display the UI. It can be cached ahead of time or it can be served and downloaded and served right away when the tool calls that needs UI to be rendered is made. The conversational agent on the host will create this new iframe where the view will be displayed and it will inject the tool results inside so that you have dynamic content rendered to the user.

0:39

SPEAKER_00

If you take a closer look at what is inside the DOM of the host when you take a... I was a bit curious. I wanted to know how it was working or how ChatGPT was actually rendering third-party UI inside the conversation. I was a bit surprised and I was met with the idea of what is not so much expectation about having a double iframe, having an iframe nested inside another iframe. And this gave me the idea for these talks. I want to bring you today with me, deep diving into why the decision was made to do this kind of inception nesting of iframes and what are the benefits, what was it put in place and what are the implications when you build apps, what you should be paying attention to and how to make sure that your experience is very nice.

0:47

SPEAKER_00

Before we go into that, let's take a close look at what ChatGPT was before MCP apps were implemented. We'll be using ChatGPT as the example through our deep dive, but the exact same happened on Claude AI if you want to take another look by yourself. The initial thing to take a look at that is very important is something called content security policy. Those are directives returned by a server as response header to document calls. So when you load ChatGPT inside your browser, ChatGPT will respond with a document plus security policy, directive on what the browser should be allowed to load and execute and what it shouldn't be able to load and execute. You've got multiple directives including inside content security policy, some about which scripts you can run, which CSS style sheet you can download, which image you can download, which API you can connect to and ask questions to. I will not go into the details, but two are very important to remember here. FrameSrc, which is the directive to allow a specific website to render iframe inside the document, and ScriptSrc, which allows specific site scripts to be run inside the browser.

0:52

SPEAKER_00

To be able to run external UI inside ChatGPT, we will use a dedicated HTML element that has been made specifically for this purpose, which is the inline frame element or iframe, that is made to spawn up nested browsing context inside your browser window. So those small pieces of views will be rendered as almost separately, completely isolated browsing context. They are very convenient, and they have two ways to be used. First one is to provide a source for the iframe that you want to render, so a URL of another page to be loaded by your browser and executed locally and rendered inside the space it's made for. And the source doc, which is another attribute which allows you to push inside the iframe content that you want to render as is, without having the browser to load another content.

0:58

SPEAKER_00

So if we want to build this marketplace of app and have third-party UI rendered inside ChatGPT, why not use straight away source doc as the attribute for injecting context into. And I'm realizing now that it's a little bit small, but I think I can zoom in a bit. No, I cannot. Okay, sorry about that. You'll have to trust me about what is written inside here. So I will just put inside an iframe, injecting context into the iframe, context being the content being the resource that is being exposed by the MCP server. So pure HTML loaded inside.

1:05

SPEAKER_00

If I do that, it's not going to work, mostly because when you load up an iframe with source doc attribute specified, the iframe that you are spawning up is sharing the same origin and sharing the same, therefore, CSP as the host that is responsible for rendering it. So any script that would be part of your application that would be completely blocked by existing ChatGPT CSP on script src directive, which basically require every script in ChatGPT to be signed with a specific nonce produced ahead of time at each request, which is a cool security feature to put in, but it prevents any app to be able to execute JS. So in order to do that, what if we relax a little bit the content security policy of ChatGPT, and make it so that it can execute any line of code. I would not suggest doing that into production, just an experimental thought here. But if you do that, you face a new problem. Basically, you are sharing the same origin as your parent DOM. So the loaded iframe script would be able to access local storage or cookies that are indexed by origin. So you would be able as an app to, for example, get the existing local storage of ChatGPT and send it to your backend server,

1:11

SPEAKER_00

But it prevents any app from being able to execute JS. So in order to do that, what if we relax a little bit the content security policy of ChatGPT and make it so that it can execute any line of code? I would not suggest doing that into production, just an experimental thought here. But if you do that, you face a new problem. You are sharing the same origin as your parent DOM. So the loaded iframe script would be able to access local storage or cookies that are indexed by origin. So you would be able as an app to, for example, get the existing local storage of ChatGPT and send it to your backend server, which if you are OpenAI, you would not want people to be able to do.

1:31

SPEAKER_00

So let's roll back, put back the CSP as it was before, and instead sandbox the iframe. Sandbox is another attribute that you can use on iframes, allowing iframes to be rendered in what we call an opaque origin. It would mean that the iframe will not share anymore the parent origin. It will be something equivalent to null, making sure that they don't share the same origin and won't have the same problem of script being able to access the parent DOM. However, doing so, you lack any capabilities that are dependent on origin indexing. Because all content, all scripts that are rendered inside your iframe will not be pointing towards a null origin.

2:14

SPEAKER_00

You cannot use local storage, you cannot use local index DB, you cannot use cookies, because those are indexed by origin. And the only way to actually provide an origin to a sandboxed iframe is to put allow same origin, which is an additional attribute that brings back the exact same origin as the parent back into the iframe, and you're back to square one where you have an iframe with exactly the right condition to escape its sandboxing and access parent DOM, access parent local storage, access parent cookies. So iframe source doc is not the way to go forward. Let's move on to the next best solution that we have, using the source attribute.

2:43

SPEAKER_00

Source attribute basically allows me to reference an endpoint that will be the content loaded by the browser inside this iframe. I'm a developer of a TGPT app, an MCP app. Why not expose my view, my small HTML application, as a normal endpoint, for example on the view endpoint of my own server? That would be a nice way to do it. However, it would require OpenAI to modify another CSP directive, which is the frame source directive, listing all domains that are allowed to actually render iframe on ChatGPT, to include an infinite list of all the MCP applications that will be developed by various companies and brought into the store.

3:15

SPEAKER_00

So every time a new app would come out, ChatGPT would have to update CSP to include the new domain so that the frame can be rendered on this specific domain. This is not doable full scale. So what we can do instead is provide a proxy controlled domain, a single one that will be owned by ChatGPT in that case, for example openaiusercontent.com. That's an actual domain that they're using for user content that they want to expose on their own domain. And use this domain as a reference inside the frame source to make sure that the directive does not block rendering any iframe that are loaded on there.

3:51

SPEAKER_00

And you need to provide a server on the OpenAI user content that's able to download the resource content from the MCP server, the HTML, and expose it so that it can be rendered, for example on any subdomain and use the first part of the subdomain as the routing key to the right application. Doing so, you effectively need to put in motion an infrastructure where your domain hosts external third-party UI from all apps that will be submitted on your store. Which is not a very good position to be into because once again you will be responsible for code that you don't know what's doing and you will be exposing it on your own domain.

4:09

SPEAKER_00

In addition to that, if you're not OpenAI or if you're not Anthropic, you might not have the resources to host to put in place infrastructure required to serve this kind of dynamic serving of content. So what you can do instead is go to the double iframe mechanism. And what you will do with that is basically load the same script for everybody, which will be a simple script responsible to recover the resources and initiate an iframe with the source doc attribute. So we will put the content inside. But this iframe will not be served at top level because it shares the same origin and it has the escaping problem we were mentioning before.

4:37

SPEAKER_00

It will be served inside an iframe with a dedicated domain that is different from the GPT to make sure the isolation stays there. You don't want to stop there. Actually, you want to put subdomains for this exact script loader. It will be the exact same content that will be served every time, but you want to put it on various subdomains so that if your app uses any API that requires origin indexing, like local storage or cookie, you don't have collision between your app. So you want app abc123 not to be able to access local storage from app abc456, for example.

5:07

SPEAKER_00

The infrastructure for that is much less intensive because you're serving the exact same script content of the first iframe for every subdomain that is equal to the same. So you want to be able to provide the same content security policy definition to the app itself so that it can prevent execution of malicious script or rendering of iframe directly inside the view. There is a way to provide this into the mcpspec and the way you will render it is using a specific meta tag inside the first iframe. This is the actual solution that I implemented into production. And it's not a new solution.

5:43

SPEAKER_00

It's been around for a long time and the first time this solution was implemented was back in Facebook days when they released the app marketplace, which is exactly the same problem that you have to run and render a third party UI inside the context of your own application. What's important for you as an app developer is to make sure what are the specs available for you to be able to control the behavior that results from this double iframe nesting. And the thing that you will have to make sure to do is every time you build an application declare all domains your application depends upon inside the provided metadata in the mcpspec.

6:02

SPEAKER_00

So that you are sure that they will be rewritten correctly inside the nested iframe. For example, if you are from your app connecting to an external API to fetch data, you need to reference this domain inside the connect src directive of the metadata. Same thing for the script of image, frame and base UI, not so much used. But the two first ones are very important. And it reminded me of a very old problem that I had when I started my developer days back in 2016. As a new developer in the space I was experiencing trouble getting cross-origin resource security right calls. I had trouble getting it right.

6:51

SPEAKER_00

CSP reminded me of those ugly days of not getting right for the first time with calls. So there has been effort in the ecosystem to make builders' life better. Especially for example on OpenAI side where they activated, they added an option in developer mode. So if you are a developer and developing app, they have a specific mode which is developer mode which allows you to have access to additional features. Up to today, when you were in developer mode, all CSP were removed. So you were discovering when you were going into production if some of your servers could not be reached because of missing domains inside your CSP.

7:38

SPEAKER_00

As a new developer in the space, I was experiencing trouble getting cross-origin resource security right with calls. I had trouble getting it right. CSP reminded me of those ugly days of not getting it right for the first time with calls. So there has been effort in the ecosystem to make builders' lives better. Especially, for example, on the OpenAI side, where they activated—they added an option in developer mode. So if you are a developer developing an app, they have a specific mode, which is developer mode, which allows you to have access to additional features. Up to today, when you were in developer mode, all CSP were removed.

8:28

SPEAKER_00

So you were discovering when you were going into production if some of your servers could not be reached because of missing domains inside your CSP. Which was not ideal. They are not the only ones doing work to make builders' lives much easier. At Alpic, we built an open source framework called SkyBridge. SkyBridge is a superset of features on top of the official app SDK Ido and Lead were mentioning. It brings a few things to the table. End-to-end type safety between your MCP server and your app, widget, and views.

9:12

SPEAKER_00

You have a lot of APIs that provide polyfill for features that are not part of the command specification and specific to some of the hosts, some of Cloud and some of the ChatGPT APIs. And we provide a bunch of modern development features, especially in the on-dev environment features. And I wanted to show you one specifically made for CSP, which we call the CSP Inspector. Time for a small demo. I do have a few minutes left. Perfect. Let me quickly switch to my screen. Okay. So this is an example code base that will be generated when you create a new SkyBridge application. This example SkyBridge application comes with a small application.

10:11

SPEAKER_00

It's an eight ball that you can ask any question to that will respond with one of the 25 predefined answers. It has an MCP tool that serves as generating the answer and a view that's there to display the question and the answer to the questions that you ask. When I start the server of SkyBridge, I have access in my browser to a dev tool, which is a small app that will give me inspection tooling to work with my app before I bring it to the GPT. For example, on the left, I have a list of tools that are exposed by my app. I can, if I want, execute any of the tools. So, for example, here I'm executing the magic eight ball tool.

10:45

SPEAKER_00

And if there are views associated with this tool, that will be rendered inside the inspector for me to have a closer look at it and make changes and see those changes reflected live in the UI. The neat thing I wanted to demonstrate is the CSP part of the inspector that we built, which basically looks at all the domains that you listed inside your metadata and all the domains that are actually accessed by calls made by your view and compile them to make sure that none of them are not listed yet. So, for example, here, everything looks green.

11:04

SPEAKER_00

But if I go back to my actual code base and, for example, fetch some API to get info about my IP location, this will be affected straight away in the inspector because the component has been re-rendered. And I know I have the exact domain that I just called listed as missing from the metadata. And I can go back inside my application and add the missing domain. And now it should appear green if I reload it. Yeah, everything good. So, neat little tool. There are a lot of other features that are packed inside SkyBridge.

12:10

SPEAKER_00

But that's one of them that we made sure to be available to builders because we've seen a lot of rejection coming from the GPT App Store submission because of missing CSP. And apps not working in production because of missing CSP domains. Just to finish up quickly, if I can. Up. Up. This one, yeah. Yeah, that's all. Thank you again for your time. If you want to grab the slides and take a look later on, feel free to scan the first QR code.

13:15

SPEAKER_00

If you want to give a try to SkyBridge, feel free to scan the second one. I will run a small lottery right now. We have Skigoro to win. If you star the SkyBridge repo in the next minute or so, I will draw a name at random and you will win a Skigoro mask. Thank you very much for your attention.

14:01

SPEAKER_00

Thank you. And the thing that you will have to make sure to do is every time you build an application declare all domains your application depends upon inside the provided metadata in the mcpspec. So that you are sure that they will be rewritten correctly inside the nested iframe. For example, if you are from your app connecting to an external API to fetch data, you need to reference this domain inside the connect src directive of the metadata. Same thing for the script of image, frame and base UI, not so much used. But the two first ones are very important. And it reminded me of a very old problem that I had when I started my developer days back in 2016 I think it was.

14:57

SPEAKER_00

As a new developer in the space I was experiencing trouble getting cross-origin resource security right calls. I had trouble getting it right. CSP reminded me of those ugly days of not getting right for the first time with calls. So there has been effort in the ecosystem to make builders' life better. Especially for example on OpenAI side where they activated, they added an option in developer mode. So if you are a developer and developing app, they have a specific mode which is developer mode which allows you to have access to additional features. Up to today, when you were in developer mode, all CSP were removed.

15:40

SPEAKER_00

So you were discovering when you were going into production if some of your servers could not be reached because of missing domains inside your CSP. Which was not ideal. They are not the only ones doing a bunch of work to make builders' life much easier. At Alpic we build an open source framework called SkyBridge. SkyBridge is a super set of features on top of the official app SDK Ido and Lead were mentioning. It brings a few things to the table. End-to-end type safety between your MCP server and your app, widget and views. You have a lot of APIs that provide polyfill for features that are not part of the command specification and specific to some of the hosts,

16:19

SPEAKER_00

some of Cloud and some of the chat GPT APIs. And we provide a bunch of modern development features, especially in the on-dev environment features. And I wanted to show you one just specifically made for CSP, which we call the CSP Inspector. Time for a small demo. I do have a few minutes left. Perfect. Let me quickly switch to my screen.

16:54

SPEAKER_00

Okay. So this is an example code base that will be generated when you create a new SkyBridge application. This example SkyBridge application comes with a small application. It's an eight ball that you can ask any question to that will respond to one of the 25 predefined answers. It has an MCP tool that serves as generating the answer and a view that's just there to display the question and the answer to the questions that you ask. When I start the server of SkyBridge, I have access in my browser to a dev tool, which is basically a small app that will give me inspection tooling to work with my app before I bring it to the GPT.

17:41

SPEAKER_00

For example, on the left, I have a list of tools that are exposed by my app. I can, if I want, execute any of the tools. So for example, here I'm executing the magic eight ball tool. And if there are views associated with this tool, that will be rendered inside the inspector for me to have a closer look at it and make changes and see those changes reflected live in the UI. The neat thing I wanted to demonstrate is the CSP part of the inspector that we built, which basically looks at all the domains that you listed inside your metadata.

18:14

SPEAKER_00

And all the domains that are actually accessed by calls made by your view and compile them to make sure that none of them are not listed yet. So for example, here, everything looks green. But if I go back to my actual code base and, for example, fetch some API to get info about my IP location, this will be affected straight away in the inspector because the component has been re-rendered. And I know I have the exact domain that I just called listed as missing from the metadata. And I can go back inside my application and add the missing domain. And now it should appear green if I reload it. Yeah, everything good. So, neat little tool.

19:01

SPEAKER_00

There are a lot of other features that are packed inside SkyBridge. But that's one of them that we made sure to be available to builders because we've seen a lot of rejection coming from the GPT App Store submission because of missing CSP. And apps not working in production because of missing CSP domains.

19:18

SPEAKER_00

Just to finish up quickly, if I can. Up. Up. This one, yeah. Yeah, that's all. Thank you again for your time. If you want to grab the slides and take a look later on, feel free to scan the first QR code. If you want to give a try to SkyBridge, feel free to scan the second one. I will run right now a small lottery. We have Skigoro to win. If you start SkyBridge repo in the next minute or so, I will draw a name at random and you will win Skigoro mask. Thank you very much for your attention.

20:09

SPEAKER_00

Thank you.

Reading tools

Type to find a passage

Appearance
Ask this transcript

Add a note