MCP应用程序垫片
一个桥接基于CLI的MCP客户端的stdio MCP代理(如 )to MCP应用程序 具有基于浏览器的交互式UI的服务器。
建造于 尼克·科森蒂诺 支持发展 BrandGhost 的 平台。
示例
通过以下方式在浏览器中呈现的Excalidraw架构图 mcp-app-shim,由Copilot CLI工具调用触发:
Excalidraw diagram rendered via mcp-app-shim
问题
MCP应用服务器(如 排除MCP)使用 registerAppTool() 展示带有交互式HTML小部件的工具。像Claude Desktop或ChatGPT这样的主机会内联渲染这些内容。但是像Copilot CLI这样的基于stdio的客户端不支持MCP Apps UI扩展——它们只看到文本结果,并默默地丢弃交互式内容。
解决方案
mcp-app-shim 位于CLI客户端和上游MCP App服务器之间:
┌──────────────┐ stdio ┌───────────────┐ HTTP/SSE ┌──────────────────┐
│ Copilot CLI │◄─────────►│ mcp-app-shim │◄────────────►│ MCP App Server │
│ (or any │ │ │ │ (Excalidraw, │
│ MCP client) │ │ ┌──────────┐ │ │ Playground, │
└──────────────┘ │ │ Browser │ │ │ custom, etc.) │
│ │ Host │ │ └──────────────────┘
│ └──────────┘ │
└───────────────┘- 透明地代理所有工具 --标准工具保持不变
- 检测应用程序工具 --工具与
_meta.ui.resourceUri触发浏览器渲染 - 获取HTML资源 从上游服务器
- 打开浏览器 包括完整的AppBridge协议支持(工具输入/结果传递,
callServerTool代理) - 返回文本结果 正常连接到CLI客户端
快速开始
先决条件
- Node.js 18+
- npm
安装
git clone https://github.com/ncosentino/mcp-app-shim.git
cd mcp-app-shim
npm install
npm run build与Copilot CLI一起使用
将垫片添加为Copilot CLI配置中任何MCP App服务器的包装器(~/.copilot/mcp-config.json):
{
"servers": {
"excalidraw": {
"command": "node",
"args": [
"/path/to/mcp-app-shim/dist/index.js",
"https://mcp.excalidraw.com/mcp"
]
}
}
}就是这样。现在,当Copilot CLI调用Excalidraw工具时,就像 create_view,图表会自动在浏览器中打开。
与Claude Desktop一起使用
添加到您的Claude桌面配置(claude_desktop_config.json):
{
"mcpServers": {
"excalidraw": {
"command": "node",
"args": [
"/path/to/mcp-app-shim/dist/index.js",
"https://mcp.excalidraw.com/mcp"
]
}
}
}从命令行使用
# Run directly
node dist/index.js https://mcp.excalidraw.com/mcp
# Or if installed globally / via npx
mcp-app-shim https://mcp.excalidraw.com/mcp集成示例
垫片适用于任何使用 registerAppTool() 从 @modelcontextprotocol/ext-apps。以下是一些你可以尝试的:
排除MCP
交互式绘图和白板。工具: create_view, export_to_excalidraw, save_checkpoint, read_checkpoint.
{
"excalidraw": {
"command": "node",
"args": ["/path/to/mcp-app-shim/dist/index.js", "https://mcp.excalidraw.com/mcp"]
}
}MCP应用游乐场
一个带有交互式工具的演示服务器,如拖放列表排序器、火焰图可视化和特征标志仪表板。
{
"playground": {
"command": "node",
"args": ["/path/to/mcp-app-shim/dist/index.js", "https://playground.mcpapps.dev/mcp"]
}
}您自己的MCP应用服务器
如果您使用以下方式构建MCP服务器 registerAppTool(),您可以用垫片包裹它:
{
"my-app": {
"command": "node",
"args": ["/path/to/mcp-app-shim/dist/index.js", "http://localhost:3000/mcp"]
}
}一个最小的MCP应用服务器看起来像:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { registerAppTool, registerAppResource } from "@modelcontextprotocol/ext-apps/server";
import { z } from "zod";
const server = new McpServer({ name: "my-app", version: "1.0.0" });
// Register a UI resource (HTML that runs in the browser)
registerAppResource(server, "widget", "ui://my-app/widget", {}, async () => ({
contents: [{
uri: "ui://my-app/widget",
mimeType: "text/html;profile=mcp-app",
text: `
My Widget
import { App } from "https://esm.sh/@modelcontextprotocol/ext-apps";
const app = new App({ name: "widget", version: "1.0.0" });
app.ontoolinput = (params) => {
document.body.innerHTML += "
" + JSON.stringify(params.input) + "
";
};
await app.connect();
`
}]
}));
// Register a tool linked to the UI
registerAppTool(server, "show_widget", {
description: "Show an interactive widget",
inputSchema: { query: z.string() },
_meta: { ui: { resourceUri: "ui://my-app/widget" } }
}, async ({ query }) => {
return { content: [{ type: "text", text: `Query: ${query}` }] };
});运作原理
建筑
垫片运行两个本地HTTP服务器:
- 主页 (端口9271)-渲染外框,管理与填充程序的WebSocket连接,实现 MCP应用程序主机协议
- 沙盒页面 (端口9272)-安全隔离的不同来源,通过以下方式将应用程序HTML加载到嵌套的iframe中
document.write()
协议流
1. CLI calls tool → shim forwards to upstream server
2. Upstream returns result → shim checks for _meta.ui.resourceUri
3. If app tool:
a. Fetch HTML resource from upstream
b. Start local host/sandbox servers (if not running)
c. Serve HTML, open browser
d. WebSocket pushes tool input + result to browser
e. AppBridge initializes (ui/initialize handshake)
f. App renders with full interactivity
4. Text result returned to CLI as normalAppBridge支持
主机页面实现了MCP Apps AppBridge协议:
ui/initialize--回应如下hostInfo,hostCapabilities,以及hostContexttools/call--代理人callServerTool来自应用程序的请求通过垫片返回到上游服务器- 工具输入/结果交付 --通过推送
ui/notifications/tool-input和ui/notifications/tool-result
发展
# Build
npm run build
# Watch mode
npm run dev
# Run integration tests
npx tsx test/integration.ts项目结构
src/
index.ts # Stdio MCP proxy (main entry point)
app-host-server.ts # Express servers + WebSocket + HTML host/sandbox pages
test/
integration.ts # Full integration test
test-server.ts # Mock MCP server with normal + app tools
test-client.ts # Direct client connection test许可证
麻省理工学院
______________________________________________________________________
由...创建 尼克·科森蒂诺 为了 BrandGhost 的 --人工智能驱动的社交媒体管理平台。
