WebSockets MCP Math Demo
使用持久对象进行状态跟踪的 MCP 客户端/服务器演示
dinasaur404
README
WebSockets MCP 数学演示
一个参考实现,演示了通过 Cloudflare Workers 和 Durable Objects 在 WebSockets 上使用 模型上下文协议 (MCP)。
概述
此存储库提供了一个通过 WebSockets 实现 MCP 的参考实现。它展示了:
- 完整的 MCP 客户端-服务器架构
- 通过 Durable Objects 实现持久的有状态会话
- 通过 WebSockets 实现双向实时通信
- 工具发现和调用
- 使用 Cloudflare Workers 进行部署
技术概述
架构
此项目演示了一个完整的通过 WebSockets 实现的 MCP,包含客户端和服务器组件:
┌─────────────────┐ ┌─────────────────┐
│ │ │ │
│ MCP 客户端 │◄───WebSocket───►│ MCP 服务器 │
│ (CF Worker) │ │ (CF Worker) │
│ │ HTTP │ │
└─────────────────┘───────────────►└─────────────────┘
│
│ 状态持久化
▼
┌─────────────────┐
│ Durable Object │
│ (MathAgent) │
│ │
└─────────────────┘
- 客户端: 一个 Cloudflare Worker,用于提供 HTML/JS 客户端应用程序
- 服务器: 一个 Cloudflare Worker,使用工具端点实现 MCP 协议
- Durable Objects: 为每个代理会话维护持久状态
WebSocket 实现
该实现支持 HTTP 和 WebSocket 传输:
-
连接建立:
- 客户端通过 HTTP POST 创建一个代理
- 客户端建立到
/agent/{agentId}/websocket
的 WebSocket 连接 - 服务器在 Durable Object 中维护连接
-
消息格式:
// 客户端到服务器 { "type": "mcp_request", "request": { "method": "add", "params": { "a": 5, "b": 3 } } } // 服务器到客户端 { "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 示例:
// 创建一个代理
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();
// 发送 MCP 请求
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 示例:
// 首先通过 HTTP 创建一个代理 (见上文)
// 建立 WebSocket 连接
const ws = new WebSocket(`wss://your-server.workers.dev/agent/${agentId}/websocket`);
// 监听消息
ws.addEventListener('message', (event) => {
const message = JSON.parse(event.data);
console.log('Received:', message);
});
// 发送 MCP 请求
ws.addEventListener('open', () => {
ws.send(JSON.stringify({
type: 'mcp_request',
request: {
method: 'add',
params: { a: 5, b: 3 }
}
}));
});
## WebSocket MCP 协议规范
此实现提出了以下针对 WebSocket 支持的 MCP 协议扩展:
### 1. 传输层
WebSocket 传输通过以下特性扩展了 MCP:
- **双向通信**: 客户端和服务器都可以发起消息
- **持久连接**: 长时间连接减少了开销
- **实时更新**: 启用服务器发起的通知和流式传输结果
- **降低延迟**: 消除频繁交互的 HTTP 请求开销
### 2. 消息信封
所有 WebSocket 消息都封装在一个带有 `type` 字段的信封中:
```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 处理
// 处理 WebSocket 连接
async function handleWebSocketConnection(request, agentId, env) {
// 获取代理的 Durable Object stub
const id = env.MATH_AGENT.idFromName(agentId);
const stub = env.MATH_AGENT.get(id);
// 将请求转发到 Durable Object
return await stub.fetch(request);
}
// Durable Object 实现
export class MathAgent {
// 处理 WebSocket 连接
async handleWebSocketConnection(request) {
// 创建一个 WebSocket 对
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
// 接受 WebSocket 连接
server.accept();
// 为 WebSocket 设置事件处理程序
server.addEventListener("message", async (event) => {
const message = JSON.parse(event.data);
// 处理不同的消息类型
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 用法
// 连接 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);
// 处理不同的消息类型
if (message.type === 'mcp_response') {
handleMcpResponse(message);
}
};
return ws;
}
// 发送 MCP 请求
function sendMcpRequest(ws, method, params) {
ws.send(JSON.stringify({
type: 'mcp_request',
request: {
method,
params
},
timestamp: new Date().toISOString()
}));
}
与 TypeScript SDK 集成
此参考实现可用于使用 WebSocket 支持扩展 MCP TypeScript SDK:
import { MCPClient } from '@modelcontextprotocol/typescript-sdk';
// 创建 WebSocket 传输
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);
}
}
}
}
// 将传输与 MCP 客户端一起使用
const transport = new WebSocketTransport('wss://example.com', 'agent-123');
const client = new MCPClient({ transport });
// 像往常一样使用 MCP 方法
const result = await client.invoke('add', { a: 5, b: 3 });
WebSocket MCP 的优势
向 MCP 添加 WebSocket 支持具有以下几个优势:
-
更低的延迟: 非常适合需要快速交互的上下文
- 高频交易
- 实时协作环境
- 需要快速响应的交互式代理
-
双向通信: 启用新的交互模式
- 服务器可以推送更新,而无需客户端轮询
- 以块的形式流式传输大型响应
- 外部事件的推送通知
-
减少网络开销: 对于频繁通信更有效
- 每个请求没有 HTTP 标头开销
- 连接设置成本在多个请求中分摊
- 在移动网络上尤其有用
-
有状态会话: 简化了维护对话上下文
- 服务器可以将状态与 WebSocket 连接关联
- 客户端无需在每个请求中发送完整上下文
- 更容易实现流式传输响应和部分更新
挑战与解决方案
WebSockets 也引入了此实现解决的挑战:
-
连接管理:
- 挑战: WebSockets 可能会意外断开连接
- 解决方案: 心跳机制和自动重新连接
-
无状态 Workers:
- 挑战: Cloudflare Workers 默认是无状态的
- 解决方案: Durable Objects 维护连接状态
-
请求/响应配对:
- 挑战: 在共享通道上将响应与请求匹配
- 解决方案: 消息 ID 跟踪和关联
-
错误处理:
- 挑战: 优雅地管理连接失败
- 解决方案: 结构化错误响应和重新连接逻辑
贡献
欢迎贡献!请随时提交 Pull Request。
许可证
此项目已获得 MIT 许可证的许可 - 有关详细信息,请参阅 LICENSE 文件。
推荐服务器
Crypto Price & Market Analysis MCP Server
一个模型上下文协议 (MCP) 服务器,它使用 CoinCap API 提供全面的加密货币分析。该服务器通过一个易于使用的界面提供实时价格数据、市场分析和历史趋势。 (Alternative, slightly more formal and technical translation): 一个模型上下文协议 (MCP) 服务器,利用 CoinCap API 提供全面的加密货币分析服务。该服务器通过用户友好的界面,提供实时价格数据、市场分析以及历史趋势数据。
MCP PubMed Search
用于搜索 PubMed 的服务器(PubMed 是一个免费的在线数据库,用户可以在其中搜索生物医学和生命科学文献)。 我是在 MCP 发布当天创建的,但当时正在度假。 我看到有人在您的数据库中发布了类似的服务器,但还是决定发布我的服务器。
mixpanel
连接到您的 Mixpanel 数据。 从 Mixpanel 分析查询事件、留存和漏斗数据。

Sequential Thinking MCP Server
这个服务器通过将复杂问题分解为顺序步骤来促进结构化的问题解决,支持修订,并通过完整的 MCP 集成来实现多条解决方案路径。

Nefino MCP Server
为大型语言模型提供访问德国可再生能源项目新闻和信息的能力,允许按地点、主题(太阳能、风能、氢能)和日期范围进行筛选。
Vectorize
将 MCP 服务器向量化以实现高级检索、私有深度研究、Anything-to-Markdown 文件提取和文本分块。
Mathematica Documentation MCP server
一个服务器,通过 FastMCP 提供对 Mathematica 文档的访问,使用户能够从 Wolfram Mathematica 检索函数文档和列出软件包符号。
kb-mcp-server
一个 MCP 服务器,旨在实现便携性、本地化、简易性和便利性,以支持对 txtai “all in one” 嵌入数据库进行基于语义/图的检索。任何 tar.gz 格式的 txtai 嵌入数据库都可以被加载。
Research MCP Server
这个服务器用作 MCP 服务器,与 Notion 交互以检索和创建调查数据,并与 Claude Desktop Client 集成以进行和审查调查。

Cryo MCP Server
一个API服务器,实现了模型补全协议(MCP),用于Cryo区块链数据提取,允许用户通过任何兼容MCP的客户端查询以太坊区块链数据。