应用
模式与限制
UI 模式、iframe 中不受支持的 Nuxt 功能,以及 API 参考。
模式
callTool 期间的骨架屏
pending 仅在进行中的 callTool 调用期间会切换为 true —— 非常适合在不丢失先前数据的情况下进行局部 UI 更新:
<button :disabled="pending" @click="callTool('color-picker', { base: nextBase })">
{{ pending ? '正在混合…' : '试试这个颜色' }}
</button>
适配全屏与内联
宿主可以将你的应用以内联方式挂载(较小),或将其展开为全屏。切换布局原语:
<section :class="['rail', isFullscreen && 'rail-grid']">
<!-- 内联时水平滚动,全屏时使用 CSS grid -->
</section>
应用到应用的工作流
在应用 A 中使用 sendPrompt,并让 LLM 将请求分发到应用 B。用户会感知到平滑的过渡;LLM 仍然在流程中,并且可以携带参数继续传递:
<button @click="sendPrompt(`Generate a typography scale for ${swatch.hex}.`)">
与字体搭配
</button>
LLM 会从提示中选择正确的工具——保持名称可预测。
CSS 共置
使用 scoped styles 或任何会输出内联样式的 CSS-in-JS 方案。打包器会将所有样式内联到 HTML 中;不会从 iframe 发起外部 CSS 请求。
你目前无法做的事
MCP 应用运行在一个隔离的 iframe 中,无法访问你的 Nuxt 运行时上下文。这意味着:
- ❌ Nuxt UI / Nuxt Image / NuxtLink —— 它们需要父 Nuxt 应用的运行时。
- ❌ 自动导入的 Nuxt composables(
useFetch、useState、useRoute、useNuxtApp、…)。 - ❌ Pinia store 或应用级插件 —— 模块图不同。
- ❌ 来自父页面的 cookies、headers、session —— 沙盒化的 origin。
你可以使用的有:
- ✅ Vue 3 + Composition API(自动导入:
ref、computed、watch、onMounted、…)。 - ✅
useMcpApp()—— iframe 中唯一的工具包 composable。 - ✅
handler内部的$fetch(服务端)—— 调用任何 Nuxt API。 - ✅ 与 SFC 相邻的共置
.ts/.css辅助文件(打包器会将它们内联)。 - ✅ 无头 UI 库(Reka UI、Headless UI Vue、Floating UI)—— 它们与框架无关。
需要丰富组件?可以在你的 apps 目录中构建一个小型共置设计系统,例如
app/mcp/_components/ —— 任何导入它的应用都会将其打包进去。或者引入一个不依赖宿主运行时的无头库。参考
| API | 位置 | 作用 |
|---|---|---|
defineMcpApp() | <script setup> | 声明工具、schema、handler、CSP。从浏览器 bundle 中移除。 |
useMcpApp<T>() | SFC body | 响应式 data / loading / hostContext + callTool、sendPrompt、openLink。 |
csp.resourceDomains | defineMcpApp | 图像 / 字体 / 样式来源白名单。 |
csp.connectDomains | defineMcpApp | fetch / XHR / WebSocket 来源白名单。 |
_meta | defineMcpApp | 除 ui.resourceUri 和 ui.csp 之外,随 _meta 一同向宿主暴露的额外字段。 |