UNPKG

cdp-tools-mcp

Version:

MCP server that connects AI assistants to Chrome DevTools Protocol for runtime debugging - set breakpoints, inspect variables, monitor network traffic, and automate browser interactions

230 lines (176 loc) 5.95 kB
# Runtime Debugging ## Setting Breakpoints **Regular breakpoints:** ```javascript breakpoint({ action: 'set', url: 'http://localhost:3000/app.js', lineNumber: 42, connectionReason: 'my-debug-session' }) ``` **Conditional breakpoints:** ```javascript breakpoint({ action: 'set', url: 'http://localhost:3000/app.js', lineNumber: 42, condition: 'userId === "123"', connectionReason: 'my-debug-session' }) ``` **Logpoints** (non-breaking): ```javascript breakpoint({ action: 'setLogpoint', url: 'http://localhost:3000/app.js', lineNumber: 42, logMessage: 'User {userId} with role {userRole}', includeCallStack: true, maxExecutions: 50, connectionReason: 'my-debug-session' }) ``` ## Execution Control When paused at a breakpoint: ```javascript // Get call stack inspect({ action: 'getCallStack', connectionReason: 'my-debug-session' }) // Get variables in current scope inspect({ action: 'getVariables', callFrameId: '0', connectionReason: 'my-debug-session' }) // Filter variables by name pattern inspect({ action: 'getVariables', callFrameId: '0', filter: 'user|config', connectionReason: 'my-debug-session' }) // Evaluate expression inspect({ action: 'evaluateExpression', expression: 'user.email', connectionReason: 'my-debug-session' }) // Step over execution({ action: 'stepOver', connectionReason: 'my-debug-session' }) // Step into execution({ action: 'stepInto', connectionReason: 'my-debug-session' }) // Step out execution({ action: 'stepOut', connectionReason: 'my-debug-session' }) // Resume execution({ action: 'resume', connectionReason: 'my-debug-session' }) ``` ## Source Maps TypeScript debugging works automatically: 1. Source maps are auto-detected and registered for lazy loading 2. Breakpoints map to original TypeScript files 3. Variable names match your source code 4. Call stacks show TypeScript file paths **Lazy Loading**: Source maps are loaded on-demand when needed (e.g., when mapping positions), not eagerly at startup. This improves performance with large codebases. **Size Limits**: To prevent performance issues: - Inline source maps (data URIs): 1MB max - File-based source maps: 10MB max **Manual Loading**: ```javascript // Register source maps from a directory (lazy - does not load immediately) loadSourceMaps({ directory: './dist' }) // Source maps load automatically when you: // - Set a breakpoint that needs mapping // - Get original position from generated code ``` ## Code Search Search for patterns in loaded scripts: ```javascript // Search for code patterns inspect({ action: 'searchCode', pattern: 'fetchUser', urlFilter: 'localhost', connectionReason: 'my-debug-session' }) // Find function definitions inspect({ action: 'searchFunctions', functionName: 'handleSubmit', connectionReason: 'my-debug-session' }) // Get source code at specific lines getSourceCode({ url: 'http://localhost:3000/app.js', startLine: 40, endLine: 60, connectionReason: 'my-debug-session' }) ``` **Webpack Support**: When using webpack with eval-based source maps, code search automatically extracts the actual source code from webpack's eval wrappers. ## Node.js Debugging Debug backend applications: ```bash # Start Node with debugging node --inspect=9229 server.js ``` ```javascript // Connect to Node.js debugger connectDebugger({ reference: 'backend debug', port: 9229 }) // Set breakpoints breakpoint({ action: 'set', url: 'file:///app/server.js', lineNumber: 50, connectionReason: 'backend-debug' }) ``` ## Multi-Runtime Debugging Debug Chrome and Node.js simultaneously: **Chrome:** ```javascript launchChrome({ reference: 'frontend debug' }) navigate({ action: 'goto', url: 'http://localhost:3000', connectionReason: 'frontend-debug' }) ``` **Node.js (separate connection):** ```javascript connectDebugger({ reference: 'backend debug', port: 9229 }) breakpoint({ action: 'set', url: 'file:///app/server.js', lineNumber: 50, connectionReason: 'backend-debug' }) ``` ## Logpoint Expressions Logpoints support variable interpolation: ```javascript // Simple variables logMessage: 'User ID: {userId}' // Object properties logMessage: 'User: {user.email}, Role: {user.role}' // Function calls logMessage: 'Timestamp: {Date.now()}' // Complex expressions logMessage: 'Cart total: {cart.items.reduce((sum, item) => sum + item.price, 0)}' ``` ## Variable Inspection Fallbacks When debugging code with many variables or deeply nested objects, `getVariables` automatically degrades gracefully to fit within token limits: 1. **Full data** at requested depth (ideal case) 2. **Depth reduced** - automatically reduce expansion depth 3. **Names only** - variable names grouped by scope 4. **Counts only** - scope counts as last resort To inspect specific variables at full depth, use `filter` or `evaluateExpression`: ```javascript // Filter to specific variable inspect({ action: 'getVariables', callFrameId: '0', filter: '^myVar$', connectionReason: 'my-debug-session' }) // Or evaluate directly inspect({ action: 'evaluateExpression', expression: 'myVar', connectionReason: 'my-debug-session' }) ``` ## Bug Hunting Pattern 1. **Launch and navigate** ```javascript launchChrome({ reference: 'bug hunt' }) navigate({ action: 'goto', url: 'http://localhost:3000/problematic-page', connectionReason: 'bug-hunt' }) ``` 2. **Monitor console errors** ```javascript console({ action: 'list', type: 'error', connectionReason: 'bug-hunt' }) ``` 3. **Set breakpoints** ```javascript breakpoint({ action: 'set', url: 'http://localhost:3000/app.js', lineNumber: 150, connectionReason: 'bug-hunt' }) ``` 4. **Trigger the bug and inspect** ```javascript input({ action: 'click', selector: '#trigger-button', connectionReason: 'bug-hunt' }) // Pauses at breakpoint inspect({ action: 'getCallStack', connectionReason: 'bug-hunt' }) inspect({ action: 'getVariables', callFrameId: '0', connectionReason: 'bug-hunt' }) ```