loader.js•3.31 kB
import { spawn } from 'child_process';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// Get current file directory (equivalent to __dirname in CommonJS)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Configure paths
const serverPath = path.resolve(__dirname, './serverMCP.js');
const logDir = path.resolve(__dirname, './logs');
const logFile = path.join(logDir, `mcp-debug-${new Date().toISOString().replace(/:/g, '-')}.log`);
// Ensure log directory exists
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
// Create log stream
const logger = fs.createWriteStream(logFile, { flags: 'a' });
// Log startup information
logger.write(`\n\n=== MCP DEBUG PROXY STARTED AT ${new Date().toISOString()} ===\n\n`);
console.error(`[PROXY] Starting debug proxy for ${serverPath}`);
console.error(`[PROXY] Logging to ${logFile}`);
// Spawn the real MCP server
const realServer = spawn('node', [serverPath], {
stdio: ['pipe', 'pipe', 'inherit'] // Redirect stderr to parent process
});
// Log messages with timestamp and direction
function logMessage(direction, data) {
const timestamp = new Date().toISOString();
const separator = '='.repeat(80);
try {
// Try to parse and pretty-print if it's JSON
const jsonData = JSON.parse(data.toString().trim());
const prettyJson = JSON.stringify(jsonData, null, 2);
logger.write(`\n${separator}\n[${timestamp}] ${direction}\n${separator}\n${prettyJson}\n`);
} catch (e) {
// If not JSON or parse error, log as raw string
const dataStr = data.toString().trim();
logger.write(`\n${separator}\n[${timestamp}] ${direction} (RAW)\n${separator}\n${dataStr}\n`);
}
}
// Intercept stdin (Claude -> Server)
process.stdin.on('data', (data) => {
logMessage('CLAUDE → SERVER', data);
// Forward to real server
if (!realServer.stdin.write(data)) {
process.stdin.pause();
realServer.stdin.once('drain', () => {
process.stdin.resume();
});
}
});
// Intercept stdout (Server -> Claude)
realServer.stdout.on('data', (data) => {
logMessage('SERVER → CLAUDE', data);
// Forward to Claude
if (!process.stdout.write(data)) {
realServer.stdout.pause();
process.stdout.once('drain', () => {
realServer.stdout.resume();
});
}
});
// Handle process events
realServer.on('exit', (code, signal) => {
logger.write(`\n\n=== SERVER EXITED (code: ${code}, signal: ${signal}) AT ${new Date().toISOString()} ===\n\n`);
console.error(`[PROXY] Server exited with code ${code} (signal: ${signal})`);
process.exit(code);
});
process.on('SIGINT', () => {
logger.write(`\n\n=== PROXY RECEIVED SIGINT AT ${new Date().toISOString()} ===\n\n`);
console.error(`[PROXY] Received SIGINT, shutting down`);
realServer.kill('SIGINT');
});
process.on('SIGTERM', () => {
logger.write(`\n\n=== PROXY RECEIVED SIGTERM AT ${new Date().toISOString()} ===\n\n`);
console.error(`[PROXY] Received SIGTERM, shutting down`);
realServer.kill('SIGTERM');
});
// Log uncaught exceptions to avoid crashes
process.on('uncaughtException', (err) => {
logger.write(`\n\n=== PROXY ERROR AT ${new Date().toISOString()} ===\n${err.stack}\n\n`);
console.error(`[PROXY] Uncaught exception:`, err);
});