Skip to content

MCP Apps 与 MCP-UI 协议深度解析

1. 引言

随着大型语言模型(LLM)在各个领域的广泛应用,如何让 AI 模型与外部工具和服务进行高效交互成为了一个关键问题。Anthropic 于 2024 年 11 月推出的 Model Context Protocol(MCP)为解决这一问题提供了标准化方案[1]。然而,传统的 MCP 工具只能返回文本或结构化数据,无法满足用户对丰富交互体验的需求。

MCP Apps 和 MCP-UI 协议应运而生,它们通过在 MCP 基础上扩展 UI 能力,使得工具能够返回交互式的 HTML 界面,从而在对话中直接渲染数据可视化、表单、仪表板等丰富的用户界面。本文将深入解析这两个协议的核心概念、技术细节和实际应用。

2. MCP 协议基础回顾

在深入探讨 MCP Apps 和 MCP-UI 之前,我们先简要回顾 MCP 的核心架构。

MCP 基于 JSON-RPC 2.0 协议,定义了三种主要角色[2]

  1. Host(宿主):发起连接的 LLM 应用程序,如 Claude Desktop、VS Code 等
  2. Client(客户端):宿主应用中的连接器,负责与服务器通信
  3. Server(服务器):提供上下文和能力的服务

MCP 服务器可以向客户端提供以下功能:

  • Resources(资源):上下文和数据,供用户或 AI 模型使用
  • Prompts(提示):模板化的消息和工作流
  • Tools(工具):供 AI 模型执行的函数

3. MCP Apps 协议详解

3.1 什么是 MCP Apps

MCP Apps 是 MCP 的第一个官方扩展,于 2026 年 1 月正式发布[3]。它允许 MCP 工具返回交互式的 HTML 界面,这些界面直接在对话中渲染,用户可以直接与之交互,而无需离开当前对话上下文。

3.2 核心工作原理

MCP Apps 的架构依赖于两个关键的 MCP 原语:

  1. 带有 UI 元数据的工具:工具在定义中包含 _meta.ui.resourceUri 字段,指向 UI 资源
  2. UI 资源:通过 ui:// 协议提供的服务器端资源,包含打包的 HTML/JavaScript

MCP Apps 的工作流程可以用以下时序图表示:

javascript
// 工具定义示例
{
  name: "visualize_data",
  description: "将数据可视化为交互式图表",
  inputSchema: { /* ... */ },
  _meta: {
    ui: {
      resourceUri: "ui://charts/interactive"
    }
  }
}

3.3 通信协议

MCP Apps 使用基于 postMessage 的 JSON-RPC 协议进行宿主与 UI 之间的通信[4]

宿主到 UI 的通信(通知)

通知类型描述
ui/notifications/tool-input完整的工具参数
ui/notifications/tool-input-partial流式传输的部分参数
ui/notifications/tool-result工具执行结果
ui/notifications/host-context-changed主题、语言环境、视口变化
ui/notifications/size-changed宿主通知尺寸约束
ui/notifications/tool-cancelled工具执行被取消

UI 到宿主的通信(请求)

方法描述
tools/call调用另一个 MCP 工具
ui/message发送后续消息到对话
ui/open-link在新标签页中打开 URL
notifications/message向宿主记录日志消息
ui/notifications/size-changed请求小部件调整大小

3.4 App API

开发者可以使用 @modelcontextprotocol/ext-apps 包来构建 MCP Apps,该包提供了 App 类用于 UI 到宿主的通信:

javascript
import { App } from "@modelcontextprotocol/ext-apps";

const app = new App();
await app.connect();

// 接收来自宿主的工具结果
app.ontoolresult = (result) => {
  renderChart(result.data);
};

// 从 UI 调用服务器工具
const response = await app.callServerTool({
  name: "fetch_details",
  arguments: { id: "123" },
});

// 更新模型上下文
await app.updateModelContext({
  content: [{ type: "text", text: "用户选择了选项 B" }],
});

3.5 安全模型

MCP Apps 通过多层安全机制确保 UI 代码的安全执行[5]

  1. Iframe 沙箱化:所有 UI 内容在受限的 iframe 中运行
  2. 预声明模板:宿主可以在渲染前审查 HTML 内容
  3. 可审计消息:所有 UI 到宿主的通信都通过可记录的 JSON-RPC
  4. 用户同意:宿主可以要求对 UI 发起的工具调用进行明确批准

4. MCP-UI 协议详解

4.1 MCP-UI 的历史与现状

MCP-UI 是由 Ido Salomon 和 Liad Yosef 创建的开源项目,它率先探索了通过 MCP 提供交互式 UI 的概念[6]。MCP-UI 的工作直接影响了 MCP Apps 规范的制定。

目前,MCP-UI 已经被标准化到 MCP Apps 中,其 SDK 实现了 MCP Apps 规范,同时作为社区增强功能的试验场[7]

4.2 SDK 包

MCP-UI 提供了多个语言的 SDK 实现:

  • @mcp-ui/server(TypeScript):创建 UI 资源对象
  • @mcp-ui/client(TypeScript):渲染工具 UI 的 React 组件
  • mcp_ui_server(Ruby):创建 UI 资源的辅助方法
  • mcp-ui-server(Python):创建 UI 资源的辅助方法

4.3 UIResource 格式

UI 内容的基础数据格式是 UIResource 对象[8]

typescript
interface UIResource {
  type: 'resource';
  resource: {
    uri: string;       // ui://component/id
    mimeType: 'text/html;profile=mcp-app';  // MCP Apps 标准
    text?: string;      // 内联 HTML 内容
    blob?: string;      // Base64 编码的内容
  };
}

关键字段说明:

  • uri:使用 ui:// 协议的唯一标识符(例如:ui://my-tool/widget-01
  • mimeTypetext/html;profile=mcp-app——MCP Apps 标准的 MIME 类型
  • textblob:实际内容,可以是纯文本或 Base64 编码

4.4 URI 方案

MCP-UI 使用特定的 URI 方案来标识 UI 资源:

  • ui://<component-name>/<instance-id>
    • 用途:所有 UI 资源
    • 内容textblob 包含 HTML 内容
    • 客户端动作:在沙箱化 iframe 中渲染

4.5 内容编码

MCP-UI 支持两种内容编码方式:

  1. text:简单的直接字符串,适用于较小、不太复杂的内容
  2. blob:Base64 编码的字符串
    • 优点:能稳健处理特殊字符,更适合大型负载,确保 JSON 传输过程中的完整性
    • 缺点:需要在客户端进行 Base64 解码,略微增加负载大小

4.6 外部 URL 处理

当使用 createUIResource 并设置 content.type: 'externalUrl' 时,不同 SDK 的行为有所不同:

  • TypeScript SDK:在服务器端获取 URL 的 HTML 内容,注入 <base> 标签以便相对路径正确解析,验证 URL(仅限 http/https,阻止私有/localhost 地址)
  • Python 和 Ruby SDK:直接将 URL 字符串存储为资源内容,由宿主客户端负责获取和渲染

5. MCP Apps 与 MCP-UI 的关系

MCP Apps 和 MCP-UI 之间存在密切的关系:

  1. MCP-UI 是先驱:MCP-UI 最早探索了通过 MCP 提供交互式 UI 的概念
  2. MCP Apps 是标准:MCP Apps 将 MCP-UI 的模式标准化为官方扩展
  3. MCP-UI 是实现:MCP-UI SDK 现在实现了 MCP Apps 规范
  4. MCP-UI 是试验场:MCP-UI 继续作为社区增强功能的试验场

对于已经使用 MCP-UI 的开发者,迁移到官方扩展是直接的,但也可以继续使用 MCP-UI,因为它的 SDK 支持 MCP Apps 模式。

6. 使用场景

MCP Apps 在以下场景中表现出色[9]

6.1 数据探索

销售分析工具返回交互式仪表板。用户可以按地区筛选、深入查看特定账户、导出报告,而无需离开对话。

6.2 配置向导

部署工具呈现包含依赖字段的表单。选择"生产环境"会显示额外的安全选项;选择"暂存环境"会显示不同的默认值。

6.3 文档审查

合同分析工具以内联方式显示 PDF 并高亮显示条款。用户点击批准或标记部分内容,模型实时看到他们的决定。

6.4 实时监控

服务器健康工具显示实时更新的指标。无需重新运行工具即可查看当前状态。

7. 客户端支持

MCP Apps 目前已在多个主流客户端中得到支持[10]

  • Claude:支持 Web 和桌面体验
  • Goose:Block 公司开发的 AI 助手
  • Visual Studio Code:通过 GitHub Copilot 集成
  • ChatGPT:OpenAI 的 AI 助手
  • Postman:API 开发工具
  • MCPJam:MCP 开发工具

