--- title: WebHooks API description: 配置和管理 WebHook 事件通知的完整指南 --- # WebHooks API WebHooks 允许 MCPHub 在特定事件发生时向您的应用程序发送实时通知。 ## 概述 MCPHub WebHooks 系统支持以下功能: - 实时事件通知 - 自定义过滤器 - 重试机制 - 签名验证 - 批量事件处理 ## 支持的事件类型 | 事件类型 | 描述 | | ----------------------- | -------------- | | `server.created` | MCP 服务器创建 | | `server.updated` | MCP 服务器更新 | | `server.deleted` | MCP 服务器删除 | | `server.status_changed` | 服务器状态变更 | | `group.created` | 服务器组创建 | | `group.updated` | 服务器组更新 | | `group.deleted` | 服务器组删除 | | `user.login` | 用户登录 | | `user.logout` | 用户登出 | | `config.changed` | 配置变更 | | `system.error` | 系统错误 | ## 创建 WebHook ### 端点 ```http POST /api/webhooks ``` ### 请求体 ```json { "url": "https://your-app.com/webhook", "events": ["server.created", "server.status_changed"], "secret": "your-webhook-secret", "active": true, "config": { "contentType": "application/json", "insecureSsl": false, "retryCount": 3, "timeout": 30 }, "filters": { "serverGroups": ["production", "staging"], "serverTypes": ["ai-assistant", "data-processor"] } } ``` ### 响应 ```json { "success": true, "data": { "id": "webhook-123", "url": "https://your-app.com/webhook", "events": ["server.created", "server.status_changed"], "active": true, "secret": "your-webhook-secret", "config": { "contentType": "application/json", "insecureSsl": false, "retryCount": 3, "timeout": 30 }, "filters": { "serverGroups": ["production", "staging"], "serverTypes": ["ai-assistant", "data-processor"] }, "createdAt": "2024-01-15T10:30:00Z", "updatedAt": "2024-01-15T10:30:00Z" } } ``` ## 获取 WebHook 列表 ### 端点 ```http GET /api/webhooks ``` ### 查询参数 | 参数名 | 类型 | 描述 | | ------ | ------- | -------------------- | | page | integer | 页码(默认:1) | | limit | integer | 每页数量(默认:20) | | active | boolean | 过滤活跃状态 | | event | string | 过滤事件类型 | ### 请求示例 ```bash curl -X GET \ 'https://api.mcphub.io/api/webhooks?active=true&limit=10' \ -H 'Authorization: Bearer YOUR_API_TOKEN' ``` ### 响应 ```json { "success": true, "data": { "webhooks": [ { "id": "webhook-123", "url": "https://your-app.com/webhook", "events": ["server.created", "server.status_changed"], "active": true, "lastDelivery": "2024-01-15T09:30:00Z", "deliveryCount": 145, "failureCount": 2, "createdAt": "2024-01-10T10:30:00Z" } ], "pagination": { "page": 1, "limit": 10, "total": 25, "pages": 3 } } } ``` ## 获取单个 WebHook ### 端点 ```http GET /api/webhooks/{id} ``` ### 响应 ```json { "success": true, "data": { "id": "webhook-123", "url": "https://your-app.com/webhook", "events": ["server.created", "server.status_changed"], "active": true, "secret": "your-webhook-secret", "config": { "contentType": "application/json", "insecureSsl": false, "retryCount": 3, "timeout": 30 }, "filters": { "serverGroups": ["production", "staging"], "serverTypes": ["ai-assistant", "data-processor"] }, "stats": { "totalDeliveries": 145, "successfulDeliveries": 143, "failedDeliveries": 2, "lastDelivery": "2024-01-15T09:30:00Z", "lastSuccess": "2024-01-15T09:30:00Z", "lastFailure": "2024-01-14T15:20:00Z" }, "createdAt": "2024-01-10T10:30:00Z", "updatedAt": "2024-01-15T10:30:00Z" } } ``` ## 更新 WebHook ### 端点 ```http PUT /api/webhooks/{id} ``` ### 请求体 ```json { "url": "https://your-app.com/new-webhook", "events": ["server.created", "server.updated", "server.deleted"], "active": true, "config": { "retryCount": 5, "timeout": 45 } } ``` ## 删除 WebHook ### 端点 ```http DELETE /api/webhooks/{id} ``` ### 响应 ```json { "success": true, "message": "WebHook 已成功删除" } ``` ## WebHook 事件格式 ### 基本结构 所有 WebHook 事件都遵循以下基本结构: ```json { "id": "event-123", "type": "server.created", "timestamp": "2024-01-15T10:30:00Z", "version": "1.0", "data": { // 事件特定数据 }, "metadata": { "source": "mcphub", "environment": "production", "triggeredBy": "user-456" } } ``` ### 服务器事件示例 #### server.created ```json { "id": "event-123", "type": "server.created", "timestamp": "2024-01-15T10:30:00Z", "version": "1.0", "data": { "server": { "id": "mcp-server-123", "name": "AI Assistant Server", "type": "ai-assistant", "endpoint": "https://ai-assistant.example.com", "group": "production", "status": "active", "capabilities": ["chat", "completion"], "createdAt": "2024-01-15T10:30:00Z" } }, "metadata": { "source": "mcphub", "environment": "production", "triggeredBy": "user-456" } } ``` #### server.status_changed ```json { "id": "event-124", "type": "server.status_changed", "timestamp": "2024-01-15T11:30:00Z", "version": "1.0", "data": { "server": { "id": "mcp-server-123", "name": "AI Assistant Server", "previousStatus": "active", "currentStatus": "inactive", "reason": "Health check failed", "lastHealthCheck": "2024-01-15T11:25:00Z" } }, "metadata": { "source": "mcphub", "environment": "production", "triggeredBy": "system" } } ``` ## 签名验证 MCPHub 使用 HMAC-SHA256 签名来验证 WebHook 的真实性。 ### 签名生成 签名在 `X-MCPHub-Signature-256` 头中发送: ``` X-MCPHub-Signature-256: sha256=5757107ea39eca8e35d1e8... ``` ### 验证示例 #### Node.js ```javascript const crypto = require('crypto'); function verifySignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); const actualSignature = signature.replace('sha256=', ''); return crypto.timingSafeEqual( Buffer.from(expectedSignature, 'hex'), Buffer.from(actualSignature, 'hex'), ); } // Express.js 中间件示例 app.use('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-mcphub-signature-256']; const payload = req.body; if (!verifySignature(payload, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send('Unauthorized'); } // 处理 WebHook 事件 const event = JSON.parse(payload); console.log('收到事件:', event.type); res.status(200).send('OK'); }); ``` #### Python ```python import hmac import hashlib def verify_signature(payload, signature, secret): expected_signature = hmac.new( secret.encode('utf-8'), payload, hashlib.sha256 ).hexdigest() actual_signature = signature.replace('sha256=', '') return hmac.compare_digest(expected_signature, actual_signature) # Flask 示例 from flask import Flask, request, jsonify import json app = Flask(__name__) @app.route('/webhook', methods=['POST']) def webhook(): signature = request.headers.get('X-MCPHub-Signature-256') payload = request.get_data() if not verify_signature(payload, signature, 'your-webhook-secret'): return jsonify({'error': 'Unauthorized'}), 401 event = json.loads(payload) print(f'收到事件: {event["type"]}') return jsonify({'status': 'success'}), 200 ``` ## 重试机制 MCPHub 对失败的 WebHook 交付实施指数退避重试: - **重试次数**: 可配置(默认 3 次) - **重试间隔**: 2^n 秒(n 为重试次数) - **最大间隔**: 300 秒(5 分钟) - **超时设置**: 可配置(默认 30 秒) ### 重试时间表 | 尝试次数 | 延迟时间 | | -------- | -------- | | 1 | 立即 | | 2 | 2 秒 | | 3 | 4 秒 | | 4 | 8 秒 | | 5 | 16 秒 | ## 获取交付历史 ### 端点 ```http GET /api/webhooks/{id}/deliveries ``` ### 查询参数 | 参数名 | 类型 | 描述 | | ---------- | ------- | ------------------------------------ | | page | integer | 页码 | | limit | integer | 每页数量 | | status | string | 过滤状态(success, failed, pending) | | event_type | string | 过滤事件类型 | ### 响应 ```json { "success": true, "data": { "deliveries": [ { "id": "delivery-123", "eventId": "event-123", "eventType": "server.created", "url": "https://your-app.com/webhook", "status": "success", "responseCode": 200, "responseTime": 145, "attempts": 1, "deliveredAt": "2024-01-15T10:30:15Z", "nextRetry": null }, { "id": "delivery-124", "eventId": "event-124", "eventType": "server.status_changed", "url": "https://your-app.com/webhook", "status": "failed", "responseCode": 500, "responseTime": 30000, "attempts": 3, "error": "Connection timeout", "deliveredAt": null, "nextRetry": "2024-01-15T11:45:00Z" } ], "pagination": { "page": 1, "limit": 20, "total": 145, "pages": 8 } } } ``` ## 测试 WebHook ### 端点 ```http POST /api/webhooks/{id}/test ``` ### 请求体 ```json { "eventType": "server.created", "customData": { "test": true, "message": "这是一个测试事件" } } ``` ### 响应 ```json { "success": true, "data": { "deliveryId": "delivery-test-123", "status": "delivered", "responseCode": 200, "responseTime": 124, "sentAt": "2024-01-15T10:30:00Z" } } ``` ## 最佳实践 ### 1. 幂等性处理 确保您的 WebHook 端点能够处理重复事件: ```javascript const processedEvents = new Set(); app.post('/webhook', (req, res) => { const event = req.body; // 检查事件是否已处理 if (processedEvents.has(event.id)) { return res.status(200).send('Already processed'); } // 处理事件 processEvent(event); // 记录已处理的事件 processedEvents.add(event.id); res.status(200).send('OK'); }); ``` ### 2. 异步处理 对于复杂的处理逻辑,使用异步处理避免阻塞: ```javascript app.post('/webhook', async (req, res) => { const event = req.body; // 立即响应 res.status(200).send('OK'); // 异步处理事件 setImmediate(() => { processEventAsync(event); }); }); ``` ### 3. 错误处理 实施适当的错误处理和日志记录: ```javascript app.post('/webhook', (req, res) => { try { const event = req.body; processEvent(event); res.status(200).send('OK'); } catch (error) { console.error('WebHook 处理错误:', error); res.status(500).send('Internal Server Error'); } }); ``` ### 4. 监控和告警 监控 WebHook 的交付状态: ```bash # 检查失败的交付 curl -X GET \ 'https://api.mcphub.io/api/webhooks/webhook-123/deliveries?status=failed' \ -H 'Authorization: Bearer YOUR_API_TOKEN' ``` ## 故障排除 ### 常见问题 1. **签名验证失败** - 检查密钥是否正确 - 确保使用原始请求体进行验证 - 验证 HMAC 计算实现 2. **超时错误** - 增加 WebHook 超时设置 - 优化端点响应时间 - 使用异步处理 3. **重复事件** - 实施幂等性检查 - 使用事件 ID 去重 - 记录处理状态 ### 调试工具 使用 MCPHub 提供的调试工具: ```bash # 查看最近的交付日志 curl -X GET \ 'https://api.mcphub.io/api/webhooks/webhook-123/deliveries?limit=5' \ -H 'Authorization: Bearer YOUR_API_TOKEN' # 重新发送失败的事件 curl -X POST \ 'https://api.mcphub.io/api/webhooks/delivery-124/redeliver' \ -H 'Authorization: Bearer YOUR_API_TOKEN' ```