UNPKG

@cortexguardai/mcp

Version:

A Node.js-based MCP adapter for seamless integration with AI development environments.

213 lines 6.63 kB
/** * Logging utilities with configurable verbosity */ export class Logger { verbose; constructor(verbose = false) { this.verbose = verbose; } info(message, ...args) { console.error(`[INFO] ${message}`, ...args); } warn(message, ...args) { console.error(`[WARN] ${message}`, ...args); } error(message, ...args) { console.error(`[ERROR] ${message}`, ...args); } debug(message, ...args) { if (this.verbose) { console.error(`[DEBUG] ${message}`, ...args); } } setVerbose(verbose) { this.verbose = verbose; } } /** * Validation utilities */ export class Validator { static UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; static URL_REGEX = /^https?:\/\/.+/; static isValidUUID(uuid) { return typeof uuid === 'string' && this.UUID_REGEX.test(uuid); } static isValidURL(url) { if (typeof url !== 'string') return false; try { const parsed = new URL(url); return parsed.protocol === 'http:' || parsed.protocol === 'https:'; } catch { return false; } } static isValidTimeout(timeout) { return typeof timeout === 'number' && timeout > 0 && timeout <= 300000; // Max 5 minutes } static isValidToken(token) { return typeof token === 'string' && token.length > 0 && token.length <= 1000; } static validateConfig(config) { const errors = []; if (!this.isValidURL(config.serverUrl)) { errors.push('Invalid server URL format'); } if (!this.isValidToken(config.authToken)) { errors.push('Invalid auth token'); } if (!this.isValidTimeout(config.timeout)) { errors.push('Invalid timeout value (must be 1-300000ms)'); } return errors; } } /** * Content-Length framing utilities */ export class FramingUtils { static HEADER_SEPARATOR = '\r\n\r\n'; static LINE_SEPARATOR = '\r\n'; static frameMessage(content) { const contentBytes = Buffer.byteLength(content, 'utf8'); return `Content-Length: ${contentBytes}${this.HEADER_SEPARATOR}${content}`; } static parseFramedMessage(buffer) { const bufferStr = buffer.toString('utf8'); const headerEndIndex = bufferStr.indexOf(this.HEADER_SEPARATOR); if (headerEndIndex === -1) { // No complete header yet return null; } const headerSection = bufferStr.substring(0, headerEndIndex); const contentLengthMatch = headerSection.match(/^Content-Length: (\d+)$/m); if (!contentLengthMatch) { throw new Error('Invalid Content-Length header'); } const contentLength = parseInt(contentLengthMatch[1], 10); const messageStart = headerEndIndex + this.HEADER_SEPARATOR.length; const messageEnd = messageStart + contentLength; if (buffer.length < messageEnd) { // Incomplete message return null; } const messageBytes = buffer.subarray(messageStart, messageEnd); const message = messageBytes.toString('utf8'); const remaining = buffer.subarray(messageEnd); return { message, remaining }; } } /** * JSON utilities with error handling */ export class JsonUtils { static safeStringify(obj) { try { return JSON.stringify(obj); } catch (error) { throw new Error(`JSON stringify error: ${error}`); } } static safeParse(json) { try { return JSON.parse(json); } catch (error) { throw new Error(`JSON parse error: ${error}`); } } } /** * Error handling utilities */ export class ErrorUtils { static isNetworkError(error) { return (error && (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND' || error.code === 'ETIMEDOUT' || error.code === 'ECONNRESET')); } static isTimeoutError(error) { return (error && (error.code === 'ETIMEDOUT' || error.message?.includes('timeout'))); } static getErrorMessage(error) { if (typeof error === 'string') { return error; } if (error && error.message) { return error.message; } return 'Unknown error'; } static sanitizeError(error) { // Remove sensitive information from errors const sanitized = { ...error }; // Remove auth tokens from error messages if (sanitized.message) { sanitized.message = sanitized.message.replace(/Bearer [A-Za-z0-9._-]+/g, 'Bearer [REDACTED]'); } if (sanitized.config?.headers?.Authorization) { sanitized.config.headers.Authorization = '[REDACTED]'; } return sanitized; } } /** * Performance monitoring utilities */ export class PerfUtils { static timers = new Map(); static startTimer(name) { this.timers.set(name, Date.now()); } static endTimer(name) { const start = this.timers.get(name); if (!start) { throw new Error(`Timer '${name}' not found`); } const duration = Date.now() - start; this.timers.delete(name); return duration; } static measureAsync(name, fn) { this.startTimer(name); return fn().finally(() => { const duration = this.endTimer(name); console.error(`[PERF] ${name}: ${duration}ms`); }); } } /** * Retry utilities for network operations */ export class RetryUtils { static async withRetry(operation, maxRetries = 3, baseDelay = 1000) { let lastError; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await operation(); } catch (error) { lastError = error; if (attempt === maxRetries) { break; } // Only retry on network errors if (!ErrorUtils.isNetworkError(error)) { throw error; } // Exponential backoff with jitter const delay = baseDelay * Math.pow(2, attempt) + Math.random() * 1000; await new Promise(resolve => setTimeout(resolve, delay)); } } throw lastError; } } //# sourceMappingURL=utils.js.map