UNPKG

@phqb/mcp-server

Version:

PHQB MCP Payment Server - AI-powered payment processing for Claude and other AI assistants

202 lines 7.29 kB
"use strict"; // MCP 权限验证模块 Object.defineProperty(exports, "__esModule", { value: true }); exports.MCPAuthManager = void 0; // 使用全局 fetch (Node.js 18+ 内置) const types_1 = require("./types"); class MCPAuthManager { constructor(apiKey, baseURL = 'https://www.phqb.com') { this.userValidation = null; this.callCounts = new Map(); this.apiKey = apiKey; this.baseURL = baseURL; } /** * 验证 API Key 并加载用户权限 */ async validateAndLoadPermissions() { try { const response = await fetch(`${this.baseURL}/api/keys/validate`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify({ context: 'mcp', timestamp: new Date().toISOString() }) }); if (!response.ok) { console.error(`API Key validation failed: ${response.status} ${response.statusText}`); return false; } const result = await response.json(); if (result.success && result.data) { this.userValidation = { valid: true, user_id: result.data.user_id, permissions: result.data.permissions || [], plan: result.data.plan || 'free', rate_limit: this.getRateLimitForPlan(result.data.plan || 'free') }; console.log(`✅ API Key validated for user ${this.userValidation.user_id} (${this.userValidation.plan} plan)`); return true; } console.error('API Key validation failed: Invalid response format'); return false; } catch (error) { console.error('API Key validation error:', error); return false; } } /** * 获取套餐对应的速率限制 */ getRateLimitForPlan(plan) { const limits = { free: { calls_per_hour: 10, calls_per_day: 50 }, pro: { calls_per_hour: 100, calls_per_day: 500 }, advanced: { calls_per_hour: -1, calls_per_day: -1 } // 无限制 }; return limits[plan] || limits.free; } /** * 获取用户可用的 MCP 工具列表 */ getAvailableTools() { if (!this.userValidation || !this.userValidation.permissions) { return []; } const availableTools = []; const userPermissions = this.userValidation.permissions; for (const [toolName, requiredPermissions] of Object.entries(types_1.MCP_TOOL_PERMISSIONS)) { // 检查用户是否拥有该工具所需的所有权限 const hasAllPermissions = requiredPermissions.every(permission => userPermissions.includes(permission)); if (hasAllPermissions) { availableTools.push(toolName); } } return availableTools; } /** * 验证工具调用权限 */ canUseTool(toolName) { if (!this.userValidation || !this.userValidation.permissions) { return false; } const requiredPermissions = types_1.MCP_TOOL_PERMISSIONS[toolName]; if (!requiredPermissions) { return false; } return requiredPermissions.every(permission => this.userValidation.permissions.includes(permission)); } /** * 检查速率限制 */ checkRateLimit() { if (!this.userValidation || !this.userValidation.rate_limit) { return false; } const { calls_per_hour, calls_per_day } = this.userValidation.rate_limit; // 无限制的情况 if (calls_per_hour === -1 && calls_per_day === -1) { return true; } const userId = this.userValidation.user_id; const now = new Date(); // 获取或初始化用户调用计数 let userCounts = this.callCounts.get(userId); if (!userCounts) { userCounts = { hour: 0, day: 0, lastReset: now }; this.callCounts.set(userId, userCounts); } // 重置计数器(如果需要) const hoursSinceReset = (now.getTime() - userCounts.lastReset.getTime()) / (1000 * 60 * 60); const daysSinceReset = hoursSinceReset / 24; if (hoursSinceReset >= 1) { userCounts.hour = 0; } if (daysSinceReset >= 1) { userCounts.day = 0; userCounts.lastReset = now; } // 检查限制 if (calls_per_hour !== -1 && userCounts.hour >= calls_per_hour) { return false; } if (calls_per_day !== -1 && userCounts.day >= calls_per_day) { return false; } return true; } /** * 记录 API 调用 */ recordAPICall() { if (!this.userValidation) return; const userId = this.userValidation.user_id; const userCounts = this.callCounts.get(userId); if (userCounts) { userCounts.hour++; userCounts.day++; } } /** * 验证工具调用(包含权限和速率限制检查) */ async validateToolCall(toolName) { // 检查认证状态 if (!this.userValidation) { throw new types_1.AuthenticationError('API Key not validated'); } // 检查工具权限 if (!this.canUseTool(toolName)) { const requiredPermissions = types_1.MCP_TOOL_PERMISSIONS[toolName] || []; throw new types_1.PermissionError(`权限不足。工具 "${toolName}" 需要以下权限: ${requiredPermissions.join(', ')}`); } // 检查速率限制 if (!this.checkRateLimit()) { const { calls_per_hour, calls_per_day } = this.userValidation.rate_limit; throw new types_1.RateLimitError(`调用频率超限。当前套餐限制: ${calls_per_hour}次/小时, ${calls_per_day}次/天`); } // 记录调用 this.recordAPICall(); } /** * 获取用户信息 */ getUserInfo() { return this.userValidation; } /** * 记录 MCP 工具使用日志 */ async logToolUsage(toolName, success, errorMessage, executionTime) { try { await fetch(`${this.baseURL}/api/mcp/logs`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.apiKey}` }, body: JSON.stringify({ tool_name: toolName, success, error_message: errorMessage, execution_time_ms: executionTime, timestamp: new Date().toISOString() }) }); } catch (error) { // 日志记录失败不应该影响主要功能 console.warn('Failed to log tool usage:', error); } } } exports.MCPAuthManager = MCPAuthManager; //# sourceMappingURL=auth.js.map