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
JavaScript
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