UNPKG

mcp-ai-agent-guidelines

Version:

A comprehensive Model Context Protocol server providing advanced tools, resources, and prompts for implementing AI agent best practices

276 lines 8.63 kB
/** * Centralized error handling utilities with typed errors for improved debugging and resilience */ import { ERROR_MESSAGES, isRetryable } from "./error-codes.js"; import { logger } from "./logger.js"; /** * MCP-aware error with standardized codes, retry hints, and response formatting. * @public */ export class McpToolError extends Error { code; context; timestamp; cause; constructor(code, message, context, cause) { super(message ?? ERROR_MESSAGES[code]); this.name = "McpToolError"; this.code = code; this.context = context ?? {}; this.timestamp = new Date(); this.cause = cause; if (Error.captureStackTrace) { Error.captureStackTrace(this, McpToolError); } } /** * Determines if this error is safe to retry based on its code category. */ isRetryable() { return isRetryable(this.code); } /** * Formats the error into an MCP-compatible response payload. */ toResponse() { return { isError: true, content: [ { type: "text", text: JSON.stringify({ error: this.name, code: this.code, message: this.message, context: this.context, retryable: this.isRetryable(), timestamp: this.timestamp.toISOString(), }, null, 2), }, ], }; } } /** * Session error for session-related issues */ export class SessionError extends Error { code; context; timestamp; constructor(message, context) { super(message); this.name = "SessionError"; this.code = "SESSION_ERROR"; this.context = context; this.timestamp = new Date(); if (Error.captureStackTrace) { Error.captureStackTrace(this, SessionError); } } } /** * Phase error for design phase workflow issues */ export class PhaseError extends Error { code; context; timestamp; constructor(message, context) { super(message); this.name = "PhaseError"; this.code = "PHASE_ERROR"; this.context = context; this.timestamp = new Date(); if (Error.captureStackTrace) { Error.captureStackTrace(this, PhaseError); } } } /** * Generation error for artifact generation failures */ export class GenerationError extends Error { code; context; timestamp; constructor(message, context) { super(message); this.name = "GenerationError"; this.code = "GENERATION_ERROR"; this.context = context; this.timestamp = new Date(); if (Error.captureStackTrace) { Error.captureStackTrace(this, GenerationError); } } } /** * Consistency error for consistency enforcement failures */ export class ConsistencyError extends Error { code; context; timestamp; constructor(message, context) { super(message); this.name = "ConsistencyError"; this.code = "CONSISTENCY_ERROR"; this.context = context; this.timestamp = new Date(); if (Error.captureStackTrace) { Error.captureStackTrace(this, ConsistencyError); } } } /** * Unknown error for unrecognized error types */ export class UnknownError extends Error { code; context; timestamp; constructor(message, context) { super(message); this.name = "UnknownError"; this.code = "UNKNOWN_ERROR"; this.context = context; this.timestamp = new Date(); if (Error.captureStackTrace) { Error.captureStackTrace(this, UnknownError); } } } /** * Type guard to check if an error has standard error properties */ function isStandardError(error) { return (error instanceof Error && "code" in error && typeof error.code === "string" && "timestamp" in error && error.timestamp instanceof Date); } /** * Centralized error reporter for consistent error handling */ // biome-ignore lint/complexity/noStaticOnlyClass: ErrorReporter is a utility namespace that provides static helper functions for error handling export class ErrorReporter { /** * Report and log an error, optionally rethrowing it */ static report(error, context, options) { const standardError = ErrorReporter.toStandardError(error, context, options?.defaultMessage); // Log the error logger.error(standardError.message, { code: standardError.code, context: standardError.context, stack: standardError.stack, }); // Optionally rethrow if (options?.rethrow) { throw standardError; } return standardError; } /** * Report a non-critical error as a warning */ static warn(error, context, defaultMessage) { const message = ErrorReporter.extractMessage(error, defaultMessage); logger.warn(message, { ...context, error: error instanceof Error ? error.stack : String(error), }); } /** * Convert any error to a StandardError */ static toStandardError(error, context, defaultMessage) { // Special case: McpToolError needs conversion since code is numeric if (error instanceof McpToolError) { // Create a SessionError with the McpToolError's message and code info const sessionError = new SessionError(error.message, { ...error.context, ...context, mcpErrorCode: error.code, retryable: error.isRetryable(), }); sessionError.stack = error.stack; return sessionError; } // If already a StandardError, preserve its type and merge context if (isStandardError(error)) { // If it already has all the context we need, return as-is if (!context || Object.keys(context).length === 0) { return error; } // Create a new error of the same type with merged context const ErrorConstructor = error.constructor; const newError = new ErrorConstructor(error.message, { ...error.context, ...context, }); newError.stack = error.stack; return newError; } // If a regular Error, convert it with UNKNOWN_ERROR code if (error instanceof Error) { const unknownError = new UnknownError(error.message, { ...context, originalError: error.name, }); unknownError.stack = error.stack; return unknownError; } // Unknown error type return new UnknownError(defaultMessage || "An unknown error occurred", { ...context, originalError: String(error), }); } /** * Extract error message from various error types */ static extractMessage(error, defaultMessage = "Unknown error") { if (error instanceof Error) { return error.message; } if (typeof error === "string") { return error; } return defaultMessage; } /** * Create a safe error response for API returns */ static createErrorResponse(error, context) { const standardError = ErrorReporter.toStandardError(error, context); return { success: false, error: { message: standardError.message, code: standardError.code, timestamp: standardError.timestamp.toISOString(), ...(standardError.context && { context: standardError.context }), }, }; } /** * Create a full error response with standard fields */ static createFullErrorResponse(error, baseResponse) { const standardError = ErrorReporter.toStandardError(error); return { success: false, sessionId: baseResponse.sessionId, status: baseResponse.status || "error", message: standardError.message, recommendations: baseResponse.recommendations || [ "Check request parameters and try again", ], artifacts: (baseResponse.artifacts || []), }; } } //# sourceMappingURL=errors.js.map