Skip to main content

web-debug

Systematic web application debugging using Chrome DevTools MCP and Playwright MCP with intelligent validation and app-specific context discovery. Use for debugging web apps, APIs, authentication flows, and UI issues.

Jump to install

Source facts

Repository
aibot88/sec_skill_store
Last source activity
May 27, 2026 at 03:47
Detected SKILL.md language
English
Stars
3
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
web-debug
description
Systematic web application debugging using Chrome DevTools MCP and Playwright MCP with intelligent validation and app-specific context discovery. Use for debugging web apps, APIs, authentication flows, and UI issues.
tools
mcp__chrome-devtools__*, mcp__playwright__*, mcp__fetch__fetch, Read, Grep, mcp__memory__*
# Web Application Debugging with Chrome DevTools MCP and Playwright MCP ## Overview This skill guides systematic, efficient web debugging using Chrome DevTools MCP and Playwright MCP. It emphasizes **validation before action** to minimize slow operations and **automatic context discovery** from project documentation. ## Decision Trees ### "Which MCP should I use?" ``` Browser debugging needed? │ ├─▶ Chrome is already open with target page? │ └─▶ Use Chrome DevTools MCP │ ├─▶ Requires: --remote-debugging-port=9222 flag │ └─▶ Check: curl http://localhost:9222/json/version │ ├─▶ Need to launch fresh browser instance? │ └─▶ Use Playwright MCP │ ├─▶ Creates headless or headed browser │ └─▶ Cleaner state, no extension interference │ ├─▶ Need to test multiple browsers (Brave, Firefox, Safari)? │ └─▶ Playwright MCP supports multiple engines │ ├─▶ Need to connect to existing DevTools session? │ └─▶ Chrome DevTools MCP only │ └─▶ Automated testing / repeatable scenarios? └─▶ Playwright MCP (better API for automation) ``` ### "How should I debug this issue?" ``` Web debugging task? │ ├─▶ Page not loading / blank screen? │ ├─▶ 1. Validate URL: mcp__fetch__fetch (check status) │ ├─▶ 2. Check console: list_console_messages({ types: ["error"] }) │ ├─▶ 3. Check network: list_network_requests (look for 4xx/5xx) │ └─▶ 4. Only then: browser_snapshot (see what rendered) │ ├─▶ Authentication not working? │ ├─▶ 1. Check docs for auth method (Context Discovery) │ ├─▶ 2. Inspect storage: browser_evaluate localStorage/cookies │ ├─▶ 3. Check network: filter for auth endpoints │ └─▶ 4. Inspect response headers (Set-Cookie, WWW-Authenticate) │ ├─▶ API call failing? │ ├─▶ 1. list_network_requests({ resourceTypes: ["xhr", "fetch"] }) │ ├─▶ 2. get_network_request({ reqid: N }) for details │ ├─▶ 3. Check: status, headers, body, CORS errors │ └─▶ 4. Compare with docs/expected API contract │ ├─▶ Element not found / can't click? │ ├─▶ 1. Quick check: browser_evaluate("!!document.querySelector(...)") │ ├─▶ 2. If false: check network for pending loads │ ├─▶ 3. If still false: browser_snapshot to see actual page │ └─▶ 4. Check: wrong selector, dynamic loading, iframe │ ├─▶ Page is slow? │ ├─▶ 1. performance_start_trace({ reload: true, autoStop: true }) │ ├─▶ 2. Review insights from trace │ └─▶ 3. Check: large network payloads, long JS execution │ └─▶ Visual/layout issue? ├─▶ 1. browser_snapshot (accessibility tree) ├─▶ 2. browser_take_screenshot (actual visual) └─▶ 3. For full-page: save to file, then resize-image --check ``` ### "Should I take a screenshot or snapshot?" ``` Need page content? │ ├─▶ Need to interact (click, fill, etc.)? │ └─▶ browser_snapshot (returns element refs like "e123") │ ├─▶ Need exact visual appearance? │ └─▶ browser_take_screenshot │ ├─▶ Viewport only: Usually safe │ ├─▶ fullPage: true: ⚠️ May exceed API limits │ │ └─▶ Save to file, then: resize-image --check │ └─▶ Element screenshot: Specify uid │ ├─▶ Just checking page structure? │ └─▶ browser_snapshot (faster, includes a11y tree) │ ├─▶ Verifying simple condition? │ └─▶ browser_evaluate is FASTEST │ └─▶ "() => document.title" │ └─▶ "() => !!document.querySelector('.logged-in')" │ └─▶ Performance investigation? └─▶ performance_start_trace / performance_stop_trace ``` ## Core Principle: Validate Before Acting **CRITICAL**: MCP browser operations are expensive. Always validate before taking action: ```bash # ❌ SLOW - Navigate blindly, then snapshot to check browser_navigate → browser_snapshot → "oops, 404" # ✅ FAST - Validate URL exists first fetch(url) → if 200 then browser_navigate → quick check current URL matches ``` ## Smart Debugging Workflow ### 1. Context Discovery (First Step) Before debugging, discover app-specific context from the repository: ```bash # Check for web debugging documentation (in priority order) 1. docs/web-debug.md # Dedicated debugging guide 2. docs/debugging.md # General debugging guide 3. docs/authentication.md # Auth-specific docs 4. README.md # Project README (search for "debug", "auth", "dev") 5. .env.example / .env.local # Environment variable hints 6. package.json / Gemfile / etc # Check for dev scripts, test users ``` **What to extract from docs:** - Base URL(s) for local dev / staging / production - Authentication mechanism (JWT, sessions, OAuth, API keys) - Test credentials or how to obtain them - Common routes and expected behavior - Known issues / quirks - API endpoint patterns **Store discovered context:** ```bash # Use MCP memory to remember app context for future sessions mcp__memory__create_entities({ entities: [{ name: "launchdeck-web-debug", entityType: "AppDebugContext", observations: [ "Base URL: http://localhost:3000", "Auth: JWT token in localStorage key 'auth_token'", "Test credentials: user@example.com / password123", "API pattern: /api/v1/{resource}", "Known issue: CORS errors on Safari, works on Brave" ] }] }) ``` ### 2. Pre-Flight Validation (Before Navigation) **Always validate URLs before navigating:** ```typescript // ✅ Validate URL is reachable const response = await mcp__fetch__fetch({ url: targetUrl, prompt: "Return status code only" }); if (response.includes("404") || response.includes("error")) { // Don't navigate, report the issue return "URL not reachable: " + targetUrl; } // ✅ Quick check - are we already on the right page? const pages = await browser_list_pages(); if (currentPage.url === targetUrl) { // Skip navigation, already there } ``` ### 3. Efficient State Inspection **Use the lightest operation that answers your question:** | Need | ❌ Slow | ✅ Fast | |------|---------|---------| | Check current URL | `browser_snapshot` | `browser_list_pages` | | Verify element exists | `browser_snapshot` | `browser_evaluate({ function: "() => !!document.querySelector('.login-btn')" })` | | Get simple value | `browser_snapshot` | `browser_evaluate({ function: "() => localStorage.getItem('token')" })` | | Check if logged in | `browser_snapshot` | `browser_evaluate({ function: "() => document.body.dataset.authenticated" })` | | Inspect network | `browser_snapshot` | `list_network_requests` | | Check console errors | `browser_snapshot` | `list_console_messages({ types: ["error"] })` | **Batch parallel operations:** ```typescript // ✅ Get all diagnostic info at once (parallel) Promise.all([ list_console_messages({ types: ["error", "warn"] }), list_network_requests({ resourceTypes: ["xhr", "fetch"] }), browser_evaluate({ function: "() => ({ url: window.location.href, token: localStorage.getItem('auth_token') })" }) ]) // ❌ Sequential snapshots (3x slower) browser_snapshot → list_console_messages → list_network_requests ``` ### 4. Authentication Handling **Discovery process:** 1. **Check documentation first** (see Context Discovery above) 2. **Inspect the app** (if docs don't exist): ```typescript // Check for common auth patterns browser_evaluate({ function: `() => ({ localStorage: Object.keys(localStorage).filter(k => k.includes('token') || k.includes('auth') || k.includes('session') ), cookies: document.cookie, hasLoginForm: !!document.querySelector('form[action*="login"]'), userIndicator: document.querySelector('[data-user], .user-name')?.textContent })` }) ``` 3. **If auth mechanism unknown, ask user ONCE and remember:** ```bash # Ask user via AskUserQuestion tool "I need to authenticate with this app but couldn't find credentials. How should I log in?" # Store their answer in MCP memory for future sessions mcp__memory__add_observations({ entityName: "app-name-web-debug", observations: ["Auth method: Form login with user@test.com / password123"] }) ``` ### 5. Systematic Debugging by Issue Type #### Network / API Debugging ```typescript // 1. List recent network activity (fast) const requests = await list_network_requests({ resourceTypes: ["xhr", "fetch"], includeStatic: false // Ignore images, fonts, etc. }); // 2. Filter for failures or slow requests const issues = requests.filter(r => r.status >= 400 || r.time > 2000 ); // 3. Inspect specific failed request if (issues.length > 0) { const detail = await get_network_request({ reqid: issues[0].id }); // Check: headers, body, timing, CORS issues } ``` #### Console Error Debugging ```typescript // 1. Get errors only (fast) const errors = await list_console_messages({ types: ["error"], includePreservedMessages: false }); // 2. Get detailed error if needed if (errors.length > 0) { const detail = await get_console_message({ msgid: errors[0].id }); } // 3. Correlate with network failures // Often console errors follow failed API calls ``` #### Authentication Flow Debugging ```typescript // 1. Check current auth state (fast evaluate, not snapshot) const authState = await browser_evaluate({ function: `() => ({ token: localStorage.getItem('auth_token'), cookies: document.cookie.split(';').map(c => c.trim().split('=')[0]), isLoggedIn: !!document.querySelector('[data-logged-in="true"]') })` }); // 2. If not authenticated, check if we have credentials const appContext = await mcp__memory__search_nodes({ query: `${appName} auth credentials` }); // 3. Perform login if we have credentials if (appContext.hasCredentials) { await browser_fill_form({ fields: [...] }); await browser_click({ element: "Submit", ref: "..." }); // 4. Validate login succeeded (check for redirect or token) await wait_for({ text: "Dashboard" }); // or check localStorage } ``` #### UI / Interaction Debugging ```typescript // 1. Before clicking, validate element exists (evaluate, not snapshot) const elementExists = await browser_evaluate({ function: `() => !!document.querySelector('button[data-action="submit"]')` }); if (!elementExists) { // Don't attempt click, investigate why element is missing // Check: network failures, JS errors, wrong page } // 2. Take snapshot only when actually needed for interaction const snapshot = await browser_snapshot(); // Now find element ref and interact ``` ## Decision Framework ### When to use full `browser_snapshot` - **Need to interact** with elements (requires refs) - **Visual debugging** (need to see layout/hierarchy) - **Unknown page state** (first time visiting) ### When to use `browser_evaluate` - **Simple data extraction** (get token, check boolean) - **Quick validation** (element exists, page ready) - **Performance-critical checks** (in loops, pre-flight validation) ### When to use `list_*` tools - **Diagnostic info** (console errors, network failures) - **Monitoring** (watching for issues during workflow) - **Quick checks** (any errors? any failed requests?) ## Common Patterns ### Pattern: Safe Navigation ```typescript async function navigateSafely(url: string) { // 1. Validate URL exists const check = await mcp__fetch__fetch({ url, prompt: "HTTP status code only" }); if (!check.includes("200")) { throw new Error(`URL not reachable: ${url}`); } // 2. Check if already there const pages = await browser_list_pages(); if (pages.current.url === url) { return "Already on page"; } // 3. Navigate await browser_navigate({ url }); // 4. Wait for specific content (not arbitrary timeout) await wait_for({ text: "Expected content" }); } ``` ### Pattern: Quick Health Check ```typescript async function quickHealthCheck() { // Parallel checks - all fast operations const [console, network, state] = await Promise.all([ list_console_messages({ types: ["error"] }), list_network_requests({ includeStatic: false }), browser_evaluate({ function: "() => ({ url: location.href, ready: document.readyState })" }) ]); return { errors: console.filter(m => m.type === "error"), failures: network.filter(r => r.status >= 400), currentUrl: state.url, pageReady: state.ready === "complete" }; }
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub