为什么不直接构建一个 Web 应用?
你当然可以构建一个独立的 Web 应用,然后给用户发一个链接。然而,MCP Apps 提供了独立页面无法比拟的以下关键优势:- 上下文保留。 应用存在于对话之中。用户无需切换标签页、迷失位置,或苦苦回想是哪个聊天线程里有那个仪表盘。UI 就在那里,与引出它的讨论并列在一起。
- 双向数据流。 你的应用可以调用 MCP 服务器上的任何工具,宿主也可以将最新结果推送给你的应用。独立的 Web 应用则需要自己的 API、认证和状态管理。MCP Apps 通过既有的 MCP 模式获得这一切。
- 与宿主能力的集成。 应用可以将操作委托给宿主,宿主随后可以调用用户已经连接的能力和工具(须经用户同意)。这样一来,不必每个应用都自行实现并维护直接集成(例如邮件提供方),应用只需请求一个结果(比如”安排这次会议”),由宿主通过用户既有的已连接能力来路由处理。
- 安全保证。 MCP Apps 运行在由宿主控制的沙箱化 iframe 中。它们无法访问父页面、窃取 cookie 或逃逸出其容器。这意味着宿主可以安全地渲染第三方应用,而无需完全信任服务器作者。
MCP Apps 的工作原理
传统的 MCP 工具返回文本、图像、资源或结构化数据,由宿主作为对话的一部分展示。MCP Apps 扩展了这一模式,允许工具在其工具描述中声明一个对交互式 UI 的引用,由宿主就地渲染。 其核心模式结合了两个 MCP 原语:一个在其描述中声明 UI 资源的工具,加上一个将数据渲染为交互式 HTML 界面的 UI 资源。 当大语言模型(LLM)决定调用一个支持 MCP Apps 的工具时,会发生以下过程:-
UI 预加载:工具描述包含一个
_meta.ui.resourceUri字段,指向一个ui://资源。宿主甚至可以在工具被调用之前预加载该资源,从而实现诸如向应用流式传输工具输入之类的特性。 -
资源获取:宿主从服务器获取该 UI 资源。该资源包含一个 HTML 页面,为简单起见通常将其 JavaScript 和 CSS 打包在一起。应用还可以从
_meta.ui.csp中指定的源加载外部脚本和资源。 -
沙箱化渲染:Web 宿主通常将 HTML 渲染在对话内的一个沙箱化 iframe 中。沙箱限制了应用对父页面的访问,从而确保安全。资源的
_meta.ui对象可以包含permissions以请求额外能力(例如麦克风、摄像头),以及csp以控制应用可以从哪些外部源加载资源。 -
双向通信:应用与宿主通过一个 JSON-RPC 协议通信,该协议构成了 MCP 的一种方言。有些请求和通知与核心 MCP 协议共享(例如
tools/call),有些相似(例如ui/initialize),而大多数是带有ui/方法名前缀的新方法。应用可以请求工具调用、发送消息、更新模型的上下文,并从宿主接收数据。
何时使用 MCP Apps
当你的用例涉及以下情形时,MCP Apps 是很合适的选择: 探索复杂数据。 用户问”按地区展示销售情况”。文本响应或许能列出一堆数字,但 MCP App 可以渲染一张交互式地图,用户点击各地区即可下钻、悬停查看详情、在不同指标间切换,而这一切都无需额外的提示。 在众多选项中进行配置。 设置一次部署涉及数十个相互依赖的选择。与其一来一回地对话(“哪个地区?""什么实例规格?""启用自动扩缩容吗?”),MCP App 呈现一个表单,用户可以一次性看到所有选项,并带有校验和默认值。 查看富媒体。 当用户要求评审 PDF、查看 3D 模型或预览生成的图像时,文字描述力有不逮。MCP App 将实际的查看器(平移、缩放、旋转)直接嵌入对话之中。 实时监控。 展示实时指标、日志或系统状态的仪表盘需要持续更新。MCP App 维持一个持久连接,随着数据变化更新显示,而无需用户追问”现在状态如何?” 多步骤工作流。 审批费用报销单、评审代码变更或分诊问题都涉及逐项检查。MCP App 提供导航控件、操作按钮,以及在多次交互之间保持的状态。安全模型
MCP Apps 运行在一个沙箱化的 iframe 中,与宿主应用之间提供了强隔离。沙箱阻止你的应用访问父窗口的 DOM、读取宿主的 cookie 或本地存储、导航父页面,或在父上下文中执行脚本。 你的应用与宿主之间的所有通信都经过 postMessage API。宿主控制你的应用可以访问哪些能力。例如,宿主可能限制应用能调用哪些工具,或禁用sendOpenLink 能力。
沙箱旨在防止应用逃逸出去访问宿主或用户数据。
框架支持
MCP Apps 使用它们自己的 MCP 方言,与核心协议一样构建于 JSON-RPC 之上。有些消息与常规 MCP 共享(例如tools/call),另一些则专属于应用(例如 ui/initialize)。传输方式是 postMessage,而非 stdio 或 HTTP。由于全部基于标准 Web 原语,你可以使用任何框架,也可以完全不用框架。
@modelcontextprotocol/ext-apps 中的 App 类是一个便利封装,而非强制要求。如果你倾向于避免依赖,或需要更紧密的控制,可以直接实现 postMessage 协议。
示例目录包含针对 React、Vue、Svelte、Preact、Solid 和纯 JavaScript 的初始模板。它们演示了每种框架体系的推荐模式,但只是示例而非要求。你可以选择最适合你用例的方式。
客户端支持
MCP Apps 是核心 MCP 规范的一个扩展。宿主支持情况因客户端而异。
-
使用框架:
@mcp-ui/client软件包提供了 React 组件,用于在你的宿主应用中渲染 MCP Apps 视图并与之交互。用法细节参见 MCP-UI 文档。 - 基于 AppBridge 构建:SDK 包含一个 App Bridge 模块,负责在沙箱化 iframe 中渲染应用、消息传递、工具调用代理和安全策略强制执行。basic-host 示例展示了如何集成它。
示例
ext-apps 仓库包含可直接运行的示例,演示不同的用例:- 3D 与可视化: map-server (CesiumJS 地球仪)、 threejs-server (Three.js 场景)、 shadertoy-server (着色器效果)
- 数据探索: cohort-heatmap-server、 customer-segmentation-server、 wiki-explorer-server
- 业务应用: scenario-modeler-server、 budget-allocator-server
- 媒体: pdf-server、 video-resource-server、 sheet-music-server、 say-server (文本转语音)
- 实用工具: qr-server、 system-monitor-server、 transcript-server (语音转文本)
- 初始模板: React、 Vue、 Svelte、 Preact、 Solid、 纯 JavaScript