diff --git a/docs/mcp-app-training.md b/docs/mcp-app-training.md new file mode 100644 index 0000000..a940629 --- /dev/null +++ b/docs/mcp-app-training.md @@ -0,0 +1,1063 @@ +# MCP App 协议培训文档 + +> 面向团队的技术培训材料,帮助理解 MCP App 协议的核心机制、实现方式与应用场景。 + +--- + +## 目录 + +1. [为什么需要 MCP App](#1-为什么需要-mcp-app) +2. [MCP Apps vs A2UI 对比](#2-mcp-apps-vs-a2ui-对比) +3. [核心概念:三层分离架构](#3-核心概念三层分离架构) +4. [协议通信机制详解](#4-协议通信机制详解) +5. [代码实现走读](#5-代码实现走读) +6. [现有实现案例分析](#6-现有实现案例分析) +7. [如何开发一个新的 MCP App Skill](#7-如何开发一个新的-mcp-app-skill) +8. [实际应用场景](#8-实际应用场景) +9. [FAQ](#9-faq) + +--- + +## 1. 为什么需要 MCP App + +### 传统 Agent 的局限 + +传统的 AI Agent 只能输出文本(Markdown、代码块等),无法直接在对话中呈现**可交互的 UI**。用户看到的永远是静态文字。 + +### MCP App 解决的问题 + +MCP App 协议让 Agent 的工具调用(tool call)能够返回**富交互组件**——图表、表单、按钮、嵌入页面等——直接渲染在聊天窗口中,用户可以点击、选择、输入,结果再传回 Agent 继续对话。 + +``` +用户提问 → Agent 思考 → 调用 MCP Tool → 返回 UI 组件 → 用户交互 → 结果回传 Agent +``` + +**核心价值:让 Agent 从"只会说话"变成"能展示、能交互"。** + +--- + +## 2. MCP Apps vs A2UI 对比 + +> 参考:[hia2ui.com - MCP Apps vs A2UI](https://hia2ui.com/zh-cn/blog/mcp-apps-vs-a2ui/) + +在 Agent UI 领域,目前存在两种主流协议方案。了解它们的差异有助于我们做出更好的技术选型。 + +### 2.1 两种哲学 + +| | MCP Apps (Anthropic) | A2UI (Google) | +|---|---|---| +| **核心理念** | **UI 即资源** — 将 UI 视为不透明的、外部获取的黑盒资源 | **UI 即协议** — 通过只具有声明语义的强类型 JSON 蓝图传输 | +| **传输内容** | 完整的 HTML/CSS/JavaScript 代码包 | 纯 JSON 声明式数据,**绝对不包含可执行代码** | +| **URI 格式** | `ui://server-name/resource` | N/A(通过 JSON schema 定义组件类型) | +| **宿主角色** | 被动容器 — 将 HTML 丢进 iframe 渲染 | 主动绘制者 — 用本地原生组件树渲染 JSON 蓝图 | + +用一句话概括差异: +- **MCP Apps**:服务端说"这是我画好的 UI 界面,你直接嵌进去展示" +- **A2UI**:服务端说"这是我要展示的数据结构,你用你自己的 UI 组件来画" + +### 2.2 四大维度详细对比 + +#### 维度一:核心架构 + +``` +MCP Apps(Iframe 沙盒模式): +┌──────────────────────┐ +│ Host(聊天界面) │ +│ ┌──────────────────┐ │ +│ │ Iframe (sandbox) │ │ ← 将服务端返回的 HTML 代码 +│ │ ┌──────────────┐ │ │ "盲目地"丢进 iframe 沙盒 +│ │ │ 完整 HTML/JS │ │ │ +│ │ └──────────────┘ │ │ +│ └──────────────────┘ │ +└──────────────────────┘ + +A2UI(原生声明式蓝图): +┌──────────────────────┐ +│ Host(聊天界面) │ +│ │ +│ ┌─────┐ ┌─────┐ │ ← Host 拿到 JSON 蓝图后 +│ │Button│ │Card │ │ 用自己本地的原生组件渲染 +│ └─────┘ └─────┘ │ +│ ┌─────┐ ┌─────┐ │ +│ │Chart│ │List │ │ +│ └─────┘ └─────┘ │ +└──────────────────────┘ +``` + +#### 维度二:跨平台可移植性 + +| 平台 | MCP Apps | A2UI | +|------|---------|------| +| Web 浏览器 | 原生支持,表现优秀 | 映射为 React/Web 组件 | +| iOS | 需启动 WebView 内核,体验较重 | 映射为原生 UIButton 等 iOS 组件 | +| Android | 需启动 WebView 内核,体验较重 | 映射为 Material Design 组件 | +| 桌面端 | Electron 等框架可支持 | 映射为对应平台原生组件 | + +**结论**:A2UI 在跨平台一致性上优势明显。同一份 JSON 负载可以在各平台渲染为原生体验,而 MCP Apps 在非 Web 平台需要依赖 WebView,体验较重。 + +#### 维度三:样式控制权与设计一致性 + +| 维度 | MCP Apps | A2UI | +|------|---------|------| +| 样式由谁决定 | **服务端**决定(HTML/CSS 自带样式) | **宿主应用**决定(本地组件库样式) | +| 品牌一致性 | 较难保证,第三方 HTML 样式难以覆盖 | 自动继承宿主的 Design Tokens | +| 深色模式 | 需要 HTML App 自行适配 | 自动继承宿主的主题设置 | +| 定制能力 | 需要 CSS overrides 强行覆盖 | 天然支持,AI 只决定"展示什么",不决定"长什么样" | + +**结论**:A2UI 在设计一致性上完胜。MCP Apps 的 HTML 自带样式可能与宿主应用的设计规范冲突。 + +#### 维度四:安全性与信任边界 + +| 维度 | MCP Apps | A2UI | +|------|---------|------| +| 可执行代码 | 包含(HTML 中可嵌入 JS) | **绝对禁止**(纯 JSON 数据) | +| 隔离方式 | 浏览器 Iframe 沙盒 | 在协议层面从根本上阻断代码注入 | +| 攻击面 | Iframe 沙盒逃逸是已知攻击面 | 无可执行代码 = 无 UI 注入攻击面 | +| LLM 生成风险 | HTML 可能由 LLM 实时生成,存在幻觉风险 | 仅传输声明式数据,组件由预审批目录提供 | + +**结论**:A2UI 从架构层面更安全(无可执行代码传输)。MCP Apps 依赖 Iframe 沙盒隔离,安全性取决于浏览器实现。 + +### 2.3 各自适用场景 + +#### 选择 MCP Apps 的场景 + +适合需要展示**完整独立应用**或**重度定制 UI** 的场景: + +- 包含复杂交互逻辑的独立工具(如 3D WebGL 可视化、代码编辑器) +- 需要嵌入的遗留系统界面(老旧的内部报表系统等) +- 有特殊渲染需求的第三方工具(终端模拟器、地图引擎等) +- 全屏弹窗类的沉浸式体验 + +> 特点:Agent 将它们作为**独立的全屏应用**召唤出来,自成一体。 + +#### 选择 A2UI 的场景 + +适合需要在聊天流中**深度内联嵌入**富交互微件的场景: + +- 聊天流中的原生交互卡片(商品卡片、审批卡片等) +- 数据驱动的动态仪表盘 +- 需要完美匹配宿主品牌设计规范的组件 +- 需要跨 Web + Mobile 统一体验的场景 + +> 特点:AI 生成的卡片与前端手写组件**无法分辨真假**。 + +### 2.4 对比总结 + +``` + MCP Apps A2UI + ┌─────────────────┐ ┌─────────────────┐ + 灵活度 │ ★★★★★ 极高 │ │ ★★★☆☆ 受组件库约束│ + 跨平台 │ ★★★☆☆ Web 为主 │ │ ★★★★★ 全平台原生 │ + 设计一致性 │ ★★☆☆☆ 需手动适配│ │ ★★★★★ 自动继承 │ + 安全性 │ ★★★☆☆ 依赖沙盒 │ │ ★★★★★ 架构级安全 │ + 开发门槛 │ ★★★★☆ 写 HTML 即可│ │ ★★★☆☆ 需组件库支持│ + 复杂 UI 能力 │ ★★★★★ 无限制 │ │ ★★★☆☆ 受限于组件集│ + └─────────────────┘ └─────────────────┘ +``` + +### 2.5 我们的选择与思考 + +**我们当前采用 MCP Apps 协议**,原因: + +1. **灵活度优先**:我们的场景需要渲染各种复杂 UI(ECharts 图表、自定义表单、任意 HTML),MCP Apps 的"传 HTML"模式给了我们最大的自由度 +2. **Web 优先**:我们的宿主环境是 Web 聊天界面,MCP Apps 的 iframe 方案天然契合 +3. **开发效率**:写一个 HTML 模板 + 一个 MCP Server 就能实现一个新组件,门槛低 +4. **生态兼容**:MCP 协议本身已有广泛的社区和工具链支持 + +**未来可能的演进**: + +- 对于需要深度内联到聊天流、强调品牌一致性的轻量卡片(如通知卡片、状态标签),可以考虑引入 A2UI +- 两种协议**并不互斥**,未来可能在同一应用中混合使用:重度工具用 MCP Apps,轻量卡片用 A2UI +- 关注 CopilotKit 等框架的双协议支持进展 + +--- + +## 3. 核心概念:三层分离架构 + +MCP App 协议的精髓是 **数据与 UI 分离**: + +``` +┌─────────────────────────────────────────────────┐ +│ Host (宿主) │ +│ 即聊天界面,负责 iframe 管理和消息路由 │ +│ │ +│ ┌─────────────────┐ ┌─────────────────────┐ │ +│ │ MCP Server │ │ HTML App (iframe) │ │ +│ │ (数据层) │ │ (渲染层) │ │ +│ │ │ │ │ │ +│ │ tools/call │ │ 接收 postMessage │ │ +│ │ → 返回纯数据 │ │ → 渲染成可交互 UI │ │ +│ │ │ │ │ │ +│ │ resources/read │ │ 用户操作 │ │ +│ │ → 返回静态 HTML │ │ → postMessage 回传 │ │ +│ └─────────────────┘ └─────────────────────┘ │ +└─────────────────────────────────────────────────┘ +``` + +### 三个角色 + +| 角色 | 职责 | 对应代码 | +|------|------|----------| +| **MCP Server** | 处理 `tools/call` 返回结构化数据;处理 `resources/read` 返回 HTML 模板 | `*_server.py` | +| **HTML App** | 静态 HTML 文件,监听 `postMessage` 接收数据后渲染 UI | `apps/*.html` | +| **Host** | 聊天界面,负责创建 iframe、加载 HTML App、通过 postMessage 传递数据 | 前端聊天框架 | + +### 为什么要分离? + +- **安全**:HTML App 运行在 sandboxed iframe 中,与主页面隔离 +- **复用**:同一个 HTML App 模板可以渲染不同数据 +- **解耦**:MCP Server 不需要关心渲染细节,只负责产出数据 + +--- + +## 4. 协议通信机制详解 + +### 3.1 完整通信流程 + +以 `render_chart` 工具调用为例,完整流程如下: + +``` +步骤 1: Agent 决定调用 render_chart 工具 + ↓ +步骤 2: Host 发送 tools/call 请求到 MCP Server + → {"method": "tools/call", "params": {"name": "render_chart", "arguments": {...}}} + ↓ +步骤 3: MCP Server 返回 App Response(纯数据 + 资源引用) + ← {"type": "app", "resourceUri": "ui://data-dashboard/chart", "data": {...}} + ↓ +步骤 4: Host 解析到 resourceUri,发送 resources/read 请求 + → {"method": "resources/read", "params": {"uri": "ui://data-dashboard/chart"}} + ↓ +步骤 5: MCP Server 返回静态 HTML 模板 + ← {"mimeType": "text/html;profile=mcp-app", "text": "...chart.html内容..."} + ↓ +步骤 6: Host 将 HTML 加载到 sandboxed iframe + ↓ +步骤 7: iframe 内 HTML App 发送就绪信号 + → window.parent.postMessage({type: 'mcp-app-ready'}, '*') + ↓ +步骤 8: Host 收到就绪信号后,通过 postMessage 发送数据 + → iframe.postMessage({type: 'mcp-app-data', payload: {...}}, '*') + ↓ +步骤 9: HTML App 接收数据并渲染 UI + ↓ +步骤 10: (可选)用户交互后,HTML App 通过 postMessage 回传结果 + → window.parent.postMessage({type: 'mcp-app-response', payload: {...}}, '*') +``` + +### 3.2 三种关键消息类型 + +| 消息类型 | 方向 | 用途 | +|----------|------|------| +| `mcp-app-ready` | iframe → Host | HTML App 加载完毕,请求数据 | +| `mcp-app-data` | Host → iframe | 向 HTML App 传递工具调用返回的数据 | +| `mcp-app-response` | iframe → Host | 用户交互结果回传给 Agent | + +### 3.3 App Response 数据结构 + +MCP Server 的 `tools/call` 返回的核心结构: + +```json +{ + "type": "app", + "resourceUri": "ui://data-dashboard/chart", + "data": { + "title": "Monthly Revenue", + "chart_type": "line", + "data": { + "categories": ["Jan", "Feb", "Mar"], + "series": [{"name": "Revenue", "data": [820, 932, 901]}] + } + }, + "_meta": { + "mcpui.dev/ui-preferred-frame-size": ["100%", "400px"] + } +} +``` + +关键字段: +- `type: "app"` — 告诉 Host 这是一个需要渲染的 App 类型结果 +- `resourceUri` — 指向要加载的 HTML App 模板的 URI +- `data` — 传递给 HTML App 的业务数据 +- `_meta` — 元信息,如建议的 iframe 尺寸 + +### 3.4 Resource URI 协议 + +资源 URI 使用 `ui://` scheme: + +``` +ui://data-dashboard/chart → chart.html +ui://data-dashboard/metrics → metrics.html +ui://mcp-ui/html → html.html (通用 HTML 渲染器) +ui://mcp-ui/ask-user → ask-user.html (交互式问答) +``` + +MIME Type 约定: +- `text/html;profile=mcp-app` — 标准 MCP App HTML +- `text/uri-list` — 外部 URL 嵌入 + +--- + +## 5. 代码实现走读 + +### 5.1 目录结构(以 data-dashboard 为例) + +``` +skills/common/data-dashboard/ +├── .claude-plugin/ +│ └── plugin.json # 插件注册配置 +├── hooks/ +│ ├── pre_prompt.py # PrePrompt 钩子:注入工具使用指南 +│ └── dashboard_guide.md # Agent 使用指南(注入到 system prompt) +├── apps/ +│ ├── chart.html # 单图表渲染器 +│ ├── metrics.html # KPI 指标卡渲染器 +│ └── multi-chart.html # 多图表网格渲染器 +├── dashboard_server.py # MCP Server 主体 +├── dashboard_tools.json # 工具定义(JSON Schema) +└── mcp_common.py # 共享工具函数 +``` + +### 5.2 plugin.json — 插件注册 + +```json +{ + "name": "data-dashboard", + "description": "Renders data as interactive dashboard card UI", + "hooks": { + "PrePrompt": [{"type": "command", "command": "python hooks/pre_prompt.py"}] + }, + "mcpServers": { + "data_dashboard": { + "transport": "stdio", + "command": "python", + "args": ["./dashboard_server.py", "{bot_id}"] + } + } +} +``` + +要点: +- `mcpServers` 注册 MCP Server,使用 stdio 传输 +- `hooks.PrePrompt` 在对话开始前注入工具使用指南,让 Agent 知道何时/如何调用这些工具 +- `{bot_id}` 是动态参数,运行时替换为实际的 bot ID + +### 5.3 MCP Server 核心逻辑 + +Server 需要处理 5 种 MCP 方法: + +```python +# 1. initialize — 握手,声明 capabilities +if method == "initialize": + return {"capabilities": {"tools": {}, "resources": {}}} + +# 2. tools/list — 返回可用工具列表(含 _meta.ui.resourceUri) +elif method == "tools/list": + tools = load_tools_from_json("dashboard_tools.json") + return {"tools": tools} + +# 3. resources/list — 返回可用资源列表 +elif method == "resources/list": + return {"resources": RESOURCE_DEFINITIONS} + +# 4. resources/read — 返回 HTML App 文件内容 +elif method == "resources/read": + html = _load_app_html(uri) + return {"contents": [{"uri": uri, "mimeType": "text/html;profile=mcp-app", "text": html}]} + +# 5. tools/call — 执行工具,返回 App Response +elif method == "tools/call": + result = handler(arguments) + return result +``` + +### 5.4 工具定义中的 `_meta` 字段 + +工具定义(`dashboard_tools.json`)中的 `_meta.ui.resourceUri` 是关键: + +```json +{ + "name": "render_chart", + "description": "Render a single ECharts chart", + "inputSchema": { ... }, + "_meta": { + "ui": { + "resourceUri": "ui://data-dashboard/chart" + } + } +} +``` + +这个字段告诉 Host:调用这个工具的结果需要使用 `ui://data-dashboard/chart` 对应的 HTML App 来渲染。 + +### 5.5 HTML App 模板的标准写法 + +每个 HTML App 都遵循同一个模式: + +```html + + +
+ + + + + + + +``` + +如果需要**回传用户交互结果**(如 ask-user),额外添加: + +```javascript +// 用户点击提交后 +window.parent.postMessage({ + type: 'mcp-app-response', + payload: { /* 用户选择的数据 */ } +}, '*'); +``` + +--- + +## 6. 现有实现案例分析 + +### 6.1 mcp-ui — 基础 UI 组件库 + +提供三个通用工具: + +| 工具 | 功能 | HTML App | +|------|------|----------| +| `render_html` | 渲染任意 HTML/CSS/JS | `html.html` — 通用 HTML 注入渲染器 | +| `render_url` | 嵌入外部 URL | `url.html` — iframe 嵌套器 | +| `ask_user` | 交互式问答(单选/多选) | `ask-user.html` — 选项卡界面 | + +**特点**:`render_html` 是万能的——Agent 可以生成任意 HTML 内容直接渲染,灵活度最高。 + +### 6.2 data-dashboard — 数据可视化 + +提供三个专用图表工具: + +| 工具 | 功能 | HTML App | +|------|------|----------| +| `render_metrics` | KPI 指标卡 | `metrics.html` — 网格卡片布局 | +| `render_chart` | 单图表(6种类型) | `chart.html` — ECharts 渲染器 | +| `render_multi_chart` | 多图表网格 | `multi-chart.html` — 网格 ECharts | + +**特点**:Agent 只需提供结构化数据(类型、分类、数值),HTML App 负责用 ECharts 渲染出专业图表。 + +### 6.3 static-hosting — 静态文件托管 + +与前两者不同,static-hosting 不走 MCP App 协议,而是: +- Agent 将生成的 HTML/CSS/JS 写入文件系统 +- 通过 FastAPI 静态文件服务提供公开 URL +- 适用于需要**持久化访问**的场景(生成报告、网页等) + +**与 MCP App 的区别**: +- MCP App → 嵌入在聊天窗口内,临时性 +- static-hosting → 独立 URL,持久化,可分享 + +--- + +## 7. 如何开发一个新的 MCP App Skill + +### 步骤总结 + +``` +1. 创建目录结构 + skills/common/my-skill/ + ├── .claude-plugin/plugin.json + ├── hooks/ + │ ├── pre_prompt.py + │ └── usage_guide.md + ├── apps/ + │ └── my-widget.html + ├── my_server.py + ├── my_tools.json + └── mcp_common.py (symlink 或 copy) + +2. 定义工具 (my_tools.json) + - name, description, inputSchema + - _meta.ui.resourceUri 指向你的 HTML App + +3. 编写 HTML App (apps/my-widget.html) + - 监听 mcp-app-data + - 发送 mcp-app-ready + - (可选)发送 mcp-app-response + +4. 编写 MCP Server (my_server.py) + - 实现 initialize / tools/list / resources/list / resources/read / tools/call + - tools/call 中将参数转为 App Response + +5. 编写 Agent 使用指南 (hooks/usage_guide.md) + - 告诉 Agent 什么时候用、怎么用这个工具 + +6. 注册插件 (.claude-plugin/plugin.json) + - 配置 mcpServers 和 hooks +``` + +### 快速模板 + +一个最小的 MCP App Server(Python): + +```python +import asyncio, json, os +from mcp_common import (create_error_response, create_ping_response, + create_tools_list_response, load_tools_from_json, + handle_mcp_streaming) + +RESOURCE_MIME_TYPE = "text/html;profile=mcp-app" +APPS_DIR = os.path.join(os.path.dirname(__file__), "apps") + +RESOURCE_MAP = {"ui://my-skill/widget": "widget.html"} + +def _load_app_html(uri): + filename = RESOURCE_MAP.get(uri) + if not filename: + raise ValueError(f"Unknown resource URI: {uri}") + with open(os.path.join(APPS_DIR, filename), "r") as f: + return f.read() + +def _create_app_response(resource_uri, data, width="100%", height="auto"): + return {"content": [{"type": "text", "text": json.dumps({ + "type": "app", "resourceUri": resource_uri, "data": data, + "_meta": {"mcpui.dev/ui-preferred-frame-size": [width, height]}, + }, ensure_ascii=False)}]} + +async def handle_request(request): + method = request.get("method") + params = request.get("params", {}) + rid = request.get("id") + + if method == "initialize": + return {"jsonrpc": "2.0", "id": rid, "result": { + "protocolVersion": "2024-11-05", + "capabilities": {"tools": {}, "resources": {}}, + "serverInfo": {"name": "my-skill", "version": "1.0.0"}}} + elif method == "tools/list": + return create_tools_list_response(rid, load_tools_from_json("my_tools.json")) + elif method == "resources/list": + return {"jsonrpc": "2.0", "id": rid, "result": {"resources": [ + {"uri": "ui://my-skill/widget", "name": "widget", + "mimeType": RESOURCE_MIME_TYPE}]}} + elif method == "resources/read": + html = _load_app_html(params.get("uri", "")) + return {"jsonrpc": "2.0", "id": rid, "result": {"contents": [ + {"uri": params["uri"], "mimeType": RESOURCE_MIME_TYPE, "text": html}]}} + elif method == "tools/call": + # 在这里处理你的业务逻辑 + return {"jsonrpc": "2.0", "id": rid, "result": _create_app_response( + "ui://my-skill/widget", params.get("arguments", {}))} + return create_error_response(rid, -32601, f"Unknown method: {method}") + +if __name__ == "__main__": + asyncio.run(handle_mcp_streaming(handle_request)) +``` + +--- + +## 8. 实际应用场景 + +### 8.1 已实现的场景 + +| 场景 | 使用的 Skill | 说明 | +|------|-------------|------| +| 数据可视化 | data-dashboard | 将查询结果渲染为图表(折线图、饼图、KPI 卡片等) | +| 通用 HTML 渲染 | mcp-ui / render_html | Agent 生成任意 HTML 内容直接展示 | +| 交互式问答 | mcp-ui / ask_user | 让用户通过点击选项来回答问题 | +| 外部页面嵌入 | mcp-ui / render_url | 在聊天中嵌入外部网页 | +| 报告生成 | static-hosting | 生成独立 HTML 报告,提供持久化 URL | + +--- + +### 8.2 电商 & 零售行业 + +#### 场景 1:商品浏览与选购 + +Agent 作为导购,在对话中展示可交互的商品卡片,用户直接点选下单。 +``` +用户: "我想买一杯咖啡" +Agent: 查询商品 → render_html 展示商品卡片列表(图片、价格、规格选择按钮) +用户: 点击"大杯拿铁" → mcp-app-response 回传选择 +Agent: 生成订单 → render_html 展示订单确认页(含二维码/支付链接) +用户: 点击"确认支付" → 跳转支付或内嵌支付页 +``` + +#### 场景 2:订单追踪可视化 + +用户查询订单后,Agent 用图表和时间轴展示物流进度。 +``` +用户: "我的订单到哪了?" +Agent: 查询物流 API → render_html 渲染物流时间轴(已下单→已发货→运输中→派送中) + render_url 嵌入地图展示快递实时位置 +``` + +#### 场景 3:智能比价与推荐 + +Agent 搜索多平台价格,用图表对比展示,用户点击心仪商品直接购买。 +``` +用户: "帮我比较一下 AirPods Pro 各平台价格" +Agent: 调用多个 API → render_chart(chart_type="bar") 展示各平台价格柱状图 + render_html 渲染商品对比卡片(含"去购买"按钮) +用户: 点击最低价平台的"去购买" → render_url 嵌入购买页面 +``` + +#### 场景 4:营销数据看板 + +商家用 Agent 查看店铺运营数据,实时图表展示 GMV、转化率、流量来源等。 +``` +店主: "看看这周的店铺数据" +Agent: 查询后台 API + → render_metrics 展示 KPI 卡片(GMV、订单数、客单价、退货率) + → render_multi_chart 展示趋势图 + 流量来源饼图 + 热销品排行柱状图 +``` + +#### 场景 5:退换货自助流程 + +用户在对话中完成退换货的完整流程,无需跳出。 +``` +用户: "我想退货" +Agent: ask_user 选择订单 → ask_user 选择退货原因 + → render_html 展示退货信息确认页(商品图、退款金额、退货地址) +用户: 点击"确认退货" → Agent 调用退货 API → 展示退货单号和进度 +``` + +--- + +### 8.3 教育 & 培训行业 + +#### 场景 1:交互式测验 + +Agent 出题后用选项卡 UI 让学生作答,即时批改并展示成绩图表。 +``` +老师: "给学生出一套 10 道英语选择题" +Agent: 生成题目 → ask_user 逐题展示选项(支持单选/多选) +学生: 逐题点击选项并提交 +Agent: 批改 → render_chart(chart_type="gauge") 展示总分 + → render_multi_chart 展示各知识点得分雷达图 + 错题分布 +``` + +#### 场景 2:学习进度仪表盘 + +学生查看自己的学习数据,Agent 用图表展示进度和薄弱环节。 +``` +学生: "我的学习情况怎么样?" +Agent: 查询学习记录 + → render_metrics 展示关键指标(完成率、连续学习天数、总学时) + → render_chart(chart_type="radar") 展示各科目能力雷达图 + → render_chart(chart_type="line") 展示近 30 天学习时长趋势 +``` + +#### 场景 3:代码 Playground + +编程教学中,Agent 在对话内嵌入可运行的代码编辑器,学生即学即练。 +``` +老师: "教学生用 Python 写一个冒泡排序" +Agent: 讲解算法 → render_html 渲染一个内嵌的代码编辑器 + 运行按钮 + 输出区 +学生: 修改代码 → 点击运行 → 实时看到排序过程动画 +``` + +#### 场景 4:课程安排与选课 + +用交互式日历展示课表,学生直接点选空闲时段报名课程。 +``` +学生: "我想报名下周的课程" +Agent: 查询可选课程 → render_html 渲染交互式周历(已有课程标灰,可选课程高亮) +学生: 点击某个时段的课程 → mcp-app-response 回传选课信息 +Agent: 确认选课 → 更新课表 +``` + +#### 场景 5:知识图谱可视化 + +复杂知识点之间的关系用交互式图谱展示,点击节点展开详情。 +``` +学生: "帮我梳理一下机器学习的知识体系" +Agent: render_html 渲染交互式知识图谱(D3.js 力导向图) + 节点:监督学习、无监督学习、强化学习... +学生: 点击"监督学习" → 回传节点 ID → Agent 展开子图谱(回归、分类、SVM、决策树...) +``` + +--- + +### 8.4 金融 & 财务行业 + +#### 场景 1:投资组合分析 + +Agent 查询持仓数据后,用图表展示资产配置和收益走势。 +``` +用户: "看看我的投资组合表现" +Agent: → render_chart(chart_type="pie") 展示资产配置比例(股票/债券/基金/现金) + → render_chart(chart_type="line") 展示近一年收益率走势(vs 沪深300) + → render_metrics 展示关键指标(总资产、日收益、年化收益率、最大回撤) +``` + +#### 场景 2:财务报表可视化 + +企业财务数据自动生成专业图表,支持钻取查看明细。 +``` +CFO: "展示 Q2 的财务概况" +Agent: 查询 ERP → render_multi_chart 四宫格展示: + - 收入趋势(折线图) + - 成本结构(饼图) + - 各部门预算执行(堆叠柱状图) + - 现金流仪表盘(gauge) +用户: 点击"销售部"柱子 → Agent 展开销售部详细费用明细 +``` + +#### 场景 3:风险评估与审批 + +贷款/保险审核场景,Agent 渲染评估报告和审批按钮。 +``` +风控: "审核这笔贷款申请" +Agent: 查询征信 → render_html 渲染风险评估报告(信用评分、负债率、历史逾期) + → render_chart(chart_type="gauge") 展示综合风险分数 + → render_html 底部渲染"批准 / 拒绝 / 补充材料"操作按钮 +风控: 点击"批准" → Agent 调用审批 API → 流程完成 +``` + +#### 场景 4:账单与报销管理 + +员工在对话中完成报销申请的完整流程。 +``` +员工: "我要提交上周出差的报销" +Agent: ask_user 选择出差项目和费用类型 + → render_html 渲染报销单表单(日期、金额、发票上传区) +员工: 填写并提交 → Agent 校验金额 → 提交审批流 + → render_html 展示审批进度时间轴 +``` + +--- + +### 8.5 医疗 & 健康行业 + +#### 场景 1:健康数据可视化 + +患者查看自己的健康指标趋势,Agent 用图表直观展示。 +``` +患者: "看看我最近的血压数据" +Agent: 查询健康记录 + → render_chart(chart_type="line") 展示近 30 天血压趋势(收缩压/舒张压双线) + → render_metrics 展示平均值、最高值、异常次数 + → render_html 底部展示健康建议卡片 +``` + +#### 场景 2:在线问诊引导 + +Agent 用交互式问答收集症状,辅助分诊。 +``` +患者: "我最近头疼" +Agent: ask_user 收集症状细节: + Q1: "头疼持续多久?" → [1-3天, 一周以上, 反复发作] + Q2: "伴随哪些症状?" → [恶心, 视力模糊, 发热, 无其他] (multi_select) + Q3: "疼痛位置?" → render_html 展示头部示意图,用户点击标记位置 +Agent: 综合分析 → render_html 展示初步评估结果 + 推荐科室 + 预约按钮 +``` + +#### 场景 3:预约挂号 + +在对话中展示医生排班表,患者点选预约。 +``` +患者: "帮我挂神经内科的号" +Agent: 查询排班 → render_html 渲染医生列表卡片(照片、职称、擅长、可约时段) +患者: 点击某医生 → ask_user 选择具体时间段 +Agent: 确认预约 → 展示预约成功信息和就诊提醒 +``` + +--- + +### 8.6 企业办公 & HR + +#### 场景 1:OA 审批流程 + +请假、采购、出差等审批在对话中一键完成。 +``` +员工: "帮我请三天年假" +Agent: ask_user 选择请假类型和日期范围 + → render_html 渲染请假申请预览(含剩余年假天数) +员工: 确认 → Agent 提交 OA 系统 + → render_html 展示审批链进度(直属经理→HR→完成) +``` + +#### 场景 2:团队数据看板 + +管理者查看团队运营指标,图表一目了然。 +``` +经理: "看看我们团队这个月的情况" +Agent: → render_metrics 展示 KPI(项目完成率、工时利用率、bug 数、客户满意度) + → render_multi_chart 展示: + - 各成员工时分布(堆叠柱状图) + - 项目进度甘特图(render_html 自定义) + - 本月 vs 上月对比(折线图) +``` + +#### 场景 3:招聘面试管理 + +HR 用 Agent 管理候选人,在对话中查看面试安排和评估。 +``` +HR: "今天有哪些面试?" +Agent: 查询日程 → render_html 渲染今日面试时间轴(候选人、岗位、面试官、时间) +HR: 点击某候选人 → Agent 展示简历摘要 + 前几轮面评 + → ask_user 选择面试结论(通过/待定/淘汰) +``` + +#### 场景 4:会议纪要与投票 + +会议中实时收集决策投票,即时展示结果。 +``` +主持人: "大家投票选择 Q3 的主推方案" +Agent: ask_user 展示方案选项(方案A/方案B/方案C),支持多人投票 + → 汇总结果 → render_chart(chart_type="pie") 展示投票比例 + → render_html 展示会议结论摘要 + 行动项清单 +``` + +--- + +### 8.7 房产 & 本地生活 + +#### 场景 1:房源浏览与对比 + +在对话中展示房源卡片,支持对比和地图查看。 +``` +用户: "帮我找朝阳区两居室,预算 500 万以内" +Agent: 搜索房源 → render_html 渲染房源卡片列表(图片轮播、价格、面积、户型图) +用户: 选中 3 套 → Agent → render_html 渲染对比表格(价格/面积/楼层/朝向/学区) +用户: 点击"查看位置" → render_html 渲染地图标注(3 套房源 + 周边配套) +``` + +#### 场景 2:餐厅推荐与订位 + +Agent 推荐餐厅,用户在对话中直接预约座位。 +``` +用户: "今晚想吃日料,帮我推荐" +Agent: 搜索附近餐厅 → render_html 渲染餐厅卡片(评分、人均、距离、招牌菜图片) +用户: 点击某餐厅 → Agent 展示详情 + 可用时段 + → ask_user 选择用餐时间和人数 +Agent: 调用预约 API → 展示预约确认信息 +``` + +#### 场景 3:装修进度管理 + +业主用 Agent 追踪装修进度,图文结合展示。 +``` +业主: "装修到哪一步了?" +Agent: 查询工程系统 → render_html 渲染装修进度时间轴(水电→瓦工→木工→油漆→软装) + 每个节点可展开查看现场照片 + → render_chart(chart_type="pie") 展示费用分配 + → render_metrics 展示预算执行(总预算、已花费、剩余) +``` + +--- + +### 8.8 物流 & 供应链 + +#### 场景 1:运输追踪大屏 + +在对话中展示车队/货物的实时状态。 +``` +调度员: "看看今天所有在途车辆" +Agent: 查询 TMS → render_html 渲染地图(标注所有在途车辆位置和状态) + → render_metrics 展示概览(在途 23 辆、已到达 15 辆、异常 2 辆) +调度员: 点击异常车辆标注 → Agent 展示异常详情 + 处理选项按钮 +``` + +#### 场景 2:库存预警与补货 + +Agent 监控库存,低于阈值时主动展示预警图表和补货建议。 +``` +仓管: "哪些商品快缺货了?" +Agent: 查询 WMS → render_html 渲染库存预警表格(红/黄/绿三色标注) + → render_chart(chart_type="bar") 展示 Top 10 紧缺商品及预计断货天数 + → render_html 底部渲染"一键生成补货单"按钮 +仓管: 点击按钮 → Agent 自动生成采购单 → ask_user 确认供应商和数量 +``` + +--- + +### 8.9 旅游 & 酒店行业 + +#### 场景 1:行程规划助手 + +Agent 生成交互式行程表,用户拖拽调整。 +``` +用户: "帮我规划 5 天东京自由行" +Agent: 生成行程 → render_html 渲染交互式日程表(每天的景点、交通、餐厅、住宿) + 每个景点卡片含图片、预计时长、门票价格 +用户: 拖拽调整顺序 / 删除某景点 → mcp-app-response 回传新顺序 +Agent: 重新优化路线 → render_html 更新地图路线图 +``` + +#### 场景 2:酒店预订对比 + +Agent 搜索多个平台,在对话中渲染对比界面。 +``` +用户: "帮我找东京新宿的酒店,2 晚" +Agent: 搜索多平台 → render_html 渲染酒店对比卡片(图片轮播、评分、价格、设施标签) + → render_chart(chart_type="scatter") 展示价格 vs 评分散点图 +用户: 点击心仪酒店 → render_url 嵌入预订页面 +``` + +#### 场景 3:景区实时信息 + +展示景区客流量、天气、开放状态等实时信息。 +``` +用户: "迪士尼现在人多吗?" +Agent: → render_metrics 展示实时数据(当前客流 12,000、各区域排队时长) + → render_chart(chart_type="line") 展示今日客流量趋势(预测下午 3 点高峰) + → render_html 展示热门项目排队时间排行(红绿标注) +``` + +--- + +### 8.10 制造 & 工业行业 + +#### 场景 1:生产监控大屏 + +Agent 实时展示产线状态和异常告警。 +``` +厂长: "1 号产线今天的情况怎么样?" +Agent: → render_metrics 展示 KPI(产量、良品率、设备 OEE、停机次数) + → render_multi_chart 展示: + - 每小时产量趋势(折线图) + - 不良品分类(饼图) + - 各工位效率对比(柱状图) + - 设备温度仪表盘(gauge) +``` + +#### 场景 2:设备维保管理 + +展示设备健康状态,支持一键报修。 +``` +维保工程师: "哪些设备需要保养了?" +Agent: 查询设备系统 → render_html 渲染设备列表(状态灯:绿/黄/红) + → render_chart(chart_type="bar") 展示各设备距下次保养的剩余天数 +工程师: 点击某设备 → Agent 展示维保记录 + 零件清单 + → render_html 渲染"创建工单"按钮 → 点击后自动创建维保工单 +``` + +#### 场景 3:质检报告可视化 + +质检数据自动生成可视化报告,支持导出。 +``` +质检员: "生成今天的质检报告" +Agent: 查询质检数据 + → render_multi_chart 展示各检测项合格率、SPC 控制图 + → render_html 渲染质检报告摘要(含不合格批次明细表格) + → static-hosting 生成 PDF 格式报告,提供下载 URL +``` + +--- + +### 8.11 IT & 运维行业 + +#### 场景 1:服务监控仪表盘 + +在对话中实时展示系统运行状态。 +``` +运维: "生产环境现在状态怎么样?" +Agent: → render_metrics 展示关键指标(在线实例 12/12、P99: 230ms、错误率 0.02%) + → render_multi_chart 展示 CPU/内存/QPS/错误率四宫格图表 + → render_url 嵌入 Grafana 面板查看更多细节 +``` + +#### 场景 2:故障排查向导 + +Agent 引导运维人员逐步排查问题。 +``` +运维: "用户反馈页面加载很慢" +Agent: + Step 1 → ask_user 选择受影响的服务(API/Web/DB) + Step 2 → Agent 查询日志 → render_chart 展示该服务近 1 小时响应时间 + Step 3 → 发现 DB 慢查询 → render_html 渲染慢查询 Top 10 表格 + Step 4 → ask_user 选择处理方式(添加索引 / 重启连接池 / 扩容) + Step 5 → Agent 执行 → render_metrics 展示恢复后的指标 +``` + +#### 场景 3:CI/CD 流水线管理 + +在对话中创建和监控部署流水线。 +``` +开发者: "帮我配一个新的部署流水线" +Agent: + → ask_user 选择代码仓库和分支策略 + → ask_user 选择构建环境(Node 20 / Python 3.12 / Go 1.22) + → ask_user 选择部署目标(dev / staging / prod) + → render_html 展示生成的 YAML 配置预览 + → 用户确认 → Agent 调 API 创建 → render_html 展示流水线状态时间轴 +``` + +--- + +### 8.12 场景速查表 + +| 行业 | 典型场景 | 核心工具组合 | +|------|---------|-------------| +| 电商零售 | 商品浏览、比价、订单追踪、营销看板、退换货 | render_html + ask_user + render_chart | +| 教育培训 | 在线测验、学习看板、代码练习、选课、知识图谱 | ask_user + render_chart + render_html | +| 金融财务 | 投资分析、财报可视化、风控审批、报销管理 | render_multi_chart + render_metrics + render_html | +| 医疗健康 | 健康趋势、问诊引导、预约挂号 | render_chart + ask_user + render_html | +| 企业办公 | OA 审批、团队看板、招聘管理、会议投票 | ask_user + render_metrics + render_chart | +| 房产生活 | 房源对比、餐厅预约、装修追踪 | render_html + render_chart + ask_user | +| 物流供应链 | 运输追踪、库存预警、补货管理 | render_html + render_metrics + render_chart | +| 旅游酒店 | 行程规划、酒店对比、景区实时信息 | render_html + render_chart + render_url | +| 制造工业 | 产线监控、设备维保、质检报告 | render_multi_chart + render_metrics + render_html | +| IT 运维 | 服务监控、故障排查、CI/CD 管理 | render_metrics + render_multi_chart + ask_user | + +## 9. FAQ + +### Q: MCP App 和 static-hosting 有什么区别? + +| 维度 | MCP App | static-hosting | +|------|---------|----------------| +| 渲染位置 | 聊天窗口内(iframe) | 独立浏览器 Tab | +| 生命周期 | 临时,随对话存在 | 持久化,有独立 URL | +| 交互能力 | 双向(postMessage) | 单向(只展示) | +| 适用场景 | 对话内交互组件 | 报告、网页、可分享内容 | + +### Q: HTML App 是每次重新加载还是缓存的? + +HTML App 模板是通过 `resources/read` 获取的静态文件,Host 可以缓存。但每次 `tools/call` 的数据是动态的,通过 postMessage 实时传入。 + +### Q: 用户交互结果如何回传给 Agent? + +HTML App 通过 `window.parent.postMessage({type: 'mcp-app-response', payload: ...})` 发送,Host 接收后将 payload 作为工具调用结果传回 Agent,Agent 可以据此继续对话。 + +### Q: 安全性如何保证? + +- HTML App 运行在 **sandboxed iframe** 中,无法访问主页面 DOM +- 使用 `postMessage` 通信,有明确的消息协议 +- 不执行任意远程代码,HTML 模板是预定义的静态文件 + +### Q: 我能用 React/Vue 来写 HTML App 吗? + +可以,但建议将构建产物打包为单个 HTML 文件(inline CSS/JS)。因为 `resources/read` 返回的是一个完整的 HTML 字符串,不支持多文件加载。也可以用 CDN 引入框架(如示例中 ECharts 用了 CDN)。 + +### Q: PrePrompt Hook 是做什么的? + +PrePrompt 钩子在每次对话开始前执行,将 `usage_guide.md` 的内容注入到 Agent 的 system prompt 中。这让 Agent 知道有哪些工具可用,以及什么时候应该调用它们。**这是让 Agent "学会"使用 UI 工具的关键。** + +--- + +## 附录:参考资源 + +- 项目内 mcp-ui 源码:`skills/common/mcp-ui/` +- 项目内 data-dashboard 源码:`skills/common/data-dashboard/` +- 项目内 static-hosting 定义:`skills/support/static-hosting/SKILL.md` +- MCP UI 社区项目:[github.com/idosal/mcp-ui](https://github.com/idosal/mcp-ui) +- MCP 协议规范:[modelcontextprotocol.io](https://modelcontextprotocol.io) diff --git a/skills/developing/ecommerce-storefront/.claude-plugin/plugin.json b/skills/developing/ecommerce-storefront/.claude-plugin/plugin.json new file mode 100644 index 0000000..37d6d8e --- /dev/null +++ b/skills/developing/ecommerce-storefront/.claude-plugin/plugin.json @@ -0,0 +1,19 @@ +{ + "name": "ecommerce-storefront", + "description": "Renders interactive product browsing, selection, and order confirmation UI for e-commerce scenarios.", + "hooks": { + "PrePrompt": [ + { + "type": "command", + "command": "python hooks/pre_prompt.py" + } + ] + }, + "mcpServers": { + "ecommerce_storefront": { + "transport": "stdio", + "command": "python", + "args": ["./ecommerce_server.py", "{bot_id}"] + } + } +} diff --git a/skills/developing/ecommerce-storefront/apps/order-confirm.html b/skills/developing/ecommerce-storefront/apps/order-confirm.html new file mode 100644 index 0000000..bbbfa1d --- /dev/null +++ b/skills/developing/ecommerce-storefront/apps/order-confirm.html @@ -0,0 +1,233 @@ + + + + + +