使用说明
WebSockets MCP数学演示
一个参考实现,展示了 模型上下文协议(MCP) 通过使用Cloudflare Workers和持久对象的WebSockets。
概述
此存储库提供了基于WebSockets的MCP的参考实现。它展示了:
- 完整的MCP客户端-服务器架构
- 通过持久对象持久化有状态会话
- WebSockets上的双向实时通信
- 工具发现和调用
- 使用Cloudflare Workers进行部署
技术概述
建筑
此项目演示了在WebSockets上使用客户端和服务器组件的完整MCP实现:
┌─────────────────┐ ┌─────────────────┐
│ │ │ │
│ MCP Client │◄───WebSocket───►│ MCP Server │
│ (CF Worker) │ │ (CF Worker) │
│ │ HTTP │ │
└─────────────────┘───────────────►└─────────────────┘
│
│ State Persistence
▼
┌─────────────────┐
│ Durable Object │
│ (MathAgent) │
│ │
└─────────────────┘
- 客户端:服务于HTML/JS客户端应用程序的Cloudflare Worker
- 服务器:使用工具端点实现MCP协议的Cloudflare Worker
- 耐用物品:维护每个代理会话的持久状态
WebSocket实现
该实现同时支持HTTP和WebSocket传输:
-
连接建立:
- 客户端通过HTTP POST创建代理
- 客户端建立WebSocket连接到
/agent/{agentId}/websocket - 服务器在持久对象中维护连接
-
消息格式:
// Client to Server { "type": "mcp_request", "request": { "method": "add", "params": { "a": 5, "b": 3 } } } // Server to Client { "type": "mcp_response", "result": { "result": 8, "operation": "add", "a": 5, "b": 3 }, "timestamp": "2023-05-01T12:34:56.789Z" } -
连接管理:
- 乒乓球心跳机制
- 自动重新连接
- 会话跟踪
入门指南
先决条件
安装
-
克隆此存储库:
git clone https://github.com/your-username/mcp-websockets-demo.git cd mcp-websockets-demo/math-mcp -
安装依赖项:
npm install -
部署服务器:
cd server wrangler deploy -
部署客户端:
cd ../client wrangler deploy -
请注意这两个worker的已部署URL,您需要它们才能使用应用程序。
用法
web界面
- 在浏览器中打开客户端URL。该界面允许您:
- 连接到MCP服务器
- 运行数学运算
- 查看WebSocket消息日志
程序化API
您还可以通过编程方式使用MCP服务器:
HTTP示例:
// Create an agent
const agentResponse = await fetch('https://your-server.workers.dev/agent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'MathAgent' })
});
const { agentId } = await agentResponse.json();
// Make an MCP request
const result = await fetch('https://your-server.workers.dev/mcp', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
agentId,
request: {
method: 'add',
params: { a: 5, b: 3 }
}
})
});
WebSocket示例:
// Create an agent first via HTTP (see above)
// Establish WebSocket connection
const ws = new WebSocket(`wss://your-server.workers.dev/agent/${agentId}/websocket`);
// Listen for messages
ws.addEventListener('message', (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
});
// Send an MCP request
ws.addEventListener('open', () => {
ws.send(JSON.stringify({
type: 'mcp_request',
request: {
method: 'add',
params: { a: 5, b: 3 }
}
}));
});
## WebSocket MCP Protocol Specification
This implementation proposes the following extensions to the MCP protocol for WebSocket support:
### 1. Transport Layer
The WebSocket transport extends MCP with these characteristics:
- **Bidirectional Communication**: Both client and server can initiate messages
- **Persistent Connection**: Long-lived connection reduces overhead
- **Real-time Updates**: Enables server-initiated notifications and streaming results
- **Reduced Latency**: Eliminates HTTP request overhead for frequent interactions
### 2. Message Envelope
All WebSocket messages are wrapped in an envelope with a `type` field:
```json
{
"type": "message_type",
"payload": { ... },
"timestamp": "ISO-8601 timestamp"
}
常见的消息类型包括:
mcp_request:客户端到服务器MCP方法调用mcp_response:服务器到客户端的响应ping/pong:连接健康检查error:错误通知notification:服务器发起的通知
3.连接生命周期
- 初始化:客户端在建立WebSocket之前通过HTTP创建代理
- 连接:客户端连接到特定于代理的WebSocket端点
- 心跳:客户端定期发送ping以保持连接
- 终止:任何一方都可以关闭连接
4.实施注意事项
在为MCP实现WebSocket支持时:
- 状态管理:处理重新连接和状态恢复
- 消息排序:实施排序以实现可靠的消息排序
- 错误处理:优雅地处理连接错误和消息失败
- 安全:应用与HTTP传输相同的身份验证机制
关键代码组件
以下是实现WebSocket MCP的关键组件:
服务器端WebSocket处理
// Handle WebSocket connections
async function handleWebSocketConnection(request, agentId, env) {
// Get Durable Object stub for the agent
const id = env.MATH_AGENT.idFromName(agentId);
const stub = env.MATH_AGENT.get(id);
// Forward the request to the Durable Object
return await stub.fetch(request);
}
// Durable Object implementation
export class MathAgent {
// Handle WebSocket connections
async handleWebSocketConnection(request) {
// Create a WebSocket pair
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
// Accept the WebSocket connection
server.accept();
// Set up event handlers for the WebSocket
server.addEventListener("message", async (event) => {
const message = JSON.parse(event.data);
// Handle different message types
if (message.type === "mcp_request") {
const result = await this.handleMcpRequest(message.request);
server.send(JSON.stringify({
type: "mcp_response",
result,
timestamp: new Date().toISOString()
}));
}
});
return new Response(null, {
status: 101,
webSocket: client
});
}
}
客户端WebSocket使用情况
// Connect WebSocket
function connectWebSocket(agentId, serverUrl) {
const ws = new WebSocket(`${serverUrl}/agent/${agentId}/websocket`);
ws.onopen = () => {
console.log('WebSocket connection established');
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
// Handle different message types
if (message.type === 'mcp_response') {
handleMcpResponse(message);
}
};
return ws;
}
// Send MCP request
function sendMcpRequest(ws, method, params) {
ws.send(JSON.stringify({
type: 'mcp_request',
request: {
method,
params
},
timestamp: new Date().toISOString()
}));
}
与TypeScript SDK集成
此参考实现可用于扩展 MCP TypeScript SDK 支持WebSocket:
import { MCPClient } from '@modelcontextprotocol/typescript-sdk';
// Create WebSocket transport
class WebSocketTransport implements MCPTransport {
private ws: WebSocket;
private pendingRequests: Map<string, {resolve, reject}>;
constructor(serverUrl: string, agentId: string) {
this.ws = new WebSocket(`${serverUrl}/agent/${agentId}/websocket`);
this.pendingRequests = new Map();
this.ws.addEventListener('message', this.handleMessage.bind(this));
}
async send(method: string, params: any): Promise<any> {
return new Promise((resolve, reject) => {
const requestId = crypto.randomUUID();
this.pendingRequests.set(requestId, { resolve, reject });
this.ws.send(JSON.stringify({
type: 'mcp_request',
request: { method, params },
requestId
}));
});
}
private handleMessage(event: MessageEvent) {
const message = JSON.parse(event.data);
if (message.type === 'mcp_response' && message.requestId) {
const pending = this.pendingRequests.get(message.requestId);
if (pending) {
pending.resolve(message.result);
this.pendingRequests.delete(message.requestId);
}
}
}
}
// Use transport with MCP client
const transport = new WebSocketTransport('wss://example.com', 'agent-123');
const client = new MCPClient({ transport });
// Use MCP methods as usual
const result = await client.invoke('add', { a: 5, b: 3 });
WebSocket MCP的优点
向MCP添加WebSocket支持提供了几个优点:
-
减少延迟:非常适合需要快速交互的环境
- 高频交易
- 实时协作环境
- 需要快速响应的交互式代理
-
双向通信:启用新的交互模式
- 服务器可以在没有客户端轮询的情况下推送更新
- 将大量响应分块流式传输
- 推送外部事件通知
-
减少网络开销:更有效地进行频繁通信
- 每个请求都没有HTTP标头开销
- 连接设置成本在多个请求中摊销
- 在移动网络上特别有用
-
有意义的会议:简化对话上下文的维护
- 服务器可以将状态与WebSocket连接相关联
- 客户端不需要为每个请求发送完整的上下文
- 更容易实现流式响应和部分更新
挑战和解决方案
WebSockets还引入了此实现所解决的挑战:
-
连接管理:
- 挑战:WebSockets可能会意外断开连接
- 解决方案:心跳机制和自动重新连接
-
无国籍工人:
- 挑战:Cloudflare Workers默认为无状态
- 解决方案:持久对象保持连接状态
-
请求/响应配对:
- 挑战:在共享通道上匹配对请求的响应
- 解决方案:邮件ID跟踪和关联
-
错误处理:
- 挑战:优雅地管理连接失败
- 解决方案:结构化错误响应和重新连接逻辑
贡献
欢迎投稿!请随时提交拉取请求。
许可证
此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。
