Skip to main content
Glama

Klaviyo MCP Server

mcp_handler.js7.79 kB
/** * Enhanced MCP Error Handler * * This module provides improved error handling for MCP communication, * with special focus on JSON parsing errors that are being displayed to users. */ import logger from '../../utils/logger.js'; import { sanitizeJson, safeJsonParse } from './json_parser.js'; /** * Reads and processes a buffer in a safe manner that handles JSON errors gracefully * @param {ReadBuffer} readBuffer - The buffer to process * @param {Function} onmessage - Callback for valid messages */ function safeProcessBuffer(readBuffer, onmessage) { if (!readBuffer || typeof readBuffer.readMessage !== 'function') { return; } try { const message = readBuffer.readMessage(); if (message === null) { return null; } if (onmessage && typeof onmessage === 'function') { onmessage(message); } return message; } catch (error) { // This is where JSON parsing errors would occur if (error.message && ( error.message.includes('JSON') || error.message.includes('Unexpected token') || error.message.includes('Unexpected end of') || error.message.includes('non-whitespace character') )) { logger.debug('JSON error in buffer processing:', error); // Try to access the internal buffer directly for advanced recovery // This is risky but worth attempting if (readBuffer._buffer) { try { // Get the content as string const bufferContent = readBuffer._buffer.toString('utf8'); // Look for complete JSON objects const newlineIndex = bufferContent.indexOf('\n'); if (newlineIndex !== -1) { // Extract and try to sanitize the JSON const line = bufferContent.substring(0, newlineIndex); const sanitized = sanitizeJson(line); // If sanitization successful, try to parse if (sanitized !== line) { const parsed = safeJsonParse(sanitized); if (parsed) { // Skip past this message in the buffer readBuffer._buffer = readBuffer._buffer.subarray(newlineIndex + 1); logger.info('Successfully recovered from malformed JSON'); if (onmessage && typeof onmessage === 'function') { onmessage(parsed); } return parsed; } } } // If we can't recover, skip to the next newline to avoid getting // stuck on the same bad message if (newlineIndex !== -1) { logger.debug('Skipping malformed JSON message'); readBuffer._buffer = readBuffer._buffer.subarray(newlineIndex + 1); } else { // If no newline, clear the buffer completely as it might be corrupted logger.debug('Clearing potentially corrupted buffer'); readBuffer.clear(); } } catch (recoveryError) { logger.debug('Error during JSON recovery attempt:', recoveryError); // Last resort: clear the buffer readBuffer.clear(); } } return null; } // For non-JSON errors, re-throw throw error; } } /** * Enhanced version of the MCP transport patcher * @param {Object} transport - The StdioServerTransport instance to patch */ export function enhanceMcpTransport(transport) { if (!transport) { return; } // Add custom error handler transport.onerror = (error) => { if (error.message && ( error.message.includes('JSON') || error.message.includes('Unexpected token') || error.message.includes('Unexpected end of') || error.message.includes('non-whitespace character') )) { // For JSON parsing errors, just log at debug level and continue logger.debug('Suppressing JSON parsing error in MCP transport'); } else { // For other errors, log normally but don't crash logger.error('MCP transport error:', error); } }; // Create an enhanced version of the ReadBuffer's readMessage method if (transport._readBuffer) { const originalReadMessage = transport._readBuffer.readMessage.bind(transport._readBuffer); transport._readBuffer.readMessage = function() { try { return originalReadMessage(); } catch (error) { if (error.message && ( error.message.includes('JSON') || error.message.includes('Unexpected token') || error.message.includes('Unexpected end of') || error.message.includes('non-whitespace character') )) { // Get buffer content as string const bufferContent = this._buffer ? this._buffer.toString('utf8') : ''; // Try to sanitize the JSON before the first newline const newlineIndex = bufferContent.indexOf('\n'); if (newlineIndex !== -1) { const line = bufferContent.substring(0, newlineIndex); const sanitized = sanitizeJson(line); if (sanitized !== line) { // Try to parse the sanitized JSON try { const parsed = JSON.parse(sanitized); // If successful, advance the buffer past this message this._buffer = this._buffer.subarray(newlineIndex + 1); logger.debug('Successfully sanitized malformed JSON'); return parsed; } catch (parseError) { // If still can't parse, skip this message this._buffer = this._buffer.subarray(newlineIndex + 1); logger.debug('Skipping unparsable JSON message'); return null; } } else { // If sanitization didn't change anything, skip this message this._buffer = this._buffer.subarray(newlineIndex + 1); logger.debug('Skipping malformed JSON message (sanitization ineffective)'); return null; } } else { // No newline found, clear the buffer to avoid getting stuck this.clear(); logger.debug('Cleared buffer due to malformed JSON with no delimiter'); return null; } } // Re-throw non-JSON errors throw error; } }; } // Override the processReadBuffer method to add robust error handling if (typeof transport.processReadBuffer === 'function') { const originalProcessReadBuffer = transport.processReadBuffer.bind(transport); transport.processReadBuffer = function() { try { // Process messages in a loop until buffer is exhausted while (true) { // Use our safe processor instead of the standard one const message = safeProcessBuffer(this._readBuffer, this.onmessage?.bind(this)); // Exit the loop when there are no more complete messages if (message === null) { break; } } } catch (error) { if (error.message && ( error.message.includes('JSON') || error.message.includes('Unexpected token') || error.message.includes('Unexpected end of') || error.message.includes('non-whitespace character') )) { logger.debug('Handled JSON error in processReadBuffer'); } else { if (this.onerror) { this.onerror(error); } } } }; } return transport; } export default { enhanceMcpTransport, safeProcessBuffer };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ivan-rivera-projects/Klaviyo-MCP-Server-Enhanced'

If you have feedback or need assistance with the MCP directory API, please join our Discord server