mcp应用程序视图
构建和嵌入MCP应用程序(SEP-1865)-MCP的交互式用户界面。
建造于 BotDojo •框架无关•可选React支持•零依赖
](https://www.npmjs.com/package/mcp-app-view) 
这是什么?
MCP Apps(SEP-1865)是模型上下文协议的扩展,使AI代理能够提供交互式用户界面。此SDK使构建与任何MCP兼容主机兼容的MCP应用程序变得容易。
此包是由创建的 BotDojo 作为对MCP生态系统的开源贡献。虽然它与任何MCP主机独立工作,但它与BotDojo无缝集成,具有持久状态、工具流等功能。
安装
npm install mcp-app-view
# or
pnpm add mcp-app-view
# or
yarn add mcp-app-view特性
- ✅ 符合SEP-1865标准 -实施 MCP应用程序规范
- ✅ 框架不可知 -适用于任何框架或vanilla JS
- ✅ 可选的React支持 -一流的React钩子和组件
- ✅ 零依赖 -无外部运行时依赖关系
- ✅ TypeScript优先 -全型安全
- ✅ 状态管理 -内置状态提供者系统(可扩展)
- ✅ 主机组件 -
McpProxyHost用于嵌入MCP应用程序
快速开始
React(最简单)
import { useMcpApp } from 'mcp-app-view/react';
function MyMcpApp() {
const { isInitialized, state, tool, updateState, sendMessage } = useMcpApp({
initialState: { counter: 0 },
});
if (!isInitialized) return
Connecting...
;
if (tool.isStreaming) return
Processing: {tool.name}...
;
return (
Counter: {state.counter}
updateState({ counter: state.counter + 1 })}>
Increment
sendMessage([{ type: 'text', text: 'Hello!' }])}>
Send Message
);
}框架不可知
import { McpAppClient } from 'mcp-app-view';
const client = new McpAppClient({ debug: true });
// Subscribe to events
client.on('initialize', (params) => {
console.log('Host:', params.appInfo);
console.log('Context:', params.hostContext);
});
client.on('toolInput', (params) => {
console.log('Tool:', params.tool.name);
console.log('Args:', params.arguments);
});
client.on('toolResult', (params) => {
console.log('Result:', params.result);
});
// Start the client
client.start();
// Send messages to host
await client.sendMessage([{ type: 'text', text: 'Hello from MCP App!' }]);
// Call tools on the host
const result = await client.callTool('get_weather', { location: 'NYC' });
// Report size changes
client.reportSize(400, 300);______________________________________________________________________
与BotDojo一起使用
BotDojo 是一个用于构建具有丰富工具功能的AI代理的平台。使用时 mcp-app-view 使用BotDojo,您可以获得其他功能:
持久状态
BotDojo会自动在会话之间持久化您的MCP应用程序状态。使用 botdojo/messageType: 'persist-state' 扩展名:
import { useMcpApp } from 'mcp-app-view/react';
function MyApp() {
const { state, sendMessage } = useMcpApp({
initialState: { counter: 0 },
});
const persistCounter = async (newValue: number) => {
// BotDojo will persist this state and hydrate it on next load
await sendMessage([{
type: 'text',
text: JSON.stringify({ counter: newValue }),
'botdojo/messageType': 'persist-state',
}]);
};
return (
persistCounter(state.counter + 1)}>
Count: {state.counter}
);
}工具流
BotDojo通过以下方式提供实时工具参数流 ui/notifications/tool-input-partial:
import { useMcpApp } from 'mcp-app-view/react';
function StreamingApp() {
const { tool } = useMcpApp();
// BotDojo streams tool arguments in real-time
if (tool.isStreaming) {
return (
Running: {tool.name}
Step: {tool.arguments?.stepId}
Progress: {tool.arguments?.progress}%
);
}
return
Result: {JSON.stringify(tool.result)}
;
}BotDojo状态提供者
为了实现完全集成,请使用BotDojo状态提供程序(可在 @botdojo/sdk):
import { useMcpApp } from 'mcp-app-view/react';
import { BotDojoStateProvider } from '@botdojo/sdk';
function MyApp() {
const { state, updateState } = useMcpApp({
initialState: { counter: 0 },
// BotDojo provider handles persistence automatically
stateProvider: new BotDojoStateProvider({ canvasId: 'my-app' }),
});
return
{state.counter}
;
}在BotDojo中托管MCP应用程序
使用 McpProxyHost 将MCP应用程序嵌入到基于BotDojo的应用程序中:
import { McpProxyHost } from 'mcp-app-view/host';
function MyHost() {
return (
{
// Handle messages, including persist-state
const content = params.content[0];
if (content['botdojo/messageType'] === 'persist-state') {
await persistState(JSON.parse(content.text));
}
}}
onToolCall={async (name, args) => {
// Execute tools via BotDojo
return await botdojo.callTool(name, args);
}}
/>
);
}______________________________________________________________________
api参考
框架不可知论(核心)
McpAppClient
MCP Apps通信的主要客户端。
import { McpAppClient } from 'mcp-app-view';
const client = new McpAppClient({
debug: false, // Enable debug logging
autoAcknowledge: true, // Auto-send ui/notifications/initialized
});
// Lifecycle
client.start();
client.stop();
// State
client.isInitialized;
client.state.appInfo;
client.state.hostCapabilities;
client.state.hostContext;
client.state.tool;
// Events
client.on('initialize', (params) => {});
client.on('toolInputPartial', (params) => {});
client.on('toolInput', (params) => {});
client.on('toolResult', (params) => {});
client.on('hostContextChanged', (context) => {});
client.on('resourceTeardown', () => {});
// Actions
await client.sendMessage(content);
await client.openLink(url);
await client.callTool(name, args);
client.reportSize(width, height);状态提供
可插拔状态管理系统。
import { createMemoryStateProvider, MemoryStateProvider } from 'mcp-app-view';
// Functional
const provider = createMemoryStateProvider({ counter: 0 });
// Class-based
const provider = new MemoryStateProvider({ counter: 0 });
// API
provider.getState();
provider.setState(newState);
provider.updateState(patch);
provider.subscribe((state, prevState) => {});
provider.reset();
provider.dispose();反应
useMcpApp
高级方便挂钩。
import { useMcpApp } from 'mcp-app-view/react';
function MyApp() {
const {
// Connection
isInitialized,
appInfo,
hostCapabilities,
hostContext,
// Tool state
tool, // { name, arguments, result, status, isStreaming }
// State management
state,
updateState,
setState,
// Actions
sendMessage,
openLink,
callTool,
reportSize,
// Utilities
getArgumentValue,
client,
} = useMcpApp({
initialState: { counter: 0 },
debug: false,
containerRef, // For auto size reporting
autoReportSize: true,
});
}useMcpProtocol
低级协议访问。
import { useMcpProtocol } from 'mcp-app-view/react';
function AdvancedApp() {
const {
isInitialized,
parentOrigin,
appInfo,
hostCapabilities,
hostContext,
// Raw messaging
sendRequest,
sendNotification,
sendResponse,
sendError,
// Event subscriptions
onInitialize,
onToolInputPartial,
onToolInput,
onToolResult,
onHostContextChanged,
onResourceTeardown,
} = useMcpProtocol({ debug: true });
}useMcpToolStream
细粒度工具流状态。
import { useMcpToolStream } from 'mcp-app-view/react';
function StreamingApp() {
const {
name,
arguments,
partialArguments,
result,
status, // 'idle' | 'streaming' | 'complete' | 'error' | 'teardown'
isStreaming,
getArgumentValue,
reset,
} = useMcpToolStream();
}McpApp & McpAppProvider
组件包装。
import { McpApp, McpAppProvider, useMcpAppContext } from 'mcp-app-view/react';
// Simple wrapper
function App() {
return (
);
}
// Provider pattern
function App() {
return (
console.log('Ready!')}
onToolResult={(result) => console.log('Done!')}
>
);
}
function MyWidget() {
const { state, updateState } = useMcpAppContext();
return
{state.counter}
;
}主机组件
McpProxyHost
在React应用程序中嵌入MCP应用程序。
import { McpProxyHost, McpProxyHostRef } from 'mcp-app-view/host';
function MyHost() {
const hostRef = useRef(null);
const handleToolCall = async (name: string, args?: Record) => {
if (name === 'get_data') {
return { data: 'Hello from host!' };
}
throw new Error(`Unknown tool: ${name}`);
};
// Send updates to the app
useEffect(() => {
hostRef.current?.sendToolInput({
tool: { name: 'process_data' },
arguments: { step: 1 },
});
}, []);
return (
{
console.log('Message from app:', params.content);
}}
onToolCall={handleToolCall}
onSizeChange={(size) => {
console.log('App size:', size);
}}
/>
);
}SEP-1865协议
此SDK实现了 SEP-1865 MCP应用程序规范.
Host → 应用消息
| 方法 | 类型 | 描述 |
|---|---|---|
ui/initialize | 请求 | 初始化应用程序 |
ui/notifications/tool-input-partial | 通知 | 流媒体工具参数 |
ui/notifications/tool-input | 通知 | 最终工具参数 |
ui/notifications/tool-result | 通知 | 工具结果 |
ui/tool-cancelled | 通知 | 工具已取消 |
ui/notifications/host-context-changed | 通知 | 上下文更新 |
ui/resource-teardown | 通知 | 清理 |
App → 主机消息
| 方法 | 类型 | 描述 |
|---|---|---|
ui/notifications/initialized | 通知 | 应用程序就绪 |
ui/notifications/size-change | 通知 | 大小更改 |
ui/open-link | 请求 | 打开URL |
ui/message | 请求 | 发送消息 |
tools/call | 请求 | 呼叫工具 |
贡献
我们欢迎捐款!请查看我们的 贡献指南.
关于BotDojo
BotDojo 是一个用于构建、运行和集成AI代理的平台。我们创建了这个SDK,以帮助开发人员与MCP建立丰富的交互体验。
- 🌐 网站
- 📖 文档
- 💬 Discord 的中文翻译是“不和谐”或“纷争”。
- 🐦 推特
许可证
MIT© BotDojo
