@ironbee-ai/devtools
v0.44.0
Published
MCP Server and CLI for IronBee DevTools
Readme
Overview
IronBee DevTools is a platform-extensible MCP server designed to give AI agents deep inspection and control over application runtimes. The architecture supports multiple platforms through a unified interface, with each platform providing specialized tools for its environment.
Supported Platforms
| Platform | Description | Status | |----------|-------------|--------| | Browser | Playwright-powered browser automation with full DevTools integration | ✅ Available | | Node | Non-blocking debugging for Node.js backend processes via Inspector Protocol | ✅ Available | | Backend | Runtime- and language-agnostic backend verification (HTTP / gRPC / GraphQL / WebSocket) + log capture (file / docker / kubernetes) + database verification (Postgres / MySQL / SQLite) | ✅ Available |
The Browser Platform exposes a Playwright-powered browser runtime to AI agents, enabling deep, bidirectional debugging and interaction with live web pages. It supports both visual understanding and code-level inspection of browser state, making it ideal for AI-driven exploration, diagnosis, and automation.
The Node Platform provides non-blocking debugging for Node.js backend processes. It connects to running Node.js processes via the Inspector Protocol (Chrome DevTools Protocol over WebSocket) and offers tracepoints, logpoints, exceptionpoints, watch expressions, and source map support—ideal for debugging APIs, workers, and server-side code.
The Backend Platform binds to wire protocols, not specific frameworks: agents drive backend services via HTTP/1.1, HTTP/2, gRPC (unary + 3 streaming modes), GraphQL, and stateful WebSockets, with automatic W3C trace propagation so every request becomes a verifiable correlation root. Paired with the log_* domain, agents capture server-side log lines (from files, docker containers, or kubernetes pods) for the same trace; paired with the db_* domain, agents inspect database state directly (schema discovery, parameterized reads, before-vs-after snapshot diffs, polling change feeds) against Postgres / MySQL / SQLite — closing the "trigger and verify" loop without locking in to any framework, language, or runtime.
Platform Selection
Choose the platform by running the appropriate MCP server or CLI:
| Use Case | MCP Server | CLI |
|----------|------------|-----|
| Browser automation & debugging | ironbee-devtools-mcp | ironbee-devtools-cli |
| Node.js backend debugging | ironbee-node-devtools-mcp | ironbee-node-devtools-cli |
| Backend verification (HTTP/gRPC/GraphQL/WS) + log capture + database (Postgres/MySQL/SQLite) | ironbee-backend-devtools-mcp | ironbee-backend-devtools-cli |
Browser Platform Capabilities
- Visual Inspection: Screenshots, ARIA snapshots, HTML/text extraction, PDF generation
- Design Comparison: Compare live page UI against Figma designs with similarity scoring
- DOM & Code-Level Debugging: Element inspection, computed styles, accessibility data
- Browser Automation: Navigation, input, clicking, scrolling, viewport control
- Execution Monitoring: Console message capture, HTTP request/response tracking
- OpenTelemetry Integration: Automatic trace injection into web pages, UI trace collection, and backend trace correlation via trace context propagation
- JavaScript Execution: Use the execute tool to batch-execute tool calls and run custom JavaScript; on the browser platform the VM receives `page` (Playwright Page) so you can use `page.evaluate()` or the Playwright API
- Session Management: Long-lived, session-based debugging with automatic cleanup
- Closed tab: If the MCP session’s browser tab was closed, the next tool run opens a new tab for that session (previous element refs are invalid until you take a new snapshot). Session network-idle / in-flight tracking state is also reset for the new tab.
- Multiple Transport Modes: Supports both stdio and HTTP transports
Node Platform Capabilities
- Connection: Connect to Node.js processes by PID, process name, port, WebSocket URL, or Docker container
- Non-Blocking Debugging: Tracepoints, logpoints, exceptionpoints without pausing execution
- Source Map Support: Resolves bundled/minified code to original source locations;
debug_resolve-source-locationtranslates stack traces and bundle locations to original source - OpenTelemetry Integration: When the Node process uses
@opentelemetry/api, tracepoint/logpoint snapshots automatically includetraceContext(traceId, spanId) for correlating backend traces with browser traces - Docker Support: Connect to Node.js processes running inside Docker containers (
containerId/containerName)
Backend Platform Capabilities
- Protocol Coverage: HTTP/1.1 + HTTP/2 (via ALPN auto-negotiation, TLS), gRPC (unary + 3 streaming modes; .proto file or descriptor), GraphQL (query/mutation, persisted queries), and stateful multi-tool WebSocket (open / send / receive / close / list)
- Trace Propagation: Every request auto-injects W3C
traceparentso the resultingtraceIdchains into log/log_read for verification — turns the platform into a true "trigger and verify" loop, not just an HTTP client. Session-pinned trace context viao11y_new-trace-id/o11y_set-trace-context/o11y_get-trace-contextlets the agent anchor a multi-tool flow to one trace without per-call plumbing; the pin is silently shadowed by an MCP-client-supplied_metadata.traceIdso the orchestrator's correlation boundary stays intact - Cookie Jar: Session-scoped, RFC 6265 host/path scoped, auto-populated from
Set-Cookie; agent-writable viarequest_set-cookies/request_list-cookies/request_clear-cookies - Default Headers / Metadata: Host-scoped HTTP default headers and target-scoped gRPC default metadata (
request_set-default-headers,request_set-default-metadata) — auth tokens stay pinned to their host/target - Replay: Replay a captured curl command or HAR entry verbatim via
request_replay - Log Capture (file / docker / kubernetes): Register a log source by name (
log_register-source), point-in-time read (log_read) or live stream (log_follow→log_get-followed→log_stop-follow), and merge across multiple sources chronologically (log_read-multi) - Log Pipeline:
tail/since/until/ substringpattern/ heuristiclevel/parseJson+ dot-pathjsonFilter/coalescefor multi-line stack traces /contextBefore+contextAfterfor grep-style windows /selectfor JSONL projection — all composable on a single read call - Rotation-Aware Following: File source survives logrotate's rename-and-recreate, copy-and-truncate, and in-place truncate without
fs.watch— deterministic cross-platform behavior (Linux/macOS/Windows/NFS/container FS) - Auto-Redaction: Returned log lines have Authorization / Cookie / X-API-Key headers, Bearer/Basic tokens,
password=/token=/api_key=pairs,*_SECRET/*_TOKENenv-style assignments, and matching JSON keys redacted before reaching the agent — credentials never reach the LLM context window (BACKEND_LOG_REDACT_ENABLEtoggle, default on) - Source Liveness Probe:
log_check-sourcereports{ reachable, sizeBytes, lastModified, recentLineCount, error }for fast "why is log_read returning empty" diagnostics - Database Verification (Postgres / MySQL / SQLite): Open named connections (
db_connectwithconnectionStringEnvso secrets stay inprocess.env, never in the agent's context), discover schema (db_list-tables,db_describe-tablereturns columns + primary key + indexes + foreign keys + row count estimate), run parameterized reads (db_query), and inspect state across protocol calls — paired withrequest_*this lets agents assert "the POST actually created the row with these values" - Snapshot & Diff State Verification:
db_snapshotcaptures a point-in-time set of rows keyed by primary key; two snapshots fed todb_diffyield exactadded/removed/changed(withchangedColumns) — the canonical before/after assertion primitive for AI-agent verification - Polling Change Feed:
db_watch-changes+db_get-changesstream diffs into a ring buffer at configurable cadence — agent watchesaudit_logs(or any table), triggers the request, drains the buffer to see exactly which rows the system wrote async - Readonly Defense-in-Depth: Connections open in server-side READ ONLY mode by default (Postgres
default_transaction_read_only, MySQLSESSION TRANSACTION READ ONLY, SQLite OS-level readonly file) — the actual security boundary, independent of the SQL parser whitelist that fast-fails write keywords. Writes flow only throughdb_transaction-begin({ writable: true })on connections explicitly opened withallowWrites:true, plusdb_seed(structured row INSERTs) anddb_run-script(raw multi-statement DDL/fixtures) - Column-Aware Redaction: Result-set columns matching
BACKEND_DB_QUERY_REDACT_KEYS(defaultpassword,token,api_key,password_hash, …) are replaced with[REDACTED]before reaching the agent; redaction recurses into JSON/JSONB column values too —users.metadata.api_keyis caught without explicit configuration - Optional Peer Deps: Engine drivers (
pg,mysql2) are loaded only when actually used — install only what your verification scenarios need. SQLite needs no driver: it runs on Node's built-innode:sqlite
Browser Platform Features
Content Tools
- Screenshots: Capture full page or specific elements (PNG/JPEG) with image data; optional
annotate: trueoverlays numbered labels (1, 2, ...) on elements from the last ARIA snapshot refs and returns anannotationsarray (ref, number, role, name, box). If the ref map is empty, a snapshot is taken automatically. SetannotateContent: trueto also include content elements (headings, list items, etc.) in the overlay. SetannotateCursorInteractive: trueto also include cursor-interactive elements (clickable/focusable by CSS without ARIA role) in the overlay. Theselectorparameter accepts a ref (e.g.e1,@e1), a getByRole/getByLabel/getByText/etc. expression, or a CSS selector; withselectorset, only annotations overlapping that element are returned and box coordinates are element-relative; withfullPage: true(no selector), box coordinates are document-relative. - HTML/Text Extraction: Get page content with filtering, cleaning, and minification options
- PDF Export: Save pages as PDF documents with customizable format and margins
- Video Recording: Record browser page interactions as WebM video using Playwright's native
page.screencastAPI (1.59+). Start withcontent_start-recording, stop withcontent_stop-recording. Works in all modes (headless, headed, persistent, CDP attach).
Interaction Tools
- Click: Click elements by snapshot ref (e.g.
e1,@e1,ref=e1), Playwright-style expression (e.g.getByRole('button', { name: 'Login' }),getByLabel('Email'),getByText('Register'),getByPlaceholder('[email protected]'),getByTitle('…'),getByAltText('…'),getByTestId('…')), or CSS selector. Refs come froma11y_take-aria-snapshotand are valid until the next snapshot or navigation. - Fill: Fill form inputs (ref, getByRole/getByLabel/getByPlaceholder/etc., or CSS selector)
- Hover: Hover over elements (ref, getByXYZ expression, or CSS selector)
- Press Key: Simulate keyboard input; optional ref, getByXYZ expression, or CSS selector to focus an element before sending the key
- Select: Select dropdown options (ref, getByRole/getByTestId/etc., or CSS selector)
- Drag: Drag and drop (source and target as ref, getByXYZ expression, or CSS selector)
- Scroll: Scroll the page viewport or specific scrollable elements with multiple modes (by, to, top, bottom, left, right); optional ref, getByXYZ, or CSS selector for scrollable container
- Resize Viewport: Resize the page viewport using Playwright viewport emulation
- Resize Window: Resize the real browser window (OS-level) using Chrome DevTools Protocol
Navigation Tools
- Go To: Navigate to URLs with configurable wait strategies. By default waitForNavigation is
true: after navigation completes, waits for network idle before taking snapshot/screenshot; setwaitForNavigation: falseto skip the network idle wait. waitForTimeoutMs (default 30000) is the timeout for that wait whenwaitForNavigationis true. By default (includeSnapshot: true) returns an ARIA snapshot with refs (output,refs); setincludeSnapshot: falsefor url/status/ok only. Use snapshotOptions (e.g.interactiveOnly,cursorInteractive) to control which elements get refs (same asa11y_take-aria-snapshot). Optional includeScreenshot saves a screenshot to disk and returnsscreenshotFilePath; use screenshotOptions (outputPath, name, fullPage, type, annotate, includeBase64) — defaults: OS temp dir, name "screenshot"; setincludeBase64: trueonly when the file cannot be read from the path (e.g. remote, container). - Go Back / Go Forward: Navigate backward or forward in history. Same waitForNavigation (default true), waitForTimeoutMs, snapshot/refs and optional screenshot behavior as Go To.
- Reload: Reload the current page. Same waitForNavigation (default true), waitForTimeoutMs, snapshot/refs and optional screenshot behavior as Go To.
Execute tool (batch)
- Execute: Batch-execute multiple tool calls in a single request via custom JavaScript. Use
callTool(name, input, returnOutput?)to invoke any registered tool (canonical id such asnavigation_go-to, or the same name the MCP host exposes whenTOOL_NAME_PREFIXis set). Reduces round-trips and token usage. Includes wall-clock timeout, max tool call limit (50), console log capture, and fail-fast error handling withfailedTooldiagnostics. On the browser platform the VM also receives the session execution context:page(Playwright Page) is available — use the Playwright API (e.g.page.locator(),page.goto()) orpage.evaluate()to run script in the browser. On the Node platform no extra bindings are injected. CLI:run execute --code '…' [--timeout-ms N]orrun execute --file ./script.js(same daemon session as other tools; starts the daemon if needed). Boolean tool flags with defaulttruealso accept--no-<flag>(e.g.--no-wait-for-navigation). MCP or daemon HTTP API (POST/callwithtoolName: "execute"andtoolInput: { code, timeoutMs? }) also work.
Observability (O11Y) Tools
- Console Messages: Capture and filter browser console logs with advanced filtering (level, search, timestamp, sequence number)
- HTTP Requests: Monitor network traffic with filtering by resource type, status code, and more. Request headers, response headers, and response body are opt-in (
includeRequestHeaders,includeResponseHeaders,includeResponseBody; default off). Response body is not stored for static assets (e.g. .js, .css, .map) - Web Vitals: Collect Core Web Vitals (LCP, INP, CLS) and supporting metrics (TTFB, FCP) with ratings and recommendations based on Google's thresholds
- OpenTelemetry Tracing: Automatic trace injection into web pages, UI trace collection (document load, fetch, XMLHttpRequest, user interactions), and trace context propagation for backend correlation
- Trace ID Management: Get, set, and generate OpenTelemetry compatible trace IDs for distributed tracing across API calls
Scenario Tools
- Scenario Add/Update/Delete: Manage reusable test scenarios stored as JS scripts in
.ironbee-devtools/scenarios.json(project-level or global) - Scenario Run: Execute a saved scenario by name. Runs in the same sandbox as
execute— supportscallTool(), composable via nestedscenario-runcalls (max depth: 5) - Scenario List: List all available scenarios from project and/or global scope
- Scenario Search: Search scenarios by description using configurable strategy (simple default or FTS5)
Synchronization Tools
- Wait for Network Idle: Wait until the page reaches a network-idle condition based on the session’s tracked in-flight request count (tunable via
sync_wait-for-network-idlelikeidleTimeMs/maxConnections), useful for SPA pages and before taking screenshots
Accessibility (A11Y) Tools
- ARIA Snapshots: Capture semantic structure and accessibility roles in YAML format. Returns a tree with element refs (e1, e2, ...) and a
refsmap; refs are stored in session context for use in interaction tools (click, fill, hover, select, drag, scroll, press-key) as the selector (e.g.e1,@e1,ref=e1). You can also use Playwright-style expressions in those tools:getByRole('button', { name: 'Login' }),getByLabel('Email'),getByText('Register'),getByPlaceholder('…'),getByTitle('…'),getByAltText('…'),getByTestId('…'), or CSS selectors. Refs are valid until the next ARIA snapshot or navigation—re-snapshot after page/DOM changes. Options: interactiveOnly (only interactive elements get refs); cursorInteractive: true (also assign refs to elements that are clickable/focusable by CSS but have no ARIA role, e.g. custom div/span buttons); selector (scope the snapshot to an element). - AX Tree Snapshots: Combine Chromium's Accessibility tree with runtime visual diagnostics (bounding boxes, visibility, occlusion detection, computed styles)
Stub Tools
- Intercept HTTP Request: Intercept and modify outgoing HTTP requests (headers, body, method) using glob patterns
- Mock HTTP Response: Mock HTTP responses (fulfill with custom status/headers/body or abort) with configurable delay, times limit, and probability (flaky testing)
- List Stubs: List all currently installed stubs for the active browser context
- Clear Stubs: Remove one or all installed stubs
Figma Tools
- Compare Page with Design: Compare the current page UI against a Figma design snapshot and return a combined similarity score using multiple signals (MSSIM, image embedding, text embedding)
React Tools
- Get Component for Element: Find React component(s) associated with a DOM element using React Fiber (best-effort)
- Get Element for Component: Map a React component instance to the DOM elements it renders by traversing the React Fiber graph
Important Requirements for React Tools:
- Persistent Browser Context: React tools work best with persistent browser context enabled (
BROWSER_PERSISTENT_ENABLE=true) - React DevTools Extension: For optimal reliability, manually install the "React Developer Tools" Chrome extension in the browser profile. The MCP server does NOT automatically install the extension.
- Chrome Web Store: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
- The extension enables reliable root discovery and component search via
__REACT_DEVTOOLS_GLOBAL_HOOK__ - Without the extension, tools fall back to scanning DOM for
__reactFiber$pointers (best-effort, less reliable)
Debug Tools (Non-Blocking)
Non-blocking debugging tools that capture snapshots without pausing execution. Ideal for AI-assisted debugging.
Probe Types:
- Tracepoint: Captures call stack, local variables, and async stack traces at a code location
- Logpoint: Evaluates and logs expressions without full debug context (lightweight)
- Exceptionpoint: Captures snapshots when exceptions occur (uncaught or all)
Core Operations (per probe type):
put-*: Create a probe at a locationremove-*: Remove a specific probelist-*: List all probes of a typeclear-*: Remove all probes of a typeget-*-snapshots: Retrieve captured snapshots (supportsfromSequencefor polling)clear-*-snapshots: Clear captured snapshots
Additional Tools:
- Resolve Source Location: Resolve a generated/bundle location (URL + line + column) to original source via source maps—useful for translating minified stack traces
- Watch Expressions: Add expressions to evaluate at every tracepoint/exceptionpoint hit
- Status: Get current debugging status (enabled, probe counts, snapshot stats)
Key Features:
- Source map support for debugging bundled/minified code with original source locations
- Automatic debugging enablement on first tool use
- Configurable limits (max snapshots, call stack depth, async segments)
- Sequence numbers for efficient snapshot polling
- OpenTelemetry trace context in Node snapshots (traceId, spanId when process uses @opentelemetry/api)
- Snapshot capture: 1 call stack frame with scopes (both platforms) to keep payloads small. Output trimming for
get-probe-snapshots: default scopes =localonly (both Browser and Node), 20 variables/scope. Override viamaxCallStackDepth,includeScopes,maxVariablesPerScope.
Prerequisites
- Node.js 22.16+ — the SQLite database engine and the FTS5 scenario-search strategy run on Node's built-in
node:sqlite, and 22.16.0 is the first release whose bundled SQLite is compiled with FTS5 - An AI assistant (with MCP client) like Cursor, Claude (Desktop or Code), VS Code, Windsurf, etc.
Quick Start
This MCP server (using STDIO or Streamable HTTP transport) can be added to any MCP Client
like VS Code, Claude, Cursor, Windsurf, GitHub Copilot via the @ironbee-ai/devtools NPM package.
No manual installation required! The server can be run directly using npx, which automatically downloads and runs the package.
📦 Playwright browser binaries (required for browser platform)
The browser platform needs Playwright browser binaries (e.g. Chromium) to control the browser.
If you use npx to run the server, browsers are not downloaded at install time — you must install them once (see below). With a normalnpm install, Playwright’s own packages may install Chromium automatically.
| Goal | What to do |
|------|------------|
| Warm up / verify ahead of time (recommended) | Run: npx -y @ironbee-ai/devtools prefetch — installs the package into the npx cache AND downloads missing browsers with visible progress, then exits (never starts the MCP server) |
| Install at first run (npx) | Set env before running: BROWSER_DEVTOOLS_INSTALL_CHROMIUM=true npx -y @ironbee-ai/devtools |
| Install manually anytime | Run: npx playwright install chromium (or firefox, webkit) |
| Skip download (CI / system browser) | Set: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 |
prefetch mode — npx -y @ironbee-ai/devtools prefetch [--browsers <csv>] [--json]
warms the whole npx delivery path at a moment you choose (a CI image build, a
setup script, the IronBee CLI's install step) instead of inside an MCP host's
startup window. --browsers takes a comma-separated subset of
chromium | chromium-headless | ffmpeg | firefox | webkit | none (none = package-only);
without the flag it derives the set from the BROWSER_DEVTOOLS_INSTALL_* env
vars, defaulting to chromium. Already-installed browsers are detected and
skipped, so re-runs are cheap. Exit code 0 on success, 1 on failure; --json
prints a machine-readable summary on stdout.
Launch-time self-heal — if the server is started from an install whose
browser download never ran (e.g. an npx cache entry created without the
BROWSER_DEVTOOLS_INSTALL_* env), the browser platform detects the missing
executables right before the first managed launch and installs them on the
spot (progress on stderr) instead of failing with "Executable doesn't exist".
Launches with an explicit BROWSER_EXECUTABLE_PATH or
BROWSER_USE_INSTALLED_ON_SYSTEM=true, and CDP attach, never trigger it.
1. Opt-in at install time — set env vars before npm install or npx so the postinstall script downloads the chosen browsers:
- Chromium (chromium + chromium-headless-shell + ffmpeg):
BROWSER_DEVTOOLS_INSTALL_CHROMIUM=true npx -y @ironbee-ai/devtools - Firefox:
BROWSER_DEVTOOLS_INSTALL_FIREFOX=true - WebKit:
BROWSER_DEVTOOLS_INSTALL_WEBKIT=true - ffmpeg only:
BROWSER_DEVTOOLS_INSTALL_FFMPEG=true— for environments that bring their own Chromium build and pointBROWSER_EXECUTABLE_PATHat it: no browser download, but screen recording still resolvesffmpegthrough Playwright's registry. Ignored when a Chromium download is also requested (ffmpeg already rides those sets). Combine as needed, e.g.BROWSER_DEVTOOLS_INSTALL_CHROMIUM=true BROWSER_DEVTOOLS_INSTALL_FIREFOX=true npx -y @ironbee-ai/devtools.
2. Install via Playwright CLI (same global cache):
npx playwright install chromium # or firefox, webkitOn Linux, include system dependencies:
npx playwright install --with-deps chromiumCLI Arguments
IronBee DevTools server supports the following CLI arguments for configuration:
--transport <stdio|streamable-http>- Configures the transport protocol (defaults tostdio).--port <number>– Configures the port number to listen on when usingstreamable-httptransport (defaults to3000).
MCP Client Configuration
To use the Node platform (Node.js backend debugging), use ironbee-node-devtools-mcp instead of ironbee-devtools-mcp:
{
"mcpServers": {
"node-devtools": {
"command": "npx",
"args": ["-y", "-p", "@ironbee-ai/devtools", "ironbee-node-devtools-mcp"]
}
}
}Alternatively, set PLATFORM=node when running ironbee-devtools-mcp.
Local Server
Add the following configuration into the claude_desktop_config.json file.
See the Claude Desktop MCP docs for more info.
Browser platform (default):
→ Browser platform requires Playwright browser binaries. See 📦 Playwright browser binaries for one-time install (env vars or
npx playwright install chromium).
{
"mcpServers": {
"ironbee-devtools": {
"command": "npx",
"args": ["-y", "@ironbee-ai/devtools"]
}
}
}Node platform:
{
"mcpServers": {
"node-devtools": {
"command": "npx",
"args": ["-y", "-p", "@ironbee-ai/devtools", "ironbee-node-devtools-mcp"]
}
}
}Remote Server (HTTP Transport)
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then, go to Settings > Connectors > Add Custom Connector in Claude Desktop and add the MCP server with:
- Name:
IronBee DevTools - Remote MCP server URL: Point to where your server is hosted (e.g.,
http://localhost:3000/mcpif running locally, orhttps://your-server.com/mcpif hosted remotely)
Run the following command. See Claude Code MCP docs for more info.
→ Browser platform requires Playwright browser binaries. See 📦 Playwright browser binaries for one-time install (env vars or
npx playwright install chromium).
Local Server
claude mcp add ironbee-devtools -- npx -y @ironbee-ai/devtoolsRemote Server
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then add the MCP server:
claude mcp add --transport http ironbee-devtools <SERVER_URL>Replace <SERVER_URL> with your server URL (e.g., http://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely).
Add the following configuration into the ~/.cursor/mcp.json file (or .cursor/mcp.json in your project folder).
See the Cursor MCP docs for more info.
→ Browser platform requires Playwright browser binaries. See 📦 Playwright browser binaries for one-time install (env vars or
npx playwright install chromium).
Local Server
{
"mcpServers": {
"ironbee-devtools": {
"command": "npx",
"args": ["-y", "@ironbee-ai/devtools"]
}
}
}Remote Server
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then add the configuration:
{
"mcpServers": {
"ironbee-devtools": {
"url": "<SERVER_URL>"
}
}
}Replace <SERVER_URL> with your server URL (e.g., http://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely).
Add the following configuration into the .vscode/mcp.json file.
See the VS Code MCP docs for more info.
→ Browser platform requires Playwright browser binaries. See 📦 Playwright browser binaries for one-time install (env vars or
npx playwright install chromium).
Local Server
{
"mcp": {
"servers": {
"ironbee-devtools": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@ironbee-ai/devtools"]
}
}
}
}Remote Server
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then add the configuration:
{
"mcp": {
"servers": {
"ironbee-devtools": {
"type": "http",
"url": "<SERVER_URL>"
}
}
}
}Replace <SERVER_URL> with your server URL (e.g., http://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely).
Add the following configuration into the ~/.codeium/windsurf/mcp_config.json file.
See the Windsurf MCP docs for more info.
→ Browser platform requires Playwright browser binaries. See 📦 Playwright browser binaries for one-time install (env vars or
npx playwright install chromium).
Local Server
{
"mcpServers": {
"ironbee-devtools": {
"command": "npx",
"args": ["-y", "@ironbee-ai/devtools"]
}
}
}Remote Server
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then add the configuration:
{
"mcpServers": {
"ironbee-devtools": {
"serverUrl": "<SERVER_URL>"
}
}
}Replace <SERVER_URL> with your server URL (e.g., http://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely).
Add the following configuration to the mcpServers section of your Copilot Coding Agent configuration through
Repository > Settings > Copilot > Coding agent > MCP configuration.
See the Copilot Coding Agent MCP docs for more info.
→ Browser platform requires Playwright browser binaries. See 📦 Playwright browser binaries for one-time install (env vars or
npx playwright install chromium).
Local Server
{
"mcpServers": {
"ironbee-devtools": {
"type": "local",
"command": "npx",
"args": ["-y", "@ironbee-ai/devtools"]
}
}
}Remote Server
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then add the configuration:
{
"mcpServers": {
"ironbee-devtools": {
"type": "http",
"url": "<SERVER_URL>"
}
}
}Replace <SERVER_URL> with your server URL (e.g., http://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely).
Add the following configuration into the ~/.gemini/settings.json file.
See the Gemini CLI MCP docs for more info.
Local Server
{
"mcpServers": {
"ironbee-devtools": {
"command": "npx",
"args": ["-y", "@ironbee-ai/devtools"]
}
}
}Remote Server
First, start the server with HTTP transport:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000Then add the configuration:
{
"mcpServers": {
"ironbee-devtools": {
"httpUrl": "<SERVER_URL>"
}
}
}Replace <SERVER_URL> with your server URL (e.g., http://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely).
Run the following command. You can find your Smithery API key here. See the Smithery CLI docs for more info.
npx -y @smithery/cli install ironbee-ai/ironbee-devtools --client <SMITHERY-CLIENT-NAME> --key <SMITHERY-API-KEY>HTTP Transport
To use HTTP transport, start the server with:
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000The server exposes the following endpoints:
GET /health- Health checkGET /ping- Ping endpointGET /mcp- MCP protocol infoPOST /mcp- MCP protocol messagesDELETE /mcp- Delete session
Important: When configuring remote MCP servers, use the actual URL where your server is hosted:
- If running locally:
http://localhost:3000/mcp(orhttp://127.0.0.1:3000/mcp) - If hosted remotely:
https://your-server.com/mcp(replace with your actual server URL)
MCP Inspector
Test the server using the MCP Inspector:
# For stdio transport
npx -y @modelcontextprotocol/inspector npx -y @ironbee-ai/devtools
# For HTTP transport (start server first)
npx -y @ironbee-ai/devtools --transport=streamable-http --port=3000
# Then in another terminal:
npx -y @modelcontextprotocol/inspector http://localhost:3000/mcp --transport httpCLI Tools
IronBee DevTools includes standalone CLI tools for both platforms:
ironbee-devtools-cli: Browser platform—navigation, screenshots, interaction, a11y, debugging, etc.ironbee-node-devtools-cli: Node platform—connect to Node.js processes, tracepoints, logpoints, exceptionpoints
This is particularly useful for:
- Scripting and automation: Use in shell scripts, CI/CD pipelines, or automated workflows
- Session-based testing: Maintain browser state across multiple commands with session IDs
Installation
The CLIs are included with the npm package:
# Run directly with npx
npx -y -p @ironbee-ai/devtools ironbee-devtools-cli --help
npx -y -p @ironbee-ai/devtools ironbee-node-devtools-cli --help
# Or install globally
npm install -g @ironbee-ai/devtools
ironbee-devtools-cli --help
ironbee-node-devtools-cli --helpTo install Playwright browser binaries (required for the browser CLI when not using a system browser), run npx playwright install chromium (see Playwright browser binaries).
Global Options
| Option | Description | Default |
|--------|-------------|---------|
| --port <number> | Daemon server port | 2020 |
| --session-id <string> | Session ID for maintaining browser state across commands | (none) |
| --json | Output results as JSON | false |
| --quiet | Suppress log messages, only show output | false |
| --verbose | Enable verbose/debug output for troubleshooting | false |
| --timeout <ms> | Timeout for operations in milliseconds | 30000 |
| --no-telemetry | Disable anonymous usage telemetry for this invocation | false |
Browser Options
| Option | Description | Default |
|--------|-------------|---------|
| --headless / --no-headless | Run browser in headless (no visible window) or headful mode | true |
| --persistent / --no-persistent | Use persistent browser context (preserves cookies, localStorage) | false |
| --user-data-dir <path> | Directory for persistent browser context user data | ./ironbee-devtools |
| --use-system-browser | Use system-installed Chrome instead of bundled browser | false |
| --browser-path <path> | Custom browser executable path | (none) |
Note: Browser options are applied when the daemon server starts. If the daemon is already running, stop it first (daemon stop) then start with new options.
Node CLI Commands
ironbee-node-devtools-cli provides Node.js backend debugging:
ironbee-node-devtools-cli
├── daemon # Manage the daemon server
├── session # Manage Node.js debugging sessions
├── tools # List and inspect available tools
├── config # Show current configuration
├── completion # Generate shell completion scripts
├── interactive (repl) # Start interactive REPL mode
├── update # Check for updates
└── debug # Debug commands
├── connect # Connect to Node.js process (pid, processName, inspectorPort, containerId, etc.)
├── disconnect # Disconnect from current process
├── status # Show connection status
├── put-tracepoint # Set a tracepoint
├── put-logpoint # Set a logpoint
├── put-exceptionpoint # Configure exception catching
└── ... # Watch, snapshots, probes managementBrowser CLI Commands
ironbee-devtools-cli organizes tools into domain-based subcommands. Object parameters (e.g. screenshotOptions, snapshotOptions) must be passed as a JSON string: --screenshot-options '{"outputPath":"/tmp","name":"myshot"}' or --snapshot-options '{"interactiveOnly":false}'. Boolean parameters with default true can be turned off with --no-<kebab-flag> (e.g. --no-wait-for-navigation). Run ironbee-devtools-cli navigation go-to --help (or the relevant subcommand) to see all options.
ironbee-devtools-cli
├── daemon # Manage the daemon server
│ ├── start # Start the daemon server
│ ├── stop # Stop the daemon server
│ ├── restart # Restart the daemon server (stop + start)
│ ├── status # Check daemon server status
│ └── info # Get detailed daemon info (version, uptime, sessions)
├── session # Manage browser sessions
│ ├── list # List all active sessions
│ ├── info <session-id> # Get information about a session
│ └── delete <session-id> # Delete a specific session
├── tools # Inspect available tools
│ ├── list # List all tools (with --domain filter)
│ ├── info <tool-name> # Get detailed tool info and parameters
│ └── search <query> # Search tools by name or description
├── config # Show current configuration
├── completion # Generate shell completion scripts
│ ├── bash # Generate bash completion script
│ └── zsh # Generate zsh completion script
├── interactive (repl) # Start interactive REPL mode
├── update # Check for and install updates
├── navigation # Navigation commands
│ ├── go-to # Navigate to a URL
│ ├── go-back-or-forward # Navigate back or forward in history (direction: back | forward)
│ └── reload # Reload the page
├── content # Content extraction commands
│ ├── take-screenshot # Take a screenshot
│ ├── get-as-html # Get HTML content
│ ├── get-as-text # Get text content
│ └── save-as-pdf # Save as PDF
├── interaction # Interaction commands
│ ├── click # Click an element
│ ├── fill # Fill a form field
│ ├── hover # Hover over an element
│ ├── press-key # Press a keyboard key
│ ├── select # Select from dropdown
│ ├── drag # Drag and drop
│ ├── scroll # Scroll the page
│ ├── resize-viewport # Resize viewport
│ └── resize-window # Resize browser window
├── a11y # Accessibility commands
│ └── take-aria-snapshot # Take ARIA snapshot
├── accessibility # Extended accessibility commands
│ └── take-ax-tree-snapshot # Take AX tree snapshot
├── o11y # Observability commands
│ ├── get-console-messages # Get console logs
│ ├── get-http-requests # Get HTTP requests
│ ├── get-web-vitals # Get Web Vitals metrics
│ ├── get-trace-context # Get current trace context
│ ├── new-trace-id # Generate new trace ID
│ └── set-trace-context # Set trace context
├── react # React debugging commands
│ ├── get-component-for-element
│ └── get-element-for-component
├── run # Batch execute (MCP parity): run execute --code '…' or --file path.js
│ └── execute
├── stub # HTTP stubbing commands
│ ├── mock-http-response # Mock HTTP responses
│ ├── intercept-http-request # Intercept requests
│ ├── list # List stubs
│ └── clear # Clear stubs
├── sync # Synchronization commands
│ └── wait-for-network-idle # Wait for network idle (configurable idle time / threshold)
├── debug # Non-blocking debugging commands
│ ├── put-tracepoint # Set a tracepoint (captures call stack)
│ ├── remove-probe # Remove a tracepoint, logpoint, or watch by ID (type + id)
│ ├── list-probes # List tracepoints, logpoints, and/or watches (optional types; omit to list all)
│ ├── put-logpoint # Set a logpoint (evaluates expression)
│ ├── put-exceptionpoint # Enable exception catching
│ ├── add-watch # Add a watch expression
│ ├── clear-probes # Clear tracepoints, logpoints, and/or watches (optional types; omit to clear all)
│ ├── get-probe-snapshots # Get tracepoint/logpoint/exceptionpoint snapshots (1 frame captured; default scopes: local only; 20 vars/scope; override: maxCallStackDepth, includeScopes, maxVariablesPerScope)
│ ├── clear-probe-snapshots # Clear tracepoint/logpoint/exceptionpoint snapshots (optional types; omit to clear all)
│ └── status # Get debugging status
└── figma # Figma integration commands
└── compare-page-with-designUsage Examples
Basic Navigation and Screenshot
# Navigate to a URL
ironbee-devtools-cli navigation go-to --url "https://example.com"
# Take a screenshot
ironbee-devtools-cli content take-screenshot --name "homepage"Browser Options
Configure browser behavior when starting the daemon:
# Run browser in headful mode (visible window)
ironbee-devtools-cli --no-headless navigation go-to --url "https://example.com"
# Use persistent browser context
ironbee-devtools-cli --persistent --user-data-dir ./my-profile navigation go-to --url "https://example.com"
# Use system Chrome instead of bundled Chromium
ironbee-devtools-cli --use-system-browser navigation go-to --url "https://example.com"
# Use a custom browser executable
ironbee-devtools-cli --browser-path /path/to/chrome navigation go-to --url "https://example.com"Session-Based Workflow
Maintain browser state across multiple commands using session IDs:
# Start a session and navigate
ironbee-devtools-cli --session-id my-session navigation go-to --url "https://example.com"
# Interact with the page (same session)
ironbee-devtools-cli --session-id my-session interaction click --selector "button.login"
# Fill a form
ironbee-devtools-cli --session-id my-session interaction fill --selector "#username" --value "[email protected]"
# Take a screenshot
ironbee-devtools-cli --session-id my-session content take-screenshot --name "after-login"
# Clean up session when done
ironbee-devtools-cli session delete my-sessionJSON Output for Scripting
Use --json and --quiet flags for machine-readable output:
# Get page content as JSON
ironbee-devtools-cli --json --quiet --session-id test navigation go-to --url "https://api.example.com"
# Output:
# {
# "url": "https://api.example.com/",
# "status": 200,
# "statusText": "",
# "ok": true
# }Daemon Management
# Check daemon status
ironbee-devtools-cli daemon status
# Start daemon manually
ironbee-devtools-cli daemon start
# Stop daemon
ironbee-devtools-cli daemon stop
# Restart daemon (useful when changing browser options)
ironbee-devtools-cli daemon restart
# Check status with JSON output
ironbee-devtools-cli daemon status --json
# Output: {"status":"running","port":2020}
# Get detailed daemon information
ironbee-devtools-cli daemon info
# Output:
# Daemon Server Information:
# Version: 0.5.0
# Port: 2020
# Uptime: 5m 23s
# Sessions: 2Session Management
# List all active sessions
ironbee-devtools-cli session list
# Output:
# Active Sessions (2):
# my-session
# Created: 2025-01-26T10:00:00.000Z
# Last Active: 2025-01-26T10:05:30.000Z
# Idle: 30s
# #default
# Created: 2025-01-26T09:55:00.000Z
# Last Active: 2025-01-26T10:04:00.000Z
# Idle: 1m 30s
# Get info about a specific session
ironbee-devtools-cli session info my-session
# Delete a session
ironbee-devtools-cli session delete my-sessionTool Discovery
# List all available tools
ironbee-devtools-cli tools list
# Output:
# Available Tools (35 total):
#
# navigation:
# go-to Navigate the browser to the given URL...
# go-back-or-forward Navigate back or forward in history (direction: back | forward)
# ...
# Filter tools by domain
ironbee-devtools-cli tools list --domain interaction
# Search for tools by keyword
ironbee-devtools-cli tools search click
# Output:
# Tools matching "click" (2 found):
#
# interaction/click
# Clicks an element on the page.
# ...
# Get detailed info about a specific tool
ironbee-devtools-cli tools info navigation_go-to
# Output:
# Tool: navigation_go-to
# Domain: navigation
#
# Description:
# Navigate the browser to the given URL...
#
# Parameters:
# --url <string> (required)
# The URL to navigate to
# --wait-until <load | domcontentloaded | commit> (optional)
# When to consider navigation succeeded
# Default: "load"
#
# Usage:
# ironbee-devtools-cli navigation go-to [options]Configuration
# Show current configuration
ironbee-devtools-cli config
# Output:
# Current Configuration:
#
# Daemon:
# Port: 2020
# Session Idle (sec): 300
# Idle Check Interval: 30
#
# Browser:
# Headless: true
# Persistent: false
# ...
# Show config as JSON
ironbee-devtools-cli config --jsonVerbose/Debug Mode
Enable verbose output for troubleshooting:
# Run any command with --verbose for detailed debug logs
ironbee-devtools-cli --verbose navigation go-to --url "https://example.com"
# Output:
# [2025-01-26T10:00:00.000Z] [DEBUG] Verbose mode enabled
# [2025-01-26T10:00:00.001Z] [DEBUG] CLI version: 0.5.0
# [2025-01-26T10:00:00.001Z] [DEBUG] Node version: v20.10.0
# [2025-01-26T10:00:00.001Z] [DEBUG] Platform: darwin
# [2025-01-26T10:00:00.002Z] [DEBUG] Checking if daemon is running on port 2020
# [2025-01-26T10:00:00.010Z] [DEBUG] Daemon health check result: running
# [2025-01-26T10:00:00.011Z] [DEBUG] Calling tool: navigation_go-to
# [2025-01-26T10:00:00.011Z] [DEBUG] Tool input: { url: "https://example.com" }
# ...Tool Search
Find tools by keyword:
# Search for tools related to "screenshot"
ironbee-devtools-cli tools search screenshot
# Output:
# Tools matching "screenshot" (2 found):
#
# content/take-screenshot
# Takes a screenshot of the current page or a specific element.
#
# figma/compare-page-with-design
# Compares the CURRENT PAGE UI against a Figma design snapshot...
# Search for tools related to "network"
ironbee-devtools-cli tools search networkShell Completions
Enable tab completion for faster command entry. Shell completions require a one-time setup:
For Bash:
# Option 1: Add to ~/.bashrc (recommended)
echo 'eval "$(ironbee-devtools-cli completion bash)"' >> ~/.bashrc
source ~/.bashrc
# Option 2: Or add manually to ~/.bashrc
eval "$(ironbee-devtools-cli completion bash)"For Zsh (macOS default):
# Option 1: Add to ~/.zshrc (recommended)
echo 'eval "$(ironbee-devtools-cli completion zsh)"' >> ~/.zshrc
source ~/.zshrc
# Option 2: Or add manually to ~/.zshrc
eval "$(ironbee-devtools-cli completion zsh)"Using with npx:
# If using npx instead of global install:
echo 'eval "$(npx -y -p @ironbee-ai/devtools ironbee-devtools-cli completion zsh)"' >> ~/.zshrc
source ~/.zshrcAfter setup, press TAB for completions:
ironbee-devtools-cli dae<TAB> # Completes to "daemon"
ironbee-devtools-cli daemon st<TAB> # Shows "start", "stop", "status", "restart"
ironbee-devtools-cli --<TAB> # Shows all global optionsInteractive REPL Mode
Start an interactive session for continuous command entry:
# Start in headless mode (default)
ironbee-devtools-cli interactive
# Start with visible browser window
ironbee-devtools-cli --no-headless interactive
# Start with persistent context (preserves cookies, localStorage)
ironbee-devtools-cli --no-headless --persistent interactive
# Aliases
ironbee-devtools-cli repl
ironbee-devtools-cli --no-headless replExample session:
IronBee DevTools CLI - Interactive Mode
Type "help" for available commands, "exit" to quit
browser> navigation go-to --url "https://example.com"
url: https://example.com/
status: 200
ok: true
browser> content take-screenshot --name "homepage"
path: /path/to/homepage.png
browser> interaction click --ref "Login"
clicked: true
browser> interaction fill --ref "Email" --value "[email protected]"
filled: true
browser> tools search screenshot
Found 2 tools:
content_take-screenshot - Take a screenshot of the current page
content_save-as-pdf - Save the current page as a PDF file
browser> daemon info
Version: 0.5.0
Uptime: 5m 23s
Sessions: 1
Port: 2020
browser> session list
Active sessions: 1
#default (idle: 30s)
browser> config
Current Configuration:
port = 2020
headless = false
persistent = true
...
browser> exit
Goodbye!Available commands in interactive mode:
| Command | Description |
|---------|-------------|
| help | Show available commands |
| exit, quit | Exit interactive mode |
| status | Show daemon status summary |
| config | Show current configuration |
| daemon <cmd> | Daemon management (start, stop, restart, status, info) |
| session <cmd> | Session management (list, info, delete) |
| tools <cmd> | Tool discovery (list, search, info) |
| update | Check for CLI updates |
| <domain> <tool> | Execute a tool |
Check for Updates
Keep your CLI up to date:
# Check for updates without installing
ironbee-devtools-cli update --check
# Output:
# Checking for updates...
#
# Current version: 0.5.0
# Latest version: 0.5.1
#
# ⚠ Update available: 0.5.0 → 0.5.1
#
# To update, run:
# npm install -g @ironbee-ai/devtools@latest
# Check and install updates interactively
ironbee-devtools-cli update
# Output:
# ...
# Do you want to update now? (y/N) y
# Updating...
# ✓ Update complete!Shell Script Example
#!/bin/bash
SESSION="test-$(date +%s)"
CLI="ironbee-devtools-cli --json --quiet --session-id $SESSION"
# Navigate
$CLI navigation go-to --url "https://example.com"
# Get text content
CONTENT=$($CLI content get-as-text)
echo "Page content: $CONTENT"
# Take screenshot
$CLI content take-screenshot --name "test-result"
# Cleanup
ironbee-devtools-cli session delete $SESSIONDaemon Architecture
The CLI uses a daemon server architecture for efficient browser management:
- Auto-start: The daemon starts automatically when you run any tool command
- Shared browser: Multiple CLI invocations share the same browser instance
- Session isolation: Each session ID gets its own isolated browser context
- Auto-cleanup: Idle sessions are automatically cleaned up after inactivity
- Full tool set: The daemon exposes the same tools as MCP (including execute for batch execution). Most tools map to domain subcommands (e.g.
navigation go-to). execute maps torun execute(not listed undertools list, which only reflects the static tool registry). - Platform env: The browser CLI forces
PLATFORM=browseron the daemon it spawns (and the Node CLI forcesPLATFORM=node), so a shell-widePLATFORM=nodecannot accidentally makeironbee-devtools-clistart a Node-platform daemon. If you still see errors, checkerror.messageon failedPOST /callresponses — the daemon includes the underlying exception message there.
The daemon listens on port 2020 by default. Use --port to specify a different port.
Configuration
The server can be configured using environment variables. Configuration is divided into server-level settings and platform-specific settings.
Server Configuration
| Variable | Description | Default |
|----------|-------------|---------|
| PORT | Port for HTTP transport | 3000 |
| TELEMETRY_ENABLE | Set to false to disable anonymous usage telemetry | (unset) |
| SESSION_IDLE_SECONDS | Idle session timeout (seconds) | 300 |
| SESSION_IDLE_CHECK_SECONDS | Interval for checking idle sessions (seconds) | 30 |
| SESSION_CLOSE_ON_SOCKET_CLOSE | Close session when socket closes | false |
| HTTP_SESSION_SHARE_ENABLE | Streamable-http mode: every client that initializes without an explicit mcp-use-session-id header joins one fixed shared session, so all connections share the same tool session context (browser, page, buffers) | false |
| TOOL_OUTPUT_SCHEMA_DISABLE | When true, omit tool output schema from MCP tool registration (can reduce token usage for some clients) | false |
| TOOL_NAME_PREFIX | Optional string prepended to every MCP-registered tool name (stdio / streamable HTTP only), including execute. MCP-facing TypeScript text is rewritten by applyNormalizedToolNamesInText in src/config.ts: only angle-bracket-wrapped substrings that match a registered canonical tool id are replaced with the prefixed name, so plain words like “execute” are never rewritten. README and non-MCP comments should use backticks only, e.g. navigation_go-to and callTool('navigation_go-to', …). In normalized sources (tool descriptions, server instructions, execute templates), authors wrap cross-tool references in angle brackets inside those string literals so clients receive the correct prefixed names. ToolRegistry.runTool also accepts a name that is a single bracket-wrapped id. Unrelated bracket tokens are left unchanged. CLI is unchanged. | (unset) |
| AVAILABLE_TOOL_DOMAINS | Optional comma-separated list of tool domains to enable. When set, only tools from these domains are registered; unset means all tools. Browser domains: a11y, content, debug, figma, interaction, navigation, o11y, react, run, stub, sync. Node domains: debug, run. Example: AVAILABLE_TOOL_DOMAINS=navigation,interaction,a11y | (all tools) |
Tool inputs are validated with a strict schema; unknown or misspelled argument keys (e.g. port instead of inspectorPort) cause a validation error.
Node Platform Configuration
| Variable | Description | Default |
|----------|-------------|---------|
| NODE_SERVER_INSTRUCTIONS_ENABLE | When true, include server instructions in MCP server info | true |
| NODE_POLICY_DEBUGGING_ENABLE | When true, include NODE_DEBUGGING_POLICY in server policies | false |
| NODE_CONSOLE_MESSAGES_BUFFER_SIZE | Maximum console messages to buffer from Node.js process | 1000 |
| NODE_INSPECTOR_HOST | Inspector host for debug_connect when MCP runs in Docker (e.g. host.docker.internal). Use with host-mapped inspectorPort so the MCP connects to the right address. | 127.0.0.1 |
| PLATFORM | Platform to use: browser or node | browser |
Browser Platform Configuration
| Variable | Description | Default |
|----------|-------------|---------|
| BROWSER_SELECTOR_TIMEOUT_MS | Default wait for an element in the interaction tools (per-call timeoutMs overrides it) | 10000 |
| BROWSER_NAVIGATION_WAIT_TIMEOUT_MS | Default budget for an action-triggered navigation plus its network-idle settle (per-call waitForTimeoutMs overrides it) | 30000 |
| BROWSER_SNAPSHOT_SCOPE_TIMEOUT_MS | How long a scoped a11y_take-aria-snapshot waits before falling back to the whole page | 5000 |
| BROWSER_SERVER_INSTRUCTIONS_ENABLE | When true, include server instructions in MCP server info | true |
| BROWSER_POLICY_UI_DEBUGGING_ENABLE | When true, include UI_DEBUGGING_POLICY in server policies | false |
| CONSOLE_MESSAGES_BUFFER_SIZE | Maximum console messages to buffer | 1000 |
| HTTP_REQUESTS_BUFFER_SIZE | Maximum HTTP requests to buffer | 1000 |
| BROWSER_HEADLESS_ENABLE | Run browser in headless mode | true |
| BROWSER_PERSISTENT_ENABLE | Use persistent browser context (preserves cookies, localStorage, etc.). Required for React tools to work optimally. | false |
| BROWSER_PERSISTENT_USER_DATA_DIR | Directory for persistent browser context user data | ./ironbee-devtools |
| BROWSER_CDP_ENDPOINT_URL | CDP attach: http://host:port, or ws://… directly. HTTP URLs are resolved like agent-browser (/json/version, /json/list, then ws://…/devtools/browser). Chromium only. | (unset) |
| BROWSER_CDP_ENABLE | When true and no endpoint URL: probes 127.0.0.1:9222 then :9229 (HTTP + WebSocket CDP discovery). With BROWSER_CDP_ENDPOINT_URL, connects only to that host/port. | false |
| BROWSER_CDP_OPEN_INSPECT | On loopback CDP failure, if Chrome is running, opens chrome://inspect/#remote-debugging so you can enable remote debugging. The server does not start Chrome — start it yourself with --remote-debugging-port=9222. Set false to never open. | true |
| BROWSER_USE_INSTALLED_ON_SYSTEM | Use system-installed Chrome browser instead of Playwright's bundled browser | false |
| BROWSER_EXECUTABLE_PATH | Custom browser executable path | (uses Playwright default) |
| BROWSER_CHROMIUM_SANDBOX | When false, launches Chromium with --no-sandbox. Required for Docker/Lambda/CI. | true |
| BROWSER_LAUNCH_ARGS | Extra Chromium launch args (comma-separated). e.g. --disable-dev-shm-usage,--single-process | (none) |
| BROWSER_ALLOWED_DOMAINS | Comma-separated list of allowed hostnames. When set, requests to non-matching hosts are aborted — but only the ones a context.route handler sees: navigation, subresources, XHR/fetch and iframes. WebSocket handshakes, redirect hops and requests a service worker's fetch handler serves are not intercepted, so they are never checked — Playwright continues a redirect internally and fires no new route event, so a chain starting on an allowed host can land on a host that is not listed. Treat this as a page-level navigation guard, not a complete egress control. Subdomains match automatically (example.com matches www.example.com). | (unset — no restriction) |
| BACKEND_ALLOWED_DOMAINS | The same egress allowlist for the backend platform. When set, request_http / request_graphql / request_replay (each redirect hop included), request_websocket-open, request_grpc targets and db_connect hosts outside the list are refused before a socket is opened. Subdomains match automatically; loopback is not implicitly allowed — list localhost / 127.0.0.1 explicitly if local targets are intended. | (unset — no restriction) |
| BROWSER_HTTP_HEADERS_SEED | Host-scoped default headers the embedding environment supplies to the browser platform, as JSON: {"host[:port]": {"header-name": "value"}}. A context-level route handler adds them to requests whose host matches a seed key, so the agent never has to know they exist — but coverage is only what context.route intercepts: WebSocket connections are not intercepted, and neither is a request a service worker's fetch handler serves, so neither is seeded (nothing sets the context option that would disable service workers). In the other direction, a redirect off a seeded host carries the headers to the target host as well, because Playwright creates no route for a redirect hop and replays the first hop's override verbatim — so seed only hosts whose redirect targets you trust. Read only when the browser platform is active. The key is compared against the request's URL.host, so write a bare host or host:port. Matching is therefore host-scoped, not origin-scoped: URL.host is identical for https:// and http://, and a key cannot carry a scheme, so a seeded value also rides plaintext requests to that host — seed hosts you reach over https, or loopback. Keys are trimmed and lower-cased and then stored verbatim: there is no URL parse, no shape rule and no default-port canonicalisation, so a key no URL.host can ever equal — h.test:443, since an https request's own host omits the default port, or a bare 8080, which is a host and not a port — is accepted in silence and simply never matches. A non-default port such as :8443 is kept and matched. Header names are trimmed and lower-cased; values are kept byte-exact (not trimmed) and accept ${file:…} secret references. The only names refused are the six framing headers (upgrade, keep-alive, transfer-encoding, expect, content-length, connection), since undici throws on each per request and a seed carrying one would break every request to that host; every other name is accepted, including the ones a route override or a request tool later displaces. Skipping is per entry: a host mapped to something other than an object, a non-string value, or a framing header warns and is skipped while its sibling hosts and headers still apply, and a host left with no usable header does not appear at all. Malformed JSON, or a top level that is not an object of host → headers, warns and yields no seeds. Duplicates are silent — the last spelling of a host key or header name wins. An unresolvable ${file:…} reference throws instead of warning. Warnings are emitted while src/config.ts is still loading, before file logging is initialised, so they reach stderr only and never appear in the log file. | (unset) |
| BACKEND_HTTP_HEADERS_SEED | The backend counterpart, same JSON shape and same host keys. One shared parser serves both vars, with the one shared framing-header check and no platform-specific name rule on either side. Matching is host-scoped, not origin-scoped: URL.host is identical for https:// and http://, and a key cannot carry a scheme, so a seeded credential also rides plaintext requests to that host — seed hosts you reach over https, or loopback. Merged under the headers the agent sets via request_set-default-headers, so for the same host and header name the agent's
