ai-debug-local-mcp
Version:
🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
122 lines (103 loc) • 3.12 kB
JavaScript
const { chromium } = require('playwright');
let browser;
let pages = new Map();
// Cleanup handlers
process.on('SIGTERM', cleanup);
process.on('SIGINT', cleanup);
process.on('exit', cleanup);
async function cleanup() {
try {
// Close all pages
for (const [id, page] of pages) {
await page.close().catch(() => {});
}
pages.clear();
// Close browser
if (browser) {
await browser.close().catch(() => {});
}
} catch (error) {
// Ignore errors during cleanup
}
process.exit(0);
}
async function start() {
try {
browser = await chromium.launch({
headless: true,
// Limit browser resources and prevent AbortSignal accumulation
args: [
'--disable-gpu',
'--disable-dev-shm-usage',
'--disable-setuid-sandbox',
'--no-sandbox',
'--disable-web-security',
'--disable-features=site-per-process',
'--max_old_space_size=512', // Limit memory usage
'--disable-backgrounding-occluded-windows',
'--disable-background-timer-throttling'
]
});
// Browser doesn't have setDefaultTimeout, this is set per-page instead
console.log('READY');
} catch (error) {
console.error('Failed to start browser:', error);
process.exit(1);
}
}
async function createPage(url) {
const page = await browser.newPage();
const id = Date.now().toString();
// Set timeouts to prevent AbortSignal accumulation
page.setDefaultTimeout(30000);
page.setDefaultNavigationTimeout(30000);
pages.set(id, page);
if (url) {
await page.goto(url);
}
return id;
}
// Simple message protocol
process.stdin.on('data', async (data) => {
const message = data.toString().trim();
const [command, ...args] = message.split(' ');
try {
switch (command) {
case 'CREATE_PAGE':
const pageId = await createPage(args[0]);
console.log(`PAGE_CREATED ${pageId}`);
break;
case 'CLOSE_PAGE':
const page = pages.get(args[0]);
if (page) {
try {
// Clear any pending operations before closing
await page.close({ runBeforeUnload: false });
} catch (error) {
// Page might already be closed, ignore
console.debug(`Error closing page ${args[0]}:`, error.message);
}
pages.delete(args[0]);
console.log(`PAGE_CLOSED ${args[0]}`);
}
break;
case 'EXECUTE':
const pageForExec = pages.get(args[0]);
if (pageForExec) {
const scriptBase64 = args[1];
const script = Buffer.from(scriptBase64, 'base64').toString('utf8');
const result = await pageForExec.evaluate(script);
console.log(`RESULT ${JSON.stringify(result)}`);
} else {
console.log(`ERROR Page ${args[0]} not found`);
}
break;
default:
console.log(`UNKNOWN_COMMAND ${command}`);
}
} catch (error) {
console.log(`ERROR ${error.message}`);
}
});
// Start the browser
start().catch(console.error);