UNPKG

mushcode-mcp-server

Version:

A specialized Model Context Protocol server for MUSHCODE development assistance. Provides AI-powered code generation, validation, optimization, and examples for MUD development.

518 lines 18.5 kB
import { logger } from './logger.js'; /** * Error severity levels for classification */ export var ErrorSeverity; (function (ErrorSeverity) { ErrorSeverity["LOW"] = "low"; ErrorSeverity["MEDIUM"] = "medium"; ErrorSeverity["HIGH"] = "high"; ErrorSeverity["CRITICAL"] = "critical"; })(ErrorSeverity || (ErrorSeverity = {})); /** * Error categories for classification */ export var ErrorCategory; (function (ErrorCategory) { ErrorCategory["PROTOCOL"] = "protocol"; ErrorCategory["VALIDATION"] = "validation"; ErrorCategory["TOOL_EXECUTION"] = "tool_execution"; ErrorCategory["KNOWLEDGE_BASE"] = "knowledge_base"; ErrorCategory["PERFORMANCE"] = "performance"; ErrorCategory["SECURITY"] = "security"; ErrorCategory["CONFIGURATION"] = "configuration"; })(ErrorCategory || (ErrorCategory = {})); /** * Base class for all MUSHCODE MCP server errors */ export class MushcodeError extends Error { details; suggestions = []; userMessage; canRecover = false; constructor(message, userMessage, details, suggestions = []) { super(message); this.details = details; this.name = this.constructor.name; this.userMessage = userMessage || message; this.suggestions = suggestions; } /** * Add a suggestion for resolving this error */ addSuggestion(suggestion) { this.suggestions.push(suggestion); } /** * Get user-friendly error information */ getUserInfo() { return { message: this.userMessage, severity: this.severity, category: this.category, suggestions: this.suggestions, canRecover: this.canRecover }; } } /** * Protocol-level communication errors */ export class ProtocolError extends MushcodeError { code = 'INTERNAL_ERROR'; mcpErrorCode = -32603; severity = ErrorSeverity.HIGH; category = ErrorCategory.PROTOCOL; canRecover = false; constructor(message, details) { const userMessage = 'Communication error with the MCP server. Please check your connection and try again.'; const suggestions = [ { action: 'retry', description: 'Wait a moment and try your request again', }, { action: 'check_connection', description: 'Verify your IDE is properly connected to the MCP server', documentation: 'https://modelcontextprotocol.io/docs/concepts/clients' } ]; super(`Protocol error: ${message}`, userMessage, details, suggestions); } } /** * Input validation errors */ export class ValidationError extends MushcodeError { code = 'INVALID_PARAMS'; mcpErrorCode = -32602; severity = ErrorSeverity.MEDIUM; category = ErrorCategory.VALIDATION; canRecover = true; constructor(message, details) { const userMessage = 'Invalid input provided. Please check your parameters and try again.'; const suggestions = [ { action: 'check_parameters', description: 'Review the required parameters for this tool', }, { action: 'fix_input', description: 'Correct the invalid input and retry your request', } ]; // Add specific suggestions based on the error details if (details?.['missingParameter']) { suggestions.push({ action: 'add_parameter', description: `Add the required parameter: ${details['missingParameter']}`, example: `"${details['missingParameter']}": "your_value_here"` }); } if (details?.['expectedType'] && details?.['actualType']) { suggestions.push({ action: 'fix_type', description: `Change parameter type from ${details['actualType']} to ${details['expectedType']}`, example: `Expected: ${details['expectedType']}, Got: ${details['actualType']}` }); } super(`Validation error: ${message}`, userMessage, details, suggestions); } } /** * Tool execution errors */ export class ToolExecutionError extends MushcodeError { code = 'INTERNAL_ERROR'; mcpErrorCode = -32603; severity = ErrorSeverity.HIGH; category = ErrorCategory.TOOL_EXECUTION; canRecover = true; constructor(toolName, message, details) { const userMessage = `The ${toolName} tool encountered an error. Please try again with different parameters.`; const suggestions = [ { action: 'retry', description: 'Try your request again with the same parameters', }, { action: 'simplify_request', description: 'Try a simpler version of your request', }, { action: 'check_input', description: 'Verify your input parameters are correct and complete', } ]; // Add tool-specific suggestions switch (toolName) { case 'generate_mushcode': suggestions.push({ action: 'clarify_description', description: 'Provide a more detailed description of what you want to generate', example: 'Instead of "make a command", try "create a command that teleports a player to a specific room"' }); break; case 'validate_mushcode': suggestions.push({ action: 'check_syntax', description: 'Ensure the MUSHCODE you\'re validating has proper syntax', }); break; case 'optimize_mushcode': suggestions.push({ action: 'provide_context', description: 'Include more context about what the code should do', }); break; } super(`Tool execution error in ${toolName}: ${message}`, userMessage, details, suggestions); } } /** * Tool not found errors */ export class ToolNotFoundError extends MushcodeError { code = 'METHOD_NOT_FOUND'; mcpErrorCode = -32601; severity = ErrorSeverity.MEDIUM; category = ErrorCategory.VALIDATION; canRecover = true; constructor(toolName) { const userMessage = `The tool "${toolName}" is not available. Please check the tool name and try again.`; const suggestions = [ { action: 'check_tool_name', description: 'Verify you\'re using the correct tool name', }, { action: 'list_available_tools', description: 'Check which tools are available in your MCP client', } ]; // Add suggestions for common misspellings const availableTools = [ 'generate_mushcode', 'validate_mushcode', 'optimize_mushcode', 'explain_mushcode', 'get_examples', 'format_mushcode', 'compress_mushcode' ]; const similarTool = availableTools.find(tool => tool.toLowerCase().includes(toolName.toLowerCase()) || toolName.toLowerCase().includes(tool.toLowerCase())); if (similarTool) { suggestions.push({ action: 'use_correct_name', description: `Did you mean "${similarTool}"?`, example: similarTool }); } super(`Tool not found: ${toolName}`, userMessage, { toolName }, suggestions); } } /** * Knowledge base errors */ export class KnowledgeBaseError extends MushcodeError { code = 'INTERNAL_ERROR'; mcpErrorCode = -32603; severity = ErrorSeverity.MEDIUM; category = ErrorCategory.KNOWLEDGE_BASE; canRecover = true; constructor(message, details) { const userMessage = 'The knowledge base is temporarily unavailable or incomplete. The server will use fallback patterns.'; const suggestions = [ { action: 'retry_later', description: 'Try your request again in a few moments', }, { action: 'use_generic_patterns', description: 'The server will attempt to use generic MUSHCODE patterns', }, { action: 'specify_server_type', description: 'Try specifying a server type (PennMUSH, TinyMUSH, etc.) for better results', example: '"server_type": "PennMUSH"' } ]; super(`Knowledge base error: ${message}`, userMessage, details, suggestions); } } /** * Performance-related errors */ export class PerformanceError extends MushcodeError { code = 'INTERNAL_ERROR'; mcpErrorCode = -32603; severity = ErrorSeverity.MEDIUM; category = ErrorCategory.PERFORMANCE; canRecover = true; constructor(operation, timeout, details) { const userMessage = `The operation took too long to complete. Please try a simpler request.`; const suggestions = [ { action: 'simplify_request', description: 'Try breaking your request into smaller parts', }, { action: 'retry', description: 'Wait a moment and try again', }, { action: 'reduce_complexity', description: 'Use fewer parameters or a shorter description', } ]; super(`Performance error: ${operation} exceeded timeout of ${timeout}ms`, userMessage, { operation, timeout, ...details }, suggestions); } } /** * Security-related errors */ export class SecurityError extends MushcodeError { code = 'INTERNAL_ERROR'; mcpErrorCode = -32603; severity = ErrorSeverity.HIGH; category = ErrorCategory.SECURITY; canRecover = true; constructor(message, details) { const userMessage = 'Security concern detected in the request. Please review and modify your input.'; const suggestions = [ { action: 'review_input', description: 'Check your input for potentially unsafe patterns', }, { action: 'use_safe_patterns', description: 'Use established MUSHCODE security best practices', documentation: 'https://mushcode.com/security' }, { action: 'specify_security_level', description: 'Explicitly specify the required security level for your code', example: '"security_level": "player"' } ]; super(`Security error: ${message}`, userMessage, details, suggestions); } } /** * Configuration errors */ export class ConfigurationError extends MushcodeError { code = 'INTERNAL_ERROR'; mcpErrorCode = -32603; severity = ErrorSeverity.HIGH; category = ErrorCategory.CONFIGURATION; canRecover = false; constructor(message, details) { const userMessage = 'Server configuration error. Please contact your administrator.'; const suggestions = [ { action: 'contact_admin', description: 'Contact your system administrator for assistance', }, { action: 'check_config', description: 'Verify the MCP server configuration is correct', documentation: 'https://modelcontextprotocol.io/docs/concepts/servers' } ]; super(`Configuration error: ${message}`, userMessage, details, suggestions); } } /** * Graceful degradation manager */ export class GracefulDegradation { static degradationLevel = 0; static maxDegradationLevel = 3; /** * Check if we should degrade functionality */ static shouldDegrade() { return this.degradationLevel > 0; } /** * Get current degradation level */ static getDegradationLevel() { return this.degradationLevel; } /** * Increase degradation level */ static increaseDegradation() { if (this.degradationLevel < this.maxDegradationLevel) { this.degradationLevel++; } } /** * Reset degradation level */ static resetDegradation() { this.degradationLevel = 0; } /** * Get degradation options for current level */ static getDegradationOptions() { switch (this.degradationLevel) { case 1: return { skipOptionalFeatures: true }; case 2: return { skipOptionalFeatures: true, useGenericPatterns: true }; case 3: return { skipOptionalFeatures: true, useGenericPatterns: true, reduceComplexity: true, fallbackToBasicMode: true }; default: return {}; } } /** * Execute operation with graceful degradation */ static async executeWithDegradation(operation, fallback, _context) { try { return await operation(); } catch (error) { // Increase degradation level on failure this.increaseDegradation(); const options = this.getDegradationOptions(); try { return await fallback(options); } catch (fallbackError) { // If fallback also fails, throw the original error with degradation info if (error instanceof MushcodeError) { error.addSuggestion({ action: 'degraded_mode', description: `Server is operating in degraded mode (level ${this.degradationLevel})`, }); } throw error; } } } } /** * Enhanced error handling with user-friendly messages and logging */ export function handleError(error, context) { if (error instanceof MushcodeError) { // Log the error with context logger.error(`${error.category} error: ${error.message}`, error, { context, errorCode: error.code, severity: error.severity }); const userInfo = error.getUserInfo(); return { code: error.code, message: error.message, userMessage: userInfo.message, severity: userInfo.severity, category: userInfo.category, suggestions: userInfo.suggestions, canRecover: userInfo.canRecover, ...(error.details && { details: error.details }) }; } if (error instanceof Error) { // Log unknown errors logger.error(`Unknown error: ${error.message}`, error, { context }); return { code: 'INTERNAL_ERROR', message: error.message, userMessage: 'An unexpected error occurred. Please try again.', severity: ErrorSeverity.HIGH, category: ErrorCategory.TOOL_EXECUTION, suggestions: [ { action: 'retry', description: 'Try your request again' }, { action: 'contact_support', description: 'If the problem persists, contact support' } ], canRecover: true }; } // Log completely unknown errors logger.error(`Unknown error type: ${typeof error}`, undefined, { context, errorValue: error }); return { code: 'INTERNAL_ERROR', message: 'Unknown error occurred', userMessage: 'An unexpected error occurred. Please try again.', severity: ErrorSeverity.HIGH, category: ErrorCategory.TOOL_EXECUTION, suggestions: [ { action: 'retry', description: 'Try your request again' } ], canRecover: true }; } /** * Create user-friendly error response for MCP protocol */ export function createMCPErrorResponse(error, context) { const errorInfo = handleError(error, context); return { error: { code: error instanceof MushcodeError ? error.mcpErrorCode : -32603, message: errorInfo.message, data: { userMessage: errorInfo.userMessage, severity: errorInfo.severity, category: errorInfo.category, suggestions: errorInfo.suggestions, canRecover: errorInfo.canRecover, ...(errorInfo.details && { details: errorInfo.details }) } } }; } /** * Validate tool parameters against schema */ export function validateToolParameters(toolName, parameters, schema) { if (!parameters || typeof parameters !== 'object') { throw new ValidationError(`Invalid parameters for tool ${toolName}: expected object`); } // Basic validation - in a real implementation, you'd use a JSON schema validator const params = parameters; const schemaProps = schema['properties'] || {}; const required = schema['required'] || []; // Check required parameters for (const requiredParam of required) { if (!(requiredParam in params)) { throw new ValidationError(`Missing required parameter '${requiredParam}' for tool ${toolName}`, { toolName, missingParameter: requiredParam }); } } // Check parameter types (basic validation) for (const [paramName, paramValue] of Object.entries(params)) { if (paramName in schemaProps) { const paramSchema = schemaProps[paramName]; const expectedType = paramSchema['type']; if (expectedType && typeof paramValue !== expectedType && paramValue !== null) { throw new ValidationError(`Invalid type for parameter '${paramName}' in tool ${toolName}: expected ${expectedType}, got ${typeof paramValue}`, { toolName, parameter: paramName, expectedType, actualType: typeof paramValue }); } } } } //# sourceMappingURL=errors.js.map