@phqb/mcp-server
Version:
PHQB MCP Payment Server - AI-powered payment processing for Claude and other AI assistants
202 lines • 7.29 kB
JavaScript
"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