dom-api-tracer-mcp
v2.7.5
Published
MCP Server for DOM Element Selector & API Tracer Chrome Extension — AI-agent bridge with CLI support
Maintainers
Readme
DOM API Tracer - MCP Server
Model Context Protocol (MCP) server for the DOM API Tracer Chrome extension. Provides programmatic access to extension features via 15 MCP tools for AI assistants and automation workflows.
Version: 2.7.5 Protocol: MCP 1.0 License: Proprietary - All Rights Reserved
Overview
This MCP server acts as a bridge between AI assistants and the DOM API Tracer extension. It exposes 15 tools that enable:
- DOM element selection and analysis
- Network request tracing (REST, WebSocket, GraphQL)
- Data source detection (API, SSR, Initial State)
- JavaScript execution in page or background context (with opt-in CSP bypass)
- Autonomous RPA actions (click, type, scroll, pressKey)
- Site profiling and change detection
- Session export for Playwright handoff
- Screenshot capture
The server works with any MCP-compatible client (Claude Desktop, Cursor, Windsurf, custom MCP clients, etc.).
Features
- 15 Smart Tools: Context-aware API for web analysis, RPA, site profiling, and session management
- CLI Support: Professional command-line interface (
npx dom-api-tracer-mcp) - HTTP Bridge: REST endpoint for extension communication (port 3101)
- Heartbeat System: 15s interval connection monitoring with stale detection
- Singleton Gateway: Prevents port conflicts between multiple agent instances
- Circuit Breakers: CLOSED→OPEN after 3 failures, auto-recovery after 30s, per-tool isolation
- Graceful Shutdown: Clean process termination on SIGINT/SIGTERM
- Workflow Validation: Built-in validators prevent common usage errors
- Rate Limiting: Protects against request flooding
- Auto-Config: One command to configure Claude/Cursor/Windsurf (
--init)
Installation
Prerequisites
- Node.js 18 or higher
- DOM API Tracer Chrome extension installed
Setup
Option A: NPM (Recommended)
# Run directly with npx (no installation needed)
npx dom-api-tracer-mcp
# Or auto-configure your AI agent config files
npx dom-api-tracer-mcp --initOption B: From Source
cd mcp-server
npm install
npm startCLI Options
dom-api-tracer-mcp # Start with default port (3101)
dom-api-tracer-mcp --port 3200 # Start on custom port
dom-api-tracer-mcp --init # Auto-configure AI agent config files
dom-api-tracer-mcp --debug # Enable verbose logging
dom-api-tracer-mcp --version # Show version
dom-api-tracer-mcp --help # Show helpEnvironment Variables
MCP_PORTorPORT: HTTP bridge port (default: 3101)MCP_DEBUG: Enable debug logging (1to enable)
Usage
Starting the Server
IMPORTANT: Do NOT start the server manually with npm start.
The MCP server is designed to be started automatically by AI assistants (Claude Code, Cursor, Antigravity, etc.) when they launch. Starting it manually will cause port conflicts.
The server will auto-start when your AI assistant launches:
[MCP Server] DOM API Tracer MCP server started successfully
[MCP Server] Version: 2.7.5
[MCP Server] Available tools: 15
[MCP Bridge] HTTP server started on port 3101 (PRIMARY)Connection Requirement: For the extension to connect to the MCP server, you must select an element in the browser first. Open any webpage, click the extension icon, click "Select Element", and click any element on the page.
Connecting MCP Clients
The server uses stdio transport for MCP communication. Configure your MCP client to auto-start the server.
Claude Code / Claude Desktop:
Edit ~/.config/claude/mcp.json (macOS/Linux) or %APPDATA%\Claude\mcp.json (Windows):
{
"mcpServers": {
"dom-api-tracer": {
"command": "npx",
"args": ["-y", "dom-api-tracer-mcp"]
}
}
}Cursor / Other MCP Clients:
Configure your client's MCP settings to execute:
npx -y dom-api-tracer-mcpAvailable Tools (15)
| Tool Name | Description | Workflow Position |
|---|---|---|
| quick_scan | One-call context bootstrap — analyze + profile check + discovery in one step | First Step |
| analyze_page | Detect frameworks, SSR data, element counts (+ inline APIs with includeApis:true) | Autonomous |
| discover_apis | Full API list with filtering — use when analyze_page isn't enough | Autonomous |
| extract_data | Auto-extract window.__*__PROPS / SSR data / stores → JSON Schema + paths | Autonomous |
| export_session | Export cookies + auth tokens → Playwright handoff | Autonomous |
| save_site_profile | Save site data schema + API endpoints as reusable profile | Profiling |
| load_site_profile | Load saved profile — skip re-discovery next session | Profiling |
| check_site_changes | Compare live page vs saved profile → detect structural changes | Monitoring |
| get_element | Programmatic (css/xpath/text) OR manual element retrieval — unified | Element |
| get_network_trace | REST (default) or WebSocket (protocol:'ws') trace for selected element | Tracing |
| execute_js | Run custom JavaScript in page or background context | Advanced |
| execute_action | RPA: click / type / scroll / pressKey | RPA |
| paginate | Multi-page / infinite scroll navigation (auto, button, scroll, url_increment) | Navigation |
| capture_screenshot | Viewport screenshot (use when actions fail visually) | Visual |
| debug_mcp_state | Internal state + tab IDs + circuit breaker status — troubleshooting only | Debug |
Tool Reference
analyze_page
Detect page structure, frameworks, SSR markers, and inline APIs.
Parameters:
includeApis(boolean, optional): Include captured API list in output (default: false)tabId(number, optional): Target a specific tab. Omit for active tab.
discover_apis
Get the full list of captured XHR/fetch/WebSocket calls with filtering.
Parameters:
urlPattern(string, optional): Filter by URL substring or regexmethod(string, optional): Filter by HTTP method (GET,POST,all)limit(number, optional): Max results (default: 3, max: 20)includeBody(boolean, optional): Include request/response bodiestabId(number, optional): Target a specific tab
extract_data
Auto-extract embedded data (window.__*__PROPS, SSR, Redux store) into JSON Schema with access paths.
Parameters:
tabId(number, optional): Target a specific tab
export_session
Export cookies and localStorage auth tokens for Playwright handoff.
Parameters:
tabId(number, optional): Target a specific tab
save_site_profile
Save the current site's data schema and API endpoints as a reusable profile.
Parameters:
domain(string, required): Site domain (e.g.sofascore.com)dataSchema(object, optional): Data schema to saveapiEndpoints(array, optional): API endpoints listnotes(string, optional): Free-form notes
load_site_profile
Load a previously saved site profile to skip re-discovery.
Parameters:
domain(string, optional): Domain to load. Omit to list all saved profiles.
check_site_changes
Compare the live page against a saved profile to detect breaking changes.
Parameters:
domain(string, required): Domain to checkupdateProfile(boolean, optional): Update the saved profile after comparison
get_element
Unified tool: programmatically select an element by CSS/XPath/text, or retrieve the manually selected element.
Parameters:
css(string, optional): CSS selector — preferred methodxpath(string, optional): XPath expressiontext(string, optional): Exact visible text content (last resort — unreliable on nested DOM)tabId(number, optional): Target a specific tabtriggerNetworkTrace(boolean, optional): Trigger network trace on selection (default: true)
Note: selectorInfo object is also accepted for backward compatibility:
selectorInfo.css/selectorInfo.xpath/selectorInfo.text
Returns: Element data including CSS selector, XPath, tag, attributes, stable selector with confidence score.
get_network_trace
Find API calls or WebSocket messages that populate the selected element.
Prerequisites: get_element must be called first.
Parameters:
protocol(string, optional):rest(default),ws, oralllimit(number, optional): Max results (default: 3)minConfidence(number, optional): Minimum confidence score (0.0–1.0, default: 0.5)
execute_js
Execute custom JavaScript in the active tab's page context or in the extension service worker.
Parameters:
code(string, required): JavaScript code to execute (max 10KB)timeout(number, optional): Timeout in ms (default: 5000, max: 30000)context(string, optional):page(default) orbackground. Background context: no DOM access, no CORS restrictions, can usefetchwith credentials.tabId(number, optional): Target a specific tabcspBypass(boolean, optional): Enable domain-specific CSP bypass when the site blocksnew Function(). Reloads the tab once and strips CSP headers for that domain only. Only use after a CSP error — do not set by default.
Security:
- Blocks
eval()andFunction() - Blocks
setInterval(memory leak risk) - Size limit: 10KB
- Execution timeout enforced
Note: This tool is BLOCKING. It waits up to the configured timeout for the result from Chrome. You do not need a separate call to retrieve results.
execute_action
Perform safe, autonomous interactions with a Chrome tab.
Parameters:
actionType(string, required):click,type,scroll, orpressKeyselectorInfo(object, required):{ css?: string, xpath?: string, text?: string }. Prefercssorxpath.url(string, required): Current page URL (for safety validation)text(string, optional): Text to type (only foractionType: 'type')
Best Practice: Always call execute_js first to validate your selector before calling execute_action.
Security: Blocked from password fields, banking, and crypto pipeline environments.
capture_screenshot
Capture a viewport screenshot of the active tab.
Parameters:
tabId(number, optional): Target a specific tab
debug_mcp_state
Return the MCP server's internal state: connection status, selected element, network trace summary, tab IDs, circuit breaker status.
Parameters: None
Common Workflows
REST API Discovery (autonomous):
analyze_page({ includeApis: true })
→ get_element({ css: '.price' })
→ get_network_trace()SSR / Embedded Data Extraction:
analyze_page()
→ extract_data() # list window.__*__PROPS paths
→ execute_js({ code: "window.__PATH__.fieldName" }) # extract valueSSR fallback (when get_network_trace has no match):
get_element({ css: '.price' })
→ get_network_trace() # returns "no match"
→ extract_data() # instead, list SSR paths
→ save_site_profile({ dataSchema: {...} }) # persist schemaWebSocket Sites (Binance, X.com, TradingView):
get_element()
→ get_network_trace({ protocol: 'ws' })RPA Automation:
execute_js({ code: "document.querySelector('button.submit') !== null" })
→ execute_action({ actionType: 'click', selectorInfo: { css: 'button.submit' }, url: '...' })Multi-Page Scraping:
paginate({ strategy: 'auto', limit: 10 })
→ execute_js({ code: "..." }) # extract data per page
→ save_site_profile({ dataSchema: {...} }) # persist collected schemaSession Export → Playwright Handoff:
export_session()
# Returns: cookies + localStorage + sessionStorage
# Use in Playwright:
await context.addCookies(session.cookies);
await page.evaluate(ls => Object.entries(ls).forEach(...), session.localStorage);Multi-Tab: Call debug_mcp_state() first to get tab IDs → pass tabId: <n> to any tool.
Strict-CSP Sites (X.com, GitHub):
execute_js({ code: "...", cspBypass: true })
# WARNING: tab reloads once, loses SPA state
# Only use after confirmed CSP errorTimeout Recovery:
# When execute_js times out on heavy DOM pages:
1. Lower timeout: execute_js({ code: "...", timeout: 3000 })
2. Use background context: execute_js({ code: "...", context: "background" })
3. Simplify code: break complex queries into stepsArchitecture
Modular Structure
mcp-server/src/
├── index.js # Thin MCP client — connects to bridge daemon, registers 15 tools
├── bridge-daemon.js # Standalone bridge process (auto-spawned by index.js)
├── tools/ # Tool implementations
│ ├── analyze-page.js
│ ├── discover-apis.js
│ ├── extract-data.js
│ ├── export-session.js
│ ├── save-site-profile.js
│ ├── load-site-profile.js
│ ├── check-site-changes.js
│ ├── get-element.js
│ ├── get-network-trace.js
│ ├── execute-js.js
│ ├── action_tools.js # execute_action
│ ├── screenshot_tools.js # capture_screenshot
│ ├── quick-scan.js # quick_scan
│ ├── paginate.js
│ ├── debug-mcp-state.js
│ └── index.js # Tool registry (allTools array)
├── bridge/ # HTTP server for extension communication
│ ├── http-server.js
│ ├── routes.js
│ └── middleware.js
├── state/ # State management
│ ├── extension-state.js # In-memory state (bridge daemon only)
│ ├── bridge-client.js # HTTP client — mirrors extensionData interface
│ └── bridge-persistence.js # Disk persistence (debounced write, atomic write)
└── utils/ # Shared utilities
├── circuit-breaker.js
├── state-validator.js
├── rate-limiter.js
├── run-script.js
├── tab-resolver.js
├── workflow-helper.js
├── workflow-state.js
├── selector-validator.js
└── logger.jsHTTP Bridge Endpoints
The server runs an Express HTTP server on port 3101 for extension communication:
| Method | Endpoint | Purpose |
|--------|----------|---------|
| GET | /health | Health check — returns connection status, data state, uptime |
| GET | /api/sync-state | Get full server state for secondary instance reconnect |
| GET | /api/pending-requests | Extension polls this to retrieve queued requests |
| GET | /api/connection-status | Connection status (connected, stale, heartbeat info) |
| GET | /api/selected-element | Selected element data |
| GET | /api/page-analysis | Page analysis data |
| GET | /api/network-trace | Network trace data |
| GET | /api/websocket-trace | WebSocket trace data |
| GET | /api/state | All state fields (including request/result for validation) |
| GET | /api/result/:type | Result polling with consume-on-read (atomic read + delete) |
| POST | /api/element-selected | Extension pushes selected element data |
| POST | /api/network-trace | Extension pushes REST network trace |
| POST | /api/websocket-trace | Extension pushes WebSocket trace |
| POST | /api/saved-selections | Extension pushes saved selections |
| POST | /api/sync-all | Extension syncs full state at once |
| POST | /api/full-sync | Extension pushes all state after detecting server restart |
| POST | /api/ping | Extension connection test |
| POST | /api/heartbeat | Extension heartbeat (every 15s) — returns pending request count, needsRestore flag |
| POST | /api/disconnect | Extension signals page unload or tab close |
| POST | /api/page-analysis | Extension pushes page analysis result |
| POST | /api/execute-js | Queue JS execution request / receive result |
| POST | /api/execute-action | Queue RPA action request / receive result |
| POST | /api/capture-screenshot | Queue screenshot request / receive result |
| POST | /api/raw-network-requests | Queue discover_apis request / receive result |
| POST | /api/select-element | Queue programmatic element selection / receive result |
| POST | /api/export-session | Queue session export request / receive result |
| POST | /api/tabs | Queue tab list request / receive result |
| POST | /api/clear-request | Extension signals a specific request was processed |
| POST | /api/clear-all-requests | Clear all pending content-script requests (on SW restart) |
| POST | /api/die | Graceful shutdown (localhost/extension origin only) |
Health Check
curl http://localhost:3101/health
# Response: {"status":"ok","isConnected":true,...}Validation System
The server implements three validation layers:
- StateValidator: Ensures data freshness (selected element expires after 10 minutes)
- RateLimiter: Prevents request flooding
- WorkflowHelper: Validates tool dependencies and execution order
When a validation error is returned, read the error message — it includes "REQUIRED STEPS" with explicit instructions on how to fix the issue.
Tool Response Format
All tools return:
{
"content": [{ "type": "text", "text": "Tool output" }],
"isError": false
}On error:
{
"content": [{ "type": "text", "text": "Error: Description\nREQUIRED STEPS:\n1. ..." }],
"isError": true
}Adding a New Tool
- Create
src/tools/my-new-tool.js:
export const myNewTool = {
name: 'my_new_tool',
description: 'What this tool does',
inputSchema: {
type: 'object',
properties: {
param1: { type: 'string', description: 'Parameter description' }
},
required: ['param1']
},
handler: async (args, bridgeClient) => {
// Use bridgeClient.refreshState() to get fresh state (called by index.js before each tool)
// Use bridgeClient.queueRequest(endpoint, data) to send requests
// Use bridgeClient.waitForResult(type, requestId, timeout) to poll for results
return { content: [{ type: 'text', text: 'Result' }] };
}
};Register in
src/tools/index.js→ add toallToolsarray.Document in this README's tools table.
Run
npm run sync-versionfrom the project root — auto-updates tool count in all docs.
Troubleshooting
Extension Not Connected
debug_mcp_state returns "extension": "disconnected":
- Ensure Chrome extension is loaded:
chrome://extensions/ - Refresh the webpage where the extension is active
- Select any element using the extension popup
- Verify server is running:
curl http://localhost:3101/health
Port Already in Use
Error: listen EADDRINUSE: address already in use :::3101# macOS/Linux
lsof -i :3101
# Windows
netstat -ano | findstr :3101
# Use a different port
export MCP_PORT=3200
npm startStale Data Error
"Selected element data is stale (>10 minutes old)": call get_element again to refresh.
CSP Errors on Strict-CSP Sites
execute_js returns a CSP error on X.com, GitHub, etc.: retry with cspBypass: true. This reloads the tab once and strips CSP headers for that domain only.
Performance
- Tool Execution: <100ms for most tools
- Network Trace: <500ms for typical traces (10–50 requests)
- JavaScript Execution: 100ms–5000ms depending on code complexity
- State Freshness: 10-minute cache for selected element data
Security
- Code Validation: JavaScript executor blocks
eval(),Function(),setInterval, XSS vectors,globalThis['chrome']bracket bypass - Timeout Enforcement: Hard timeout on all JS execution (max 30s)
- Size Limits: Code max 10KB, result max 100KB
- Rate Limiting: Prevents request flooding
- RPA Safety Guard: Blocks password fields and sensitive environments
License
This software is proprietary. All rights reserved.
Unauthorized copying, distribution, or modification is prohibited.
For licensing inquiries: [email protected]
Support
- Main README: ../README.md
- MCP Protocol: Model Context Protocol Specification
- Contact: [email protected]