这意味着开发者可以构建一个交互式体验,在所有广泛使用的客户端中运行,而无需编写任何客户端特定的代码。

8. 开发入门

8.1 环境设置

要开始构建 MCP Apps,可以使用官方 SDK:

bash
npm install @modelcontextprotocol/ext-apps
npm install @mcp-ui/server
npm install @mcp-ui/client

8.2 创建简单的 MCP App

以下是一个简单的示例,展示如何创建带有交互式 UI 的 MCP 工具:

typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { registerAppTool, registerAppResource } from '@modelcontextprotocol/ext-apps/server';
import { createUIResource } from '@mcp-ui/server';
import { z } from 'zod';

const server = new McpServer({ name: 'my-server', version: '1.0.0' });

// 创建 UI 资源
const widgetUI = createUIResource({
  uri: 'ui://my-server/widget',
  content: { 
    type: 'rawHtml', 
    htmlString: `
      <h1>交互式小部件</h1>
      <button onclick="handleClick()">点击我</button>
      <script>
        function handleClick() {
          window.parent.postMessage({
            type: 'tool',
            payload: { toolName: 'process_click', params: {} }
          }, '*');
        }
      </script>
    `
  },
  encoding: 'text',
});

// 注册资源处理器
registerAppResource(server, 'widget_ui', widgetUI.resource.uri, {}, async () => ({
  contents: [widgetUI.resource]
}));

// 注册带有 _meta.ui.resourceUri 的工具
registerAppTool(server, 'show_widget', {
  description: '显示交互式小部件',
  inputSchema: { query: z.string() },
  _meta: { ui: { resourceUri: widgetUI.resource.uri } }
}, async ({ query }) => {
  return { content: [{ type: 'text', text: `查询: ${query}` }] };
});

8.3 客户端渲染

在客户端使用 AppRenderer 组件渲染工具 UI:

tsx
import { AppRenderer } from '@mcp-ui/client';

function ToolUI({ client, toolName, toolInput, toolResult }) {
  return (
    <AppRenderer
      client={client}
      toolName={toolName}
      sandbox={{ url: sandboxUrl }}
      toolInput={toolInput}
      toolResult={toolResult}
      onOpenLink={async ({ url }) => {
        // 验证 URL 方案后再打开
        if (url.startsWith('https://') || url.startsWith('http://')) {
          window.open(url);
        }
      }}
      onMessage={async (params) => console.log('消息:', params)}
    />
  );
}

9. 总结与展望

MCP Apps 和 MCP-UI 协议为 AI 工具提供了强大的 UI 能力,使得 AI 助手不再局限于文本交互,而是能够提供丰富的可视化、表单、仪表板等交互式界面。这不仅提升了用户体验,也为 AI 应用的开发开辟了新的可能性。

随着更多客户端支持 MCP Apps,以及社区不断贡献新的组件和模式,我们可以预见 AI 交互将变得更加直观、高效和人性化。开发者现在就可以开始构建 MCP Apps,为用户提供前所未有的 AI 交互体验。

参考文献


  1. Anthropic. "Introducing the Model Context Protocol." (2024-11-25). https://www.anthropic.com/news/model-context-protocol ↩︎

  2. Model Context Protocol. "Specification." (2025-06-18). https://modelcontextprotocol.io/specification/2025-06-18 ↩︎

  3. MCP Core Maintainers. "MCP Apps - Bringing UI Capabilities To MCP Clients." (2026-01-26). https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/ ↩︎

  4. MCP-UI. "Protocol Details." (2025). https://mcpui.dev/guide/protocol-details ↩︎

  5. Model Context Protocol. "MCP Apps." (2026). https://modelcontextprotocol.io/extensions/apps/overview ↩︎

  6. MCP-UI. "Introduction." (2025). https://mcpui.dev/guide/introduction ↩︎

  7. MCP-UI. "MCP-UI is now standardized into MCP Apps!" (2026). https://mcpui.dev ↩︎

  8. MCP-UI. "Protocol Details - UIResource Wire Format." (2025). https://mcpui.dev/guide/protocol-details ↩︎

  9. MCP Core Maintainers. "MCP Apps - Bringing UI Capabilities To MCP Clients." (2026-01-26). https://blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/ ↩︎

  10. Model Context Protocol. "MCP Apps - Client Support." (2026). https://modelcontextprotocol.io/extensions/apps/overview ↩︎