关于 WebSockets MCP Math Demo
这是一个使用 Cloudflare Workers 和 Durable Objects 实现 MCP WebSocket 通信的参考项目,面向探索双向、有状态 MCP 会话的开发者,包含客户端、服务端和数学运算演示。
主要功能
- 01MCP 客户端与服务端示例
- 02支持 HTTP 和 WebSocket 传输
- 03通过 Durable Objects 持久化会话
- 04双向实时消息通信
- 05工具发现与调用
- 06心跳检测和自动重连
适用场景
- 01原型验证有状态的 MCP WebSocket 传输
- 02探索客户端与服务端消息及工具调用
- 03在 Cloudflare Workers 上测试持久化 Agent 会话
- 04通过浏览器界面查看 WebSocket 消息
MCP 相关
演示通过 WebSocket 和 HTTP 进行 MCP 客户端与服务端通信,并支持工具发现和调用。服务端提供数学运算演示,Durable Objects 负责维护会话状态。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
WebSockets MCP 数学演示
使用 Cloudflare Workers 和 Durable Objects,通过 WebSockets 实现 Model Context Protocol (MCP) 的参考实现。
概述
此仓库提供了通过 WebSockets 实现 MCP 的参考实现,展示了:
- 完整的 MCP 客户端-服务端架构
- 通过 Durable Objects 实现的持久化有状态会话
- 通过 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
- Durable Objects:为每个 Agent 会话维护持久化状态
WebSocket 实现
此实现同时支持 HTTP 和 WebSocket 传输:
-
建立连接:
- 客户端通过 HTTP POST 创建 Agent
- 客户端与
/agent/{agentId}/websocket建立 WebSocket 连接 - 服务端在 Durable Object 中维护连接
-
消息格式:
// 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" } -
连接管理:
- Ping/pong 心跳机制
- 自动重新连接
- 会话跟踪
开始使用
前提条件
安装
-
克隆此仓库:
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. 连接生命周期
- 初始化:客户端先通过 HTTP 创建 Agent,再建立 WebSocket 连接
- 连接:客户端连接到 Agent 专属的 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 支持可带来多项优势:
-
更低的延迟:非常适用于需要快速交互的场景
- 高频交易
- 实时协作环境
- 需要快速响应的交互式 Agent
-
双向通信:支持全新的交互模式
- 服务端无需客户端轮询即可推送更新
- 以分块方式流式传输大型响应
- 针对外部事件的推送通知
-
降低网络开销:更适合频繁通信
- 每次请求都无需承担 HTTP 标头开销
- 多次请求可分摊连接建立成本
- 对移动网络尤其有帮助
-
有状态会话:简化对话上下文的维护
- 服务端可以将状态关联到 WebSocket 连接
- 客户端无需在每次请求中发送完整上下文
- 更容易实现流式响应和部分更新
挑战与解决方案
WebSocket 也会带来一些挑战,本实现对此进行了处理:
-
连接管理:
- 挑战:WebSocket 可能会意外断开连接
- 解决方案:心跳机制和自动重连
-
无状态工作器:
- 挑战:Cloudflare Workers 默认是无状态的
- 解决方案:Durable Objects 可维护连接状态
-
请求/响应配对:
- 挑战:在共享通道上匹配响应与请求
- 解决方案:跟踪消息 ID 并进行关联
-
错误处理:
- 挑战:妥善处理连接故障
- 解决方案:结构化错误响应和重连逻辑
贡献
欢迎贡献!请随时提交 Pull Request。
许可证
本项目采用 MIT License 许可,详情请参阅 LICENSE 文件。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。