UNPKG

maplestory-mcp-server

Version:

Official-style NEXON MapleStory MCP Server for Claude Desktop - Complete character info, union details, guild data, rankings, and game mechanics

154 lines 6.01 kB
"use strict"; /** * Custom error classes for MCP Maple * Provides structured error handling for different failure scenarios */ Object.defineProperty(exports, "__esModule", { value: true }); exports.TimeoutError = exports.NetworkError = exports.ValidationError = exports.RateLimitError = exports.InvalidApiKeyError = exports.GuildNotFoundError = exports.CharacterNotFoundError = exports.NexonApiError = exports.McpMapleError = void 0; exports.createNexonApiError = createNexonApiError; exports.isRetryableError = isRetryableError; exports.getRetryDelay = getRetryDelay; exports.sanitizeErrorForLogging = sanitizeErrorForLogging; class McpMapleError extends Error { code; statusCode; context; constructor(message, code, statusCode, context) { super(message); this.code = code; this.statusCode = statusCode; this.context = context; this.name = 'McpMapleError'; Object.setPrototypeOf(this, McpMapleError.prototype); } toJSON() { return { name: this.name, message: this.message, code: this.code, statusCode: this.statusCode, context: this.context, stack: this.stack, }; } } exports.McpMapleError = McpMapleError; class NexonApiError extends McpMapleError { constructor(message, statusCode, endpoint, params) { super(message, 'NEXON_API_ERROR', statusCode, { endpoint, params }); this.name = 'NexonApiError'; Object.setPrototypeOf(this, NexonApiError.prototype); } } exports.NexonApiError = NexonApiError; class CharacterNotFoundError extends McpMapleError { constructor(characterName) { super(`Character '${characterName}' not found`, 'CHARACTER_NOT_FOUND', 404, { characterName }); this.name = 'CharacterNotFoundError'; Object.setPrototypeOf(this, CharacterNotFoundError.prototype); } } exports.CharacterNotFoundError = CharacterNotFoundError; class GuildNotFoundError extends McpMapleError { constructor(guildName, worldName) { super(`Guild '${guildName}' not found${worldName ? ` in world '${worldName}'` : ''}`, 'GUILD_NOT_FOUND', 404, { guildName, worldName }); this.name = 'GuildNotFoundError'; Object.setPrototypeOf(this, GuildNotFoundError.prototype); } } exports.GuildNotFoundError = GuildNotFoundError; class InvalidApiKeyError extends McpMapleError { constructor() { super('Invalid NEXON API key provided', 'INVALID_API_KEY', 401); this.name = 'InvalidApiKeyError'; Object.setPrototypeOf(this, InvalidApiKeyError.prototype); } } exports.InvalidApiKeyError = InvalidApiKeyError; class RateLimitError extends McpMapleError { constructor(retryAfter) { super('API rate limit exceeded', 'RATE_LIMIT_EXCEEDED', 429, { retryAfter }); this.name = 'RateLimitError'; Object.setPrototypeOf(this, RateLimitError.prototype); } } exports.RateLimitError = RateLimitError; class ValidationError extends McpMapleError { constructor(field, value, expectedType) { super(`Validation failed for field '${field}': ${value}${expectedType ? ` (expected ${expectedType})` : ''}`, 'VALIDATION_ERROR', 400, { field, value, expectedType }); this.name = 'ValidationError'; Object.setPrototypeOf(this, ValidationError.prototype); } } exports.ValidationError = ValidationError; class NetworkError extends McpMapleError { constructor(originalError) { super('Network request failed', 'NETWORK_ERROR', undefined, { originalError: originalError.message, }); this.name = 'NetworkError'; Object.setPrototypeOf(this, NetworkError.prototype); } } exports.NetworkError = NetworkError; class TimeoutError extends McpMapleError { constructor(timeout) { super(`Request timed out after ${timeout}ms`, 'TIMEOUT_ERROR', 408, { timeout }); this.name = 'TimeoutError'; Object.setPrototypeOf(this, TimeoutError.prototype); } } exports.TimeoutError = TimeoutError; // Error factory functions function createNexonApiError(statusCode, message, endpoint, params) { switch (statusCode) { case 401: return new InvalidApiKeyError(); case 404: if (endpoint?.includes('character')) { const characterName = params?.character_name || 'unknown'; return new CharacterNotFoundError(characterName); } if (endpoint?.includes('guild')) { const guildName = params?.guild_name || 'unknown'; const worldName = params?.world_name; return new GuildNotFoundError(guildName, worldName); } return new McpMapleError(message, 'NOT_FOUND', statusCode, { endpoint, params }); case 429: return new RateLimitError(); default: return new NexonApiError(message, statusCode, endpoint, params); } } // Error utilities function isRetryableError(error) { if (error instanceof NexonApiError) { // Retry on server errors and rate limits (with backoff) return error.statusCode ? error.statusCode >= 500 || error.statusCode === 429 : false; } if (error instanceof RateLimitError) { return true; } if (error instanceof NetworkError || error instanceof TimeoutError) { return true; } return false; } function getRetryDelay(attemptNumber, baseDelay = 1000) { // Exponential backoff with jitter const delay = baseDelay * Math.pow(2, attemptNumber - 1); const jitter = Math.random() * 0.1 * delay; return Math.min(delay + jitter, 30000); // Max 30 seconds } function sanitizeErrorForLogging(error) { if (error instanceof McpMapleError) { return error.toJSON(); } return { name: error.name || 'UnknownError', message: error.message || 'Unknown error occurred', stack: error.stack, }; } //# sourceMappingURL=errors.js.map