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