应用
useMcpApp() 桥接
来自 iframe 内部的 data、hostContext、sendPrompt、callTool 和 openLink。
useMcpApp()
唯一的客户端组合式函数,会自动导入到每个 MCP App SFC 中。它返回 iframe 与主机通信所需的一切:
const {
data, // Ref<T | null> — 从 structuredContent 水合而来,由 callTool 刷新
loading, // Ref<boolean> — 在首个有效载荷到达前始终为 true
error, // Ref<Error | null> — 桥接 / 传输 / 有效载荷错误
pending, // Ref<boolean> — 当 callTool() 正在执行时为 true
hostContext, // Ref<HostContext | null> — 主题、显示模式、区域设置,…
callTool, // (name, params?) => Promise<T | null> — 重新调用任意 MCP 工具
sendPrompt, // (prompt: string) => void — 向聊天中发送一条消息
openLink, // (url: string) => void — 请求主机打开一个 URL
} = useMcpApp<MyPayload>()
将你的有效载荷类型作为泛型传入,以便下游获得完整推断。
data 和 loading
当处理程序返回 structuredContent 时,data 在首次渲染时就已经填充。loading 初始为 true,在首个有效载荷到达后变为 false。对于进行中的 callTool() 刷新,请使用 pending:
<template>
<section v-if="loading" class="skeleton" />
<section v-else-if="data" class="content">
{{ data.swatches.length }} 个色板,来自 {{ data.base }}
</section>
</template>
hostContext
在 ui/initialize 握手期间,主机会向 iframe 传递一个上下文对象。用它来适配深色模式、全屏或固定的 iframe 尺寸:
interface HostContext {
theme?: 'light' | 'dark'
displayMode?: 'inline' | 'fullscreen' | 'pip'
containerDimensions?: { width?: number, height?: number, maxWidth?: number, maxHeight?: number }
locale?: string
timeZone?: string
platform?: 'web' | 'desktop' | 'mobile'
}
<script setup lang="ts">
const { hostContext } = useMcpApp()
const isDark = computed(() => hostContext.value?.theme === 'dark')
const isFullscreen = computed(() => hostContext.value?.displayMode === 'fullscreen')
</script>
<template>
<main :data-theme="isDark ? 'dark' : 'light'" :data-mode="isFullscreen ? 'fullscreen' : 'inline'">
…
</main>
</template>
hostContext 在第一次绘制时为 null,会在握手后填充(通常 <50 ms)。请始终在模板中使用回退值。sendPrompt(prompt) — 后续跟进
将消息发送到聊天中,就像用户亲自输入了一样。然后 LLM 会像处理任何其他请求一样路由它——包括调用另一个 MCP App:
<button @click="sendPrompt(`Use ${swatch.name} (${swatch.hex}) as the brand colour.`)">
使用此颜色
</button>
主机会像用户输入了一样接收该提示。LLM 可能会回复、调用另一个工具,或者响应时打开另一个 MCP App——应用到应用的工作流 就由这个原语自然实现。
后续跟进是尽力而为。实现了
ui/message 的主机可以顺畅转发提示。ChatGPT 会确认请求,但并不总是将下一个工具以内联方式重新渲染(这是上游限制)。callTool(name, params) — 原地刷新
从 iframe 中重新调用任意 MCP 工具。结果会自动替换 data:
<script setup lang="ts">
const { data, pending, callTool } = useMcpApp<PalettePayload>()
async function refresh(base: string) {
await callTool('color-picker', { base })
}
</script>
可将其用于筛选、分页、刷新按钮——任何无需完整聊天往返即可更改查询的操作。
openLink(url)
沙盒 iframe 不能打开窗口。openLink 会请求主机替你完成此操作(例如在新的浏览器标签页中打开预订确认页面):
<button @click="openLink(`https://example.com/colors/${swatch.hex.slice(1)}`)">
在网页中查看
</button>
如果你还需要从 iframe 中
fetch() 该目标,请将目标主机添加到 csp.connectDomains。