Skip to main content
Glama

Token Saver MCP

by jerry426
debug-javascript-error.ts8.27 kB
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js' import type { ToolMetadata } from '../types' import { z } from 'zod' import { ensureCDPConnection } from '../../browser-functions' const logger = { info: console.error, error: console.error, warn: console.warn } export const metadata: ToolMetadata = { name: 'debug_javascript_error', title: 'Debug JavaScript Error', category: 'helper', description: 'Complete JavaScript error debugging and analysis workflow with stack trace analysis and fix recommendations', docs: { brief: 'Complete JavaScript error debugging and analysis workflow', testsAutomatically: [ 'Runtime error capture and stack traces', 'Console error collection and categorization', 'Unhandled promise rejection detection', 'Error source file identification', 'Framework-specific error patterns', 'Memory usage during errors', 'Source map availability', 'Environment debugging features', ], savesTimeVsManual: [ 'No need to manually monitor console constantly', 'Automatically captures all error types', 'Categorizes errors by common patterns', 'Identifies error source files', 'Provides debugging recommendations', 'Checks for debugging tool availability', ], integrationWorkflows: [ 'Debug production errors efficiently', 'Identify error patterns during development', 'Validate error handling improvements', 'Test error boundary implementations', 'Monitor application stability', 'Automated error reporting', ], exampleUsage: `debug_javascript_error({ url: "http://localhost:3000/broken-page", triggerAction: "document.getElementById('buggy-button').click()", waitBeforeTrigger: 2000 })`, }, } // Tool handler - single source of truth for execution export async function handler({ url, triggerAction, waitBeforeTrigger = 1000 }: any): Promise<any> { try { const client = await ensureCDPConnection() // Set up error capture before navigation await client.execute(` window.__capturedErrors = []; window.__originalError = window.onerror; window.onerror = function(msg, source, lineno, colno, error) { window.__capturedErrors.push({ message: msg, source: source, line: lineno, column: colno, stack: error ? error.stack : 'No stack trace', timestamp: Date.now() }); if (window.__originalError) { return window.__originalError.apply(this, arguments); } return false; }; window.addEventListener('unhandledrejection', function(event) { window.__capturedErrors.push({ message: 'Unhandled Promise Rejection: ' + event.reason, stack: event.reason && event.reason.stack ? event.reason.stack : 'No stack trace', timestamp: Date.now(), type: 'promise' }); }); `) await client.navigate(url) await new Promise(resolve => setTimeout(resolve, waitBeforeTrigger)) // Clear console to capture fresh errors client.clearConsoleMessages() // Trigger the error if action provided if (triggerAction) { try { await client.execute(triggerAction) } catch (triggerError: any) { // This is expected - we're triggering an error logger.info('Trigger resulted in error (expected):', triggerError.message) } } // Wait for errors to be captured await new Promise(resolve => setTimeout(resolve, 500)) // Collect all errors const capturedErrors = await client.execute('window.__capturedErrors || []') const consoleErrors = client.getConsoleMessages ? client.getConsoleMessages('error') : [] // Analyze errors const analysis = await client.execute(` (() => { const errors = window.__capturedErrors || []; const analysis = { errorTypes: {}, commonPatterns: [], affectedFiles: new Set(), suggestions: [] }; errors.forEach(err => { // Categorize error types if (err.message.includes('undefined')) { analysis.errorTypes.undefined = (analysis.errorTypes.undefined || 0) + 1; analysis.suggestions.push('Check for undefined variables or properties'); } if (err.message.includes('null')) { analysis.errorTypes.null = (analysis.errorTypes.null || 0) + 1; analysis.suggestions.push('Add null checks before accessing properties'); } if (err.message.includes('TypeError')) { analysis.errorTypes.typeError = (analysis.errorTypes.typeError || 0) + 1; analysis.suggestions.push('Verify data types and method availability'); } if (err.message.includes('ReferenceError')) { analysis.errorTypes.referenceError = (analysis.errorTypes.referenceError || 0) + 1; analysis.suggestions.push('Check variable declarations and scope'); } // Extract file from stack const stackLines = (err.stack || '').split('\\n'); stackLines.forEach(line => { const match = line.match(/\\(([^:)]+):/); if (match && !match[1].includes('node_modules')) { analysis.affectedFiles.add(match[1]); } }); }); analysis.affectedFiles = Array.from(analysis.affectedFiles); analysis.suggestions = [...new Set(analysis.suggestions)]; // Check for common issues const hasReact = !!window.React; const hasVue = !!window.Vue; const hasAngular = !!window.angular; return { errorCount: errors.length, analysis, framework: { react: hasReact, vue: hasVue, angular: hasAngular }, debugging: { hasSourceMaps: document.querySelector('script[src*=".map"]') !== null, strictMode: (function() { return !this; })(), } }; })() `) return { content: [{ type: 'text', text: JSON.stringify({ success: true, errors: { captured: capturedErrors, console: consoleErrors.map((e: any) => ({ text: e.text, url: e.url, line: e.line, })), total: capturedErrors.length + consoleErrors.length, }, analysis: analysis.analysis, environment: { framework: analysis.framework, debugging: analysis.debugging, }, recommendations: [ ...analysis.analysis.suggestions, capturedErrors.length > 5 ? 'Multiple errors detected - check initialization order' : null, analysis.debugging.hasSourceMaps ? null : 'Enable source maps for better debugging', ].filter(Boolean), }, null, 2), }], } } catch (error: any) { logger.error('Failed to debug JavaScript error:', error) return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: error.message, }, null, 2), }], } } } export function register(server: McpServer) { server.registerTool( 'debug_javascript_error', { title: 'Debug JavaScript Error', description: 'Capture and analyze JavaScript errors on a page with detailed debugging info', inputSchema: { url: z.string().describe('URL where error occurs'), triggerAction: z.string().optional().describe('JavaScript to trigger the error'), waitBeforeTrigger: z.number().optional().describe('Wait time before trigger (ms)'), }, }, handler, // Use the exported handler ) }

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/jerry426/token-saver-mcp'

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