模型上下文协议应用演示平台

一个用于理解和演示MCP(模型上下文协议)应用架构的教育平台,展示如何通过安全沙箱环境实现交互式UI组件与主机的双向通信。

  • by MosheHM
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 MosheHM/mcp-apps-playground

使用说明

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    │
└───────────────────────────────────────────────────────────┘

关键组件

  1. AppHost:承载MCP应用程序的React组件

    • 在沙盒iframe中呈现应用程序
    • 管理AppBridge生命周期
    • 将主机功能暴露给应用程序
  2. AppBridge:通信层

    • 通过PostMessage实现JSON-RPC 2.0
    • 双向请求/响应和通知
    • 类型安全消息处理
  3. 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应用程序的两种方法

  1. 游乐场模式 (/)-通过直接控制选择和测试单个应用程序
  2. 聊天界面 (/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!');
  }}
/>

开发技巧

  1. 打开浏览器控制台:通信日志对调试非常有帮助
  2. 检查网络选项卡:查看iframe是否正确加载
  3. 原产地验证:在生产中,使用特定的来源,而不是 '*'
  4. 错误处理:始终处理网桥请求中的promise拒绝
  5. TypeScript:使用提供的类型以获得更好的开发人员体验

安全考虑

  1. 沙盒属性:仔细选择iframe沙盒权限
  2. 原产地验证:验证生产中的消息来源
  3. 输入验证:在使用应用程序之前,对应用程序中的所有数据进行消毒
  4. CSP标头:考虑内容安全策略以获得额外保护
  5. 超文本传输安全协议:在生产环境中始终使用HTTPS

参考文献

贡献

这是一个教育游乐场。请随意:

  • 添加更多示例应用
  • 改进文档
  • 修复错误或问题
  • 分享反馈

许可证

麻省理工学院许可证-您可以自由使用它来学习和构建自己的MCP应用程序!


幸福大厦! 🚀

如果您有任何疑问或想了解有关MCP Apps的更多信息,请查看 详细的架构文档.