msexchange-mcp
Version:
MCP server for Microsoft Exchange/Outlook email operations via Microsoft Graph API
194 lines • 7.07 kB
JavaScript
/**
* Error classification and handling utilities
*/
export var ErrorType;
(function (ErrorType) {
ErrorType["AUTHENTICATION"] = "authentication";
ErrorType["NETWORK"] = "network";
ErrorType["API_LIMIT"] = "api_limit";
ErrorType["VALIDATION"] = "validation";
ErrorType["NOT_FOUND"] = "not_found";
ErrorType["PERMISSION"] = "permission";
ErrorType["SYNTAX"] = "syntax";
ErrorType["UNKNOWN"] = "unknown";
})(ErrorType || (ErrorType = {}));
/**
* Classify errors and provide actionable suggestions
*/
export function classifyError(error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const lowerMessage = errorMessage.toLowerCase();
// Authentication errors
if (lowerMessage.includes('unauthorized') ||
lowerMessage.includes('401') ||
lowerMessage.includes('authentication') ||
lowerMessage.includes('invalid token') ||
lowerMessage.includes('expired token')) {
return {
type: ErrorType.AUTHENTICATION,
message: 'Authentication failed',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Check if your credentials are valid',
'Try re-authenticating with the device code flow',
'Ensure your Azure AD app has the required permissions'
],
retryable: false
};
}
// Network errors
if (lowerMessage.includes('enotfound') ||
lowerMessage.includes('etimedout') ||
lowerMessage.includes('econnrefused') ||
lowerMessage.includes('network')) {
return {
type: ErrorType.NETWORK,
message: 'Network connection error',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Check your internet connection',
'Verify the Microsoft Graph API is accessible',
'Try again in a few moments'
],
retryable: true
};
}
// API rate limit errors
if (lowerMessage.includes('429') ||
lowerMessage.includes('rate limit') ||
lowerMessage.includes('too many requests')) {
return {
type: ErrorType.API_LIMIT,
message: 'API rate limit exceeded',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Wait a few minutes before retrying',
'Reduce the frequency of requests',
'Use smaller batch sizes for queries'
],
retryable: true
};
}
// Validation errors
if (lowerMessage.includes('invalid') ||
lowerMessage.includes('bad request') ||
lowerMessage.includes('400') ||
lowerMessage.includes('malformed')) {
return {
type: ErrorType.VALIDATION,
message: 'Invalid request parameters',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Check the format of your search query',
'Ensure email addresses are valid',
'Remove special characters from search terms',
'Use proper date formats (YYYY-MM-DD)'
],
retryable: false
};
}
// Not found errors
if (lowerMessage.includes('not found') ||
lowerMessage.includes('404') ||
lowerMessage.includes('does not exist')) {
return {
type: ErrorType.NOT_FOUND,
message: 'Resource not found',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Verify the email ID is correct',
'Check if the email was deleted',
'Ensure you have access to this mailbox'
],
retryable: false
};
}
// Permission errors
if (lowerMessage.includes('forbidden') ||
lowerMessage.includes('403') ||
lowerMessage.includes('permission') ||
lowerMessage.includes('access denied')) {
return {
type: ErrorType.PERMISSION,
message: 'Permission denied',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Check if you have the required permissions for this operation',
'Verify the Azure AD app has proper Graph API permissions',
'Contact your administrator for access'
],
retryable: false
};
}
// OData syntax errors
if (lowerMessage.includes('syntax') ||
lowerMessage.includes('odata') ||
lowerMessage.includes('filter') ||
lowerMessage.includes('restriction or sort order is too complex')) {
return {
type: ErrorType.SYNTAX,
message: 'Query syntax error',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Simplify your search query',
'Remove special characters from search terms',
'Use quotes for exact phrases',
'Try searching without date filters'
],
retryable: false
};
}
// Unknown errors
return {
type: ErrorType.UNKNOWN,
message: 'An unexpected error occurred',
originalError: error instanceof Error ? error : undefined,
suggestions: [
'Try again with a simpler query',
'Check the server logs for more details',
'Contact support if the issue persists'
],
retryable: true
};
}
/**
* Format error response for user display
*/
export function formatErrorResponse(classified) {
const parts = [
`❌ ${classified.message}`,
'',
'Suggestions:',
...classified.suggestions.map(s => `• ${s}`),
];
if (classified.retryable) {
parts.push('', '🔄 This error may be temporary. Please try again.');
}
if (process.env.DEBUG && classified.originalError) {
parts.push('', `Debug info: ${classified.originalError.message}`);
}
return parts.join('\n');
}
/**
* Retry with exponential backoff for retryable errors
*/
export async function retryWithBackoff(operation, maxRetries = 3, baseDelay = 1000) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await operation();
}
catch (error) {
lastError = error;
const classified = classifyError(error);
if (!classified.retryable || attempt === maxRetries - 1) {
throw error;
}
const delay = baseDelay * Math.pow(2, attempt);
console.error(`Retrying after ${delay}ms (attempt ${attempt + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}
//# sourceMappingURL=errorClassifier.js.map