使用说明
MCP应用游乐场
一个最小的教育游乐场,了解 模型上下文协议(MCP)应用程序 建筑。该项目演示了MCP服务器如何返回交互式UI组件,这些组件通过安全的沙盒环境与其主机通信。
什么是MCP应用程序?
MCP应用程序 是可由MCP服务器返回并在沙盒iframe中呈现的交互式UI组件。它们能够:
- 交互式工作流程:用户可以直接与UI元素交互
- 安全执行:应用程序在具有有限权限的隔离iframe中运行
- 双向通信:应用程序和主机通过JSON-RPC 2.0交换消息
- 框架无关:应用程序可以用任何web技术(React、Vue、vanilla JS等)构建
将MCP应用程序视为MCP服务器可以提供的“迷你应用程序”,以创建更丰富、更互动的体验,而不仅仅是简单的文本响应。
架构概述
┌─────────────────────────────────────────────────────────┐
│ Host Application │
│ ┌────────────────────────────────────────────────────┐ │
│ │ AppHost Component │ │
│ │ - Manages iframe lifecycle │ │
│ │ - Creates AppBridge for communication │ │
│ │ - Exposes host methods (notifications, actions) │ │
│ └──────────────────┬─────────────────────────────────┘ │
│ │ AppBridge │
│ │ (JSON-RPC over PostMessage) │
└─────────────────────┼─────────────────────────────────────┘
│
│ Secure PostMessage
│ Cross-origin communication
│
┌─────────────────────┼─────────────────────────────────────┐
│ │ Sandboxed Iframe │
│ ┌──────────────────▼───────────────────────────────┐ │
│ │ MCP App │ │
│ │ - Renders interactive UI │ │
│ │ - Creates AppBridge to communicate with host │ │
│ │ - Calls host methods (showNotification, etc.) │ │
│ │ - Responds to host requests (sendData, etc.) │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ Limited permissions: allow-scripts allow-same-origin │
└───────────────────────────────────────────────────────────┘
关键组件
-
AppHost:承载MCP应用程序的React组件
- 在沙盒iframe中呈现应用程序
- 管理AppBridge生命周期
- 将主机功能暴露给应用程序
-
AppBridge:通信层
- 通过PostMessage实现JSON-RPC 2.0
- 双向请求/响应和通知
- 类型安全消息处理
-
MCP应用程序:交互式应用程序
- 在独立的iframe中运行
- 仅通过AppBridge进行通信
- 可以用任何web框架构建
关键概念
1.AppBridge通信
这 AppBridge 将PostMessage封装在JSON-RPC 2.0协议中,提供:
-
请求::发送消息并等待响应
const result = await bridge.request('host.showNotification', { message: 'Hello!', type: 'info' }); -
通知:发送单向消息(预期无响应)
bridge.notify('counter.changed', { count: 5 }); -
处理器:注册传入消息的处理程序
bridge.onRequest('app.sendData', async (params) => { // Handle data from host return { success: true }; });
2.Iframe沙盒
应用程序在具有受限权限的沙盒iframe中运行:
<iframe
sandbox="allow-scripts allow-same-origin"
src="app-url"
/>
这通过以下方式提供安全性:
- 将应用程序执行与宿主页面隔离
- 防止直接DOM访问主机
- 限制应用程序的功能(除非允许,否则没有弹出窗口、表单等)
3.邮件传输
通信使用浏览器 张贴消息API:
- 安全:源验证可防止未经授权的访问
- 跨域:跨不同领域工作
- 异步:无阻塞消息传递
- 标准:内置于所有现代浏览器中
4.应用程序生命周期
应用程序可以实现生命周期方法:
class MyApp implements App {
async onMount(bridge: AppBridge) {
// Called when app is initialized
this.bridge = bridge;
}
async onUnmount() {
// Called when app is being destroyed
this.bridge.close();
}
}
入门指南
安装
# Install dependencies
npm install
运行项目
选项1:仅前端(演示模式)
npm run dev
访问 http://localhost:3000 操场或 /chat.html 用于具有模拟响应的聊天界面。
选项2:使用AI驱动的后端(推荐)
# Terminal 1: Start the backend server
npm run dev:server
# Terminal 2: Start the frontend
npm run dev
# Or run both together:
npm run dev:all
后端服务器运行在 http://localhost:3001 并提供人工智能驱动的响应,智能地决定何时返回MCP应用程序。
体验MCP应用程序的两种方法
- 游乐场模式 (
/)-通过直接控制选择和测试单个应用程序 - 聊天界面 (
/chat.html)-人工智能聊天,根据您的请求智能返回交互式应用程序
项目结构
mcp-apps-playground/
├── src/
│ ├── app/
│ │ └── HelloWorldApp.tsx # Minimal example
│ ├── host/
│ │ └── AppHost.tsx # Host component
│ ├── bridge/
│ │ └── AppBridge.ts # Communication layer
│ ├── chat/
│ │ ├── ChatInterface.tsx # Chat UI with embedded apps
│ │ └── chat-main.tsx # Chat entry point
│ ├── types/
│ │ └── index.ts # TypeScript types
│ └── main.tsx # Demo application
├── examples/
│ ├── counter/
│ │ └── CounterApp.tsx # Interactive counter
│ └── form/
│ └── FormApp.tsx # Form submission
├── server/
│ ├── index.js # AI-powered backend server
│ └── README.md # Server documentation
├── docs/
│ └── ARCHITECTURE.md # Detailed architecture
├── index.html # Playground entry point
├── chat.html # Chat interface entry
├── hello.html # Hello app entry
├── counter.html # Counter app entry
├── form.html # Form app entry
└── package.json
例子
人工智能聊天界面
新 使用人工智能后端体验MCP应用程序 /chat.html
聊天界面演示了具有AI功能的MCP服务器如何智能地决定何时返回交互式MCP应用程序:
特性
- AI决策引擎:后端服务器分析您的消息,并决定应用程序是否有用
- 自然语言交互:简单地用简单的英语描述你需要什么
- 智能应用程序选择:AI返回最合适的应用程序(计数器、表单或演示)
- 会话上下文:服务器维护对话历史记录以获得更好的响应
- 一次聊天中有多个应用程序:同时创建多个应用程序并与之交互
运作原理
User: "I need to track some numbers"
↓
AI Server analyzes intent
↓
Returns: Counter App + explanatory text
↓
App rendered in chat message
试试看:
- 启动后端服务器:
npm run dev:server - 访问
/chat.html - 键入自然语言请求,如:
- “为我创建一个计数器”
- “我需要一个表格来收集用户数据”
- “演示MCP应用程序的工作原理”
- 人工智能将智能地返回适当的交互组件
技术说明:当前的实现使用智能模式匹配,可以轻松升级为使用GPT-4、Claude或本地LLM。看 server/README.md 了解集成细节。
1.Hello World应用程序
最简单的MCP应用程序:
- 显示基本AppBridge设置
- 演示宿主方法调用
- 显示状态更新
试试看:点击“向主机发送消息”查看主机通信
2.计数器应用程序
交互式状态管理:
- 应用程序内的本地状态管理
- 双向通信(应用程序↔ 主机)
- 活动历史跟踪
- 主机可以通过AppBridge控制计数器
试试看:
- 局部递增/递减
- 查看活动日志
- 检查浏览器控制台的通信日志
3.表单应用程序
表单处理和数据提交:
- 输入验证
- 表单状态管理
- 向主机提交结构化数据
- 错误处理和反馈
试试看:
- 填写表格
- 提交以查看主机交互
- 检查浏览器控制台以查看提交的数据
标准方法
宿主方法(可由应用程序调用)
// Show a notification
bridge.request('host.showNotification', {
message: 'Hello!',
type: 'info'
});
// Execute an action
bridge.request('host.executeAction', {
action: 'save',
data: { ... }
});
// Get host capabilities
const caps = await bridge.request('host.getCapabilities');
// Log a message (debugging)
bridge.request('host.log', {
level: 'info',
message: 'Debug info'
});
应用程序方法(可由主机调用)
// Initialize the app
bridge.request('app.initialize', {
initialCount: 5
});
// Send data to the app
bridge.request('app.sendData', {
formData: { name: 'John' }
});
// Request app to perform an action
bridge.request('app.performAction', {
action: 'reset'
});
构建自己的应用程序
步骤1:创建应用程序组件
import React, { useEffect, useState } from 'react';
import { AppBridge } from '../bridge/AppBridge';
const MyApp: React.FC = () => {
const [bridge, setBridge] = useState<AppBridge | null>(null);
useEffect(() => {
// Connect to host
const appBridge = new AppBridge(window.parent, '*');
setBridge(appBridge);
// Register handlers for host requests
appBridge.onRequest('app.doSomething', async (params) => {
return { success: true };
});
return () => {
appBridge.close();
};
}, []);
return <div>My App Content</div>;
};
步骤2:创建HTML入口点
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
<script type="module" src="/src/app/MyApp.tsx"></script>
</body>
</html>
步骤3:使用AppHost进行渲染
<AppHost
appUrl="/my-app.html"
title="My App"
height="400px"
onReady={(bridge) => {
console.log('App ready!');
}}
/>
开发技巧
- 打开浏览器控制台:通信日志对调试非常有帮助
- 检查网络选项卡:查看iframe是否正确加载
- 原产地验证:在生产中,使用特定的来源,而不是
'*' - 错误处理:始终处理网桥请求中的promise拒绝
- TypeScript:使用提供的类型以获得更好的开发人员体验
安全考虑
- 沙盒属性:仔细选择iframe沙盒权限
- 原产地验证:验证生产中的消息来源
- 输入验证:在使用应用程序之前,对应用程序中的所有数据进行消毒
- CSP标头:考虑内容安全策略以获得额外保护
- 超文本传输安全协议:在生产环境中始终使用HTTPS
参考文献
-
MCP-UI PR#147: ochafik为MCP应用程序提供的React渲染器
- React中MCP应用程序的实现参考
-
modelcontextprotocol/ext应用程序: MCP官方应用SDK
- 用于构建MCP应用程序的TypeScript SDK
- SEP-1865规范
-
JSON-RPC 2.0: 规格说明
- AppBridge使用的通信协议
贡献
这是一个教育游乐场。请随意:
- 添加更多示例应用
- 改进文档
- 修复错误或问题
- 分享反馈
许可证
麻省理工学院许可证-您可以自由使用它来学习和构建自己的MCP应用程序!
幸福大厦! 🚀
如果您有任何疑问或想了解有关MCP Apps的更多信息,请查看 详细的架构文档.