Skip to main content
Glama
2389-research

MCP Agent Social Media Server

error-handler.ts6.37 kB
// ABOUTME: Enhanced error handling with context enrichment and proper MCP error formatting // ABOUTME: Provides structured error responses and comprehensive error tracking import { logger } from '../logger.js'; // Custom error classes for better type safety export class McpValidationError extends Error { constructor( message: string, public details?: any, ) { super(message); this.name = 'McpValidationError'; } } export class McpAuthenticationError extends Error { constructor(message: string) { super(message); this.name = 'McpAuthenticationError'; } } export class McpRateLimitError extends Error { constructor( message: string, public retryAfter?: number, ) { super(message); this.name = 'McpRateLimitError'; } } export class McpTimeoutError extends Error { constructor( message: string, public timeout?: number, ) { super(message); this.name = 'McpTimeoutError'; } } export class McpMethodNotFoundError extends Error { constructor( message: string, public method?: string, ) { super(message); this.name = 'McpMethodNotFoundError'; } } export interface ErrorContext { sessionId: string; requestId: string; method: string; startTime: number; } export interface McpError { code: number; message: string; data?: any; } export class ErrorHandler { private errorCount = 0; private errorsByType = new Map<string, number>(); private errorsByMethod = new Map<string, number>(); /** * Handle and enrich errors with context */ async handleError(error: any, request: any, context: ErrorContext): Promise<Error> { this.errorCount++; const errorType = error.constructor.name; this.errorsByType.set(errorType, (this.errorsByType.get(errorType) || 0) + 1); this.errorsByMethod.set(context.method, (this.errorsByMethod.get(context.method) || 0) + 1); // Create enriched error const enrichedError = this.createEnrichedError(error, request, context); // Log error with context logger.error('Request processing error', { error: enrichedError.message, errorType, method: context.method, sessionId: context.sessionId, requestId: context.requestId, processingTime: Date.now() - context.startTime, originalError: error.message, stack: error.stack, }); return enrichedError; } /** * Create an enriched error with proper MCP formatting */ private createEnrichedError(error: any, request: any, context: ErrorContext): Error { let mcpError: McpError; // Handle known error types using proper type checking if (error.code && typeof error.code === 'number') { // Already an MCP error mcpError = { code: error.code, message: error.message, data: error.data, }; } else if (error instanceof McpValidationError) { mcpError = { code: -32602, // Invalid params message: 'Request validation failed', data: { originalMessage: error.message, details: error.details, }, }; } else if (error instanceof McpTimeoutError) { mcpError = { code: -32603, // Internal error message: 'Request timed out', data: { timeout: error.timeout, method: context.method, }, }; } else if (error instanceof McpMethodNotFoundError) { mcpError = { code: -32601, // Method not found message: 'Method not found', data: { method: error.method || request.method, }, }; } else if (error instanceof McpAuthenticationError) { mcpError = { code: -32600, // Invalid request message: 'Unauthorized request', data: { sessionId: context.sessionId, }, }; } else if (error instanceof McpRateLimitError) { mcpError = { code: -32603, // Internal error message: 'Rate limit exceeded', data: { retryAfter: error.retryAfter || 60, }, }; } else { // Generic internal error mcpError = { code: -32603, // Internal error message: 'Internal server error', data: { originalMessage: error.message, type: error.constructor.name, }, }; } // Create final error object const finalError = new Error(mcpError.message); (finalError as any).code = mcpError.code; (finalError as any).data = { ...mcpError.data, context: { sessionId: context.sessionId, requestId: context.requestId, method: context.method, timestamp: new Date().toISOString(), processingTime: Date.now() - context.startTime, }, }; return finalError; } /** * Format error for MCP response */ formatMcpError(error: any): McpError { return { code: error.code || -32603, message: error.message || 'Internal server error', data: error.data || null, }; } /** * Check if error is recoverable */ isRecoverableError(error: any): boolean { if (!error.code) return false; const recoverableCodes = [ -32602, // Invalid params - client can fix -32601, // Method not found - client can fix -32600, // Invalid request - client can fix ]; return recoverableCodes.includes(error.code); } /** * Get error statistics */ getStats() { return { totalErrors: this.errorCount, errorsByType: Object.fromEntries(this.errorsByType), errorsByMethod: Object.fromEntries(this.errorsByMethod), mostCommonError: this.getMostCommonError(), errorRate: this.errorCount, // This would be divided by total requests in a real system }; } /** * Get the most common error type */ private getMostCommonError(): string | null { if (this.errorsByType.size === 0) return null; let maxCount = 0; let mostCommon = ''; for (const [type, count] of this.errorsByType) { if (count > maxCount) { maxCount = count; mostCommon = type; } } return mostCommon; } /** * Clear error statistics */ clearStats(): void { this.errorCount = 0; this.errorsByType.clear(); this.errorsByMethod.clear(); logger.info('Error statistics cleared'); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/2389-research/mcp-socialmedia'

If you have feedback or need assistance with the MCP directory API, please join our Discord server