应用
CSP 与构建流水线
内容安全策略、允许列表域名,以及 HTML bundle 的生成方式。
CSP 与资源允许列表
该工具包会向每个应用的 HTML 注入一个 保守的内容安全策略。默认情况下,iframe 可以:
- 只运行其自身的内联脚本。
- 仅从同一响应中渲染图片和样式。
- 通过
postMessage与其父宿主通信。
如果你的 UI 需要外部资源或 API,请显式允许它们:
app/mcp/color-picker.vue
<script setup lang="ts">
defineMcpApp({
description: '选择一种颜色并预览调色板。',
csp: {
resourceDomains: ['https://images.unsplash.com'],
connectDomains: ['https://api.example.com'],
},
handler: async ({ base }) => ({ structuredContent: await $fetch('/api/palette', { query: { base } }) }),
})
</script>
CSP 会镜像到 _meta.ui.csp(以及 ChatGPT 的 openai/widgetCSP),因此在 iframe 级别强制执行 CSP 的宿主也会采用相同规则。
仅在万不得已时才传入
csp: false —— 并且仅当你完全控制 iframe 加载的资源时才这样做。默认策略正是让应用能够在不同宿主之间安全渲染的关键。| 字段 | 它允许什么 |
|---|---|
resourceDomains | 来自这些源的 <img>、<style>、<link>、字体 |
connectDomains | 到这些源的 fetch()、XHR、WebSocket、EventSource |
来源应使用 http(s):// 或 ws(s)://。在应用响应被提供之前,该工具包会拒绝空值、不受支持的 URL 协议、空白、引号和分号。
它是如何连接的
在幕后,配置好的 apps 目录下的每个 .vue 文件在构建时都会变成 三种产物:
- 在你的 MCP 处理器上注册的一个 工具定义(输入 schema、描述、服务器处理函数)。
- 一个位于
ui://mcp-app/<name>的 UI 资源,返回text/html;profile=mcp-app。 - 一个将 Vue SFC(Vue runtime、你的代码、作用域 CSS、资源)内联进资源响应中的 单文件 HTML bundle。
当 LLM 调用该工具时:
- 你的
handler在服务器上运行并生成structuredContent。 - 工具包将这些数据注入到打包后的 HTML 中,形式为
<script type="application/json" id="__mcp_app_data__">…</script>。 - 宿主将该资源返回给用户;其 iframe 启动,并且
useMcpApp()会同步将内联数据读取到data中。 - 从那里开始,iframe 和宿主通过 JSON-RPC 桥交换
callTool、sendPrompt、openLink以及主题/尺寸更新等消息。
一切都在 一个 HTML 响应 中交付。iframe 不需要额外的 HTTP 请求,没有瀑布流,没有闪烁。