Are you the author? Sign in to claim
browser-devtools-mcp
A powerful Model Context Protocol (MCP) server that provides AI coding assistants with comprehensive browser automation and debugging capabilities using Playwright. This server enables both execution-level debugging (logs, network requests) and visual debugging (screenshots, ARIA snapshots) to help AI assistants understand and interact with web pages effectively.
Browser DevTools MCP 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.
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 browser-devtools-mcp NPM package.
No manual installation required! The server can be run directly using npx, which automatically downloads and runs the package.
Browser DevTools MCP server supports the following CLI arguments for configuration:
--transport <stdio|streamable-http> - Configures the transport protocol (defaults to stdio).--port <number> – Configures the port number to listen on when using streamable-http transport (defaults to 3000).Add the following configuration into the claude_desktop_config.json file.
See the Claude Desktop MCP docs for more info.
{
"mcpServers": {
"browser-devtools": {
"command": "npx",
"args": ["-y", "browser-devtools-mcp"]
}
}
}
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then, go to Settings > Connectors > Add Custom Connector in Claude Desktop and add the MCP server with:
Browser DevToolshttp://localhost:3000/mcp if running locally, or https://your-server.com/mcp if hosted remotely)Run the following command. See Claude Code MCP docs for more info.
claude mcp add browser-devtools -- npx -y browser-devtools-mcp
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then add the MCP server:
claude mcp add --transport http browser-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.
{
"mcpServers": {
"browser-devtools": {
"command": "npx",
"args": ["-y", "browser-devtools-mcp"]
}
}
}
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then add the configuration:
{
"mcpServers": {
"browser-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.
{
"mcp": {
"servers": {
"browser-devtools": {
"type": "stdio",
"command": "npx",
"args": ["-y", "browser-devtools-mcp"]
}
}
}
}
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then add the configuration:
{
"mcp": {
"servers": {
"browser-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.
{
"mcpServers": {
"browser-devtools": {
"command": "npx",
"args": ["-y", "browser-devtools-mcp"]
}
}
}
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then add the configuration:
{
"mcpServers": {
"browser-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.
{
"mcpServers": {
"browser-devtools": {
"type": "local",
"command": "npx",
"args": ["-y", "browser-devtools-mcp"]
}
}
}
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then add the configuration:
{
"mcpServers": {
"browser-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.
{
"mcpServers": {
"browser-devtools": {
"command": "npx",
"args": ["-y", "browser-devtools-mcp"]
}
}
}
First, start the server with HTTP transport:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
Then add the configuration:
{
"mcpServers": {
"browser-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 serkan-ozal/browser-devtools-mcp --client <SMITHERY-CLIENT-NAME> --key <SMITHERY-API-KEY>
To use HTTP transport, start the server with:
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
The server exposes the following endpoints:
GET /health - Health checkGET /ping - Ping endpointGET /mcp - MCP protocol infoPOST /mcp - MCP protocol messagesDELETE /mcp - Delete sessionImportant: When configuring remote MCP servers, use the actual URL where your server is hosted:
http://localhost:3000/mcp (or http://127.0.0.1:3000/mcp)https://your-server.com/mcp (replace with your actual server URL)Test the server using the MCP Inspector:
# For stdio transport
npx -y @modelcontextprotocol/inspector npx -y browser-devtools-mcp
# For HTTP transport (start server first)
npx -y browser-devtools-mcp --transport=streamable-http --port=3000
# Then in another terminal:
npx -y @modelcontextprotocol/inspector http://localhost:3000/mcp --transport http
The server can be configured using environment variables:
| Variable | Description | Default |
|---|---|---|
PORT | Port for HTTP transport | 3000 |
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 |
CONSOLE_MESSAGES_BUFFER_SIZE | Maximum console messages to buffer | 1000 |
HTTP_REQUESTS_BUFFER_SIZE | Maximum HTTP requests to buffer | 1000 |
BROWSER_EXECUTABLE_PATH | Custom browser executable path | (uses Playwright default) |
content_take-screenshotTakes a screenshot of the current page or a specific element.
Parameters:
outputPath (string, optional): Directory path where screenshot will be saved (default: OS temp directory)name (string, optional): Screenshot name (default: "screenshot")selector (string, optional): CSS selector for element to capturefullPage (boolean, optional): Capture full scrollable page (default: false)type (enum, optional): Image format - "png" or "jpeg" (default: "png")Returns:
filePath (string): Full path of the saved screenshot fileimage (object): Screenshot image data with mimeTypecontent_get-as-htmlRetrieves the HTML content of the current page or a specific element.
Parameters:
selector (string, optional): CSS selector to limit the HTML content to a specific containerremoveScripts (boolean, optional): Remove all script tags from the HTML (default: true)removeComments (boolean, optional): Remove all HTML comments (default: false)removeStyles (boolean, optional): Remove all style tags from the HTML (default: false)removeMeta (boolean, optional): Remove all meta tags from the HTML (default: false)cleanHtml (boolean, optional): Perform comprehensive HTML cleaning (default: false)minify (boolean, optional): Minify the HTML output (default: false)maxLength (number, optional): Maximum number of characters to return (default: 50000)Returns:
output (string): The requested HTML content of the pagecontent_get-as-textRetrieves the visible text content of the current page or a specific element.
Parameters:
selector (string, optional): CSS selector to limit the text content to a specific containermaxLength (number, optional): Maximum number of characters to return (default: 50000)Returns:
output (string): The requested text content of the pagecontent_save-as-pdfSaves the current page as a PDF document.
Parameters:
outputPath (string, optional): Directory path where PDF will be saved (default: OS temp directory)name (string, optional): PDF name (default: "page")format (enum, optional): Page format - "Letter", "Legal", "Tabloid", "Ledger", "A0" through "A6" (default: "A4")printBackground (boolean, optional): Whether to print background graphics (default: false)margin (object, optional): Page margins with top, right, bottom, left (default: "1cm" for each)Returns:
filePath (string): Full path of the saved PDF fileinteraction_clickClicks an element on the page.
Parameters:
selector (string, required): CSS selector for the element to clickinteraction_fillFills a form input field.
Parameters:
selector (string, required): CSS selector for the input fieldvalue (string, required): Value to fillinteraction_hoverHovers over an element.
Parameters:
selector (string, required): CSS selector for the element to hoverinteraction_press-keySimulates keyboard input.
Parameters:
key (string, required): Key to press (e.g., "Enter", "Escape", "Tab")interaction_selectSelects an option from a dropdown.
Parameters:
selector (string, required): CSS selector for the select elementvalue (string, required): Value to selectinteraction_dragPerforms drag and drop operation.
Parameters:
sourceSelector (string, required): CSS selector for the source elementtargetSelector (string, required): CSS selector for the target elementinteraction_evaluateExecutes JavaScript in the browser console.
Parameters:
script (string, required): JavaScript code to executeReturns:
result (any): Result of the JavaScript evaluationnavigation_go-toNavigates to a URL.
Parameters:
url (string, required): URL to navigate to (must include scheme)timeout (number, optional): Maximum operation time in milliseconds (default: 0 - no timeout)waitUntil (enum, optional): When to consider navigation succeeded - "load", "domcontentloaded", "networkidle", or "commit" (default: "load")Returns:
url (string): Final URL after navigationstatus (number): HTTP status codestatusText (string): HTTP status textok (boolean): Whether navigation was successful (2xx status)navigation_go-backNavigates backward in browser history.
navigation_go-forwardNavigates forward in browser history.
monitoring_get-console-messagesRetrieves console messages/logs from the browser with advanced filtering.
Parameters:
type (enum, optional): Filter by message level - "ERROR", "WARNING", "INFO", "DEBUG"search (string, optional): Text to search for in messagestimestamp (number, optional): Start time filter (Unix epoch milliseconds)sequenceNumber (number, optional): Only return messages after this sequence numberlimit (object, optional): Limit results
count (number): Maximum number of messagesfrom (enum): "start" or "end" (default: "end")Returns:
messages (array): Array of console messages with type, text, location, timestamp, and sequence numbermonitoring_get-http-requestsRetrieves HTTP requests from the browser with detailed filtering.
Parameters:
resourceType (enum, optional): Filter by resource type (e.g., "document", "script", "stylesheet")status (object, optional): Filter by status code range
min (number): Minimum status codemax (number): Maximum status codeok (boolean, optional): Filter by success/failure (2xx = success)timestamp (number, optional): Start time filter (Unix epoch milliseconds)sequenceNumber (number, optional): Only return requests after this sequence numberlimit (object, optional): Limit results
count (number): Maximum number of requestsfrom (enum): "start" or "end" (default: "end")Returns:
requests (array): Array of HTTP requests with URL, method, headers, body, response, timing, and metadatamonitoring_get-trace-idGets the OpenTelemetry compatible trace id of the current session.
Parameters:
Returns:
traceId (string, optional): The OpenTelemetry compatible trace id of the current session if availablemonitoring_new-trace-idGenerates a new OpenTelemetry compatible trace id and sets it to the current session.
Parameters:
Returns:
traceId (string): The generated new OpenTelemetry compatible trace idmonitoring_set-trace-idSets the OpenTelemetry compatible trace id of the current session.
Parameters:
traceId (string, optional): The OpenTelemetry compatible trace id to be set. Leave it empty to clear the session trace id, so no OpenTelemetry trace header will be propagated from browser throughout the API callsReturns:
a11y_take-aria-snapshotCaptures an ARIA (accessibility) snapshot of the current page or a specific element.
Parameters:
selector (string, optional): CSS selector for element to snapshotReturns:
output (string): Includes the page URL, title, and a YAML-formatted accessibility treeUsage:
accessibility_take-ax-tree-snapshot for comprehensive UI analysisaccessibility_take-ax-tree-snapshotCaptures a UI-focused snapshot by combining Chromium's Accessibility (AX) tree with runtime visual diagnostics.
Parameters:
roles (array, optional): Optional role allowlist (button, link, textbox, checkbox, radio, combobox, switch, tab, menuitem, dialog, heading, listbox, listitem, option). If omitted, a built-in set of interactive roles is usedincludeStyles (boolean, optional): Whether to include computed CSS styles for each node (default: true)includeRuntimeVisual (boolean, optional): Whether to compute runtime visual information (bounding box, visibility, viewport) (default: true)checkOcclusion (boolean, optional): If true, checks whether each element is visually occluded by another element using elementFromPoint() sampled at multiple points (default: false)onlyVisible (boolean, optional): If true, only visually visible nodes are returned (default: false)onlyInViewport (boolean, optional): If true, only nodes intersecting the viewport are returned (default: false)textPreviewMaxLength (number, optional): Maximum length of the text preview extracted from each element (default: 80)styleProperties (array, optional): List of CSS computed style properties to extract (default: includes display, visibility, opacity, position, z-index, colors, fonts, etc.)Returns:
url (string): The current page URL at the time the AX snapshot was capturedtitle (string): The document title of the page at the time of the snapshotaxNodeCount (number): Total number of nodes returned by Chromium Accessibility.getFullAXTree before filteringcandidateCount (number): Number of DOM-backed AX nodes that passed role filtering before enrichmentenrichedCount (number): Number of nodes included in the final enriched snapshot outputtruncatedBySafetyCap (boolean): Indicates whether the result set was truncated by an internal safety capnodes (array): List of enriched DOM-backed AX nodes combining accessibility metadata with visual diagnostics, including:
axNodeId, parentAxNodeId, childAxNodeIds: Tree structurerole, name, ignored: Accessibility propertiesbackendDOMNodeId, domNodeId, frameId: DOM referenceslocalName, id, className, selectorHint: Element identificationtextPreview: Short preview of rendered text contentstyles: Computed CSS styles (if includeStyles is true)runtime: Visual diagnostics including boundingBox, isVisible, isInViewport, and optional occlusion dataUsage:
checkOcclusion: true when investigating UI/layout problemsa11y_take-aria-snapshot tool for complete UI analysisThe server uses session-based architecture where each MCP client connection gets its own browser context and page. Sessions are automatically cleaned up when:
The server supports multiple browser engines:
Browser instances are shared across sessions for efficiency, but each session has its own isolated browser context.
Console messages and HTTP requests are buffered in memory with configurable buffer sizes. Both tools support advanced filtering:
# Clone the repository
git clone https://github.com/serkan-ozal/browser-devtools-mcp.git
cd browser-devtools-mcp
# Install dependencies
npm install
# Build the project
npm run build
npm run build - Build TypeScript to JavaScriptnpm run start - Start server with stdio transportnpm run start:http - Start server with HTTP transportnpm run watch - Watch mode for developmentnpm run inspector - Run MCP Inspector (stdio)npm run inspector:http - Run MCP Inspector (HTTP)npm run lint:check - Check code formattingnpm run lint:format - Format codeThis server enables AI assistants to:
navigation_go-tocontent_take-screenshot to see the current statemonitoring_get-console-messages for errorsmonitoring_get-http-requests to see API callsa11y_take-aria-snapshot and accessibility_take-ax-tree-snapshot to understand page structureinteraction_click, interaction_fill, etc.content_get-as-html or content_get-as-textcontent_save-as-pdf for documentationContributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.
Serkan Ozal
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official GitHub integration for repos, issues, PRs, and CI/CD workflows