browsertrace-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@browsertrace-mcpTake a screenshot of the current tab"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
BrowserTrace MCP
An unpacked Chrome MV3 extension that exposes screenshots, trusted mouse/keyboard
input, and click-to-fetch/XHR tracing through the
@sunwu51/chrome-mcp-sdk
WebSocket bridge for sunwu51/mcp-center.
The tracer does not add an OPID header or otherwise modify page requests. It
records the operation context locally in chrome.storage.local and deletes a
tab's records when the tab closes or its main document navigates.
The extension requests unlimitedStorage because captured request/response
bodies can exceed Chrome's default extension storage quota.
Build
npm install
npm run buildThen open chrome://extensions, enable Developer mode, choose Load unpacked,
and select the generated dist directory. Refresh pages that were already open
before installing or reloading the extension.
By default the extension connects to:
ws://localhost:3000/ws/browsertraceClick the extension action to change the URL or disable the bridge. MCP Center
exposes the tools with its normal server prefix, for example
browsertrace_screenshot.
This switch controls only the MCP Center WebSocket connection; direct calls
from other extensions remain enabled through the same Chrome MCP SDK tool registry.
Related MCP server: paparazzi
Direct calls from another extension
BrowserTrace also exposes the same JSON-RPC 2.0 MCP surface directly to other
installed Chrome extensions. The receiving manifest uses
externally_connectable.ids: ["*"] with matches: [], so extension callers are
allowed but ordinary web pages are not. A caller only needs the BrowserTrace
extension ID shown on chrome://extensions:
const BROWSERTRACE_ID = "<browsertrace-extension-id>";
chrome.runtime.sendMessage(
BROWSERTRACE_ID,
{ jsonrpc: "2.0", id: 1, method: "tools/list" },
(response) => console.log(response.result.tools)
);
chrome.runtime.sendMessage(
BROWSERTRACE_ID,
{
jsonrpc: "2.0",
id: 2,
method: "tools/call",
params: {
name: "screenshot",
arguments: { tabId: 123, includeImage: true }
}
},
(response) => console.log(response)
);Both transports support initialize, tools/list, tools/call, and ping.
Direct extension calls can receive inline MCP image content, snapshots, normal
JSON results, and upload screenshots to MCP Center. Restrict
externally_connectable.ids to known extension IDs if the local Chrome profile
contains untrusted extensions.
Typical agent loop
Call
tab_openand keep its returnedtabId. New tabs open in the background by default, and navigation waits forloadby default. SetwaitUntiltonone,domcontentloaded, ornetwork_idlewhen a different boundary is needed.Call
screenshot. It returns a viewport image and a compact accessibility snapshot with element UIDs.Call
cua_actionwith an elementuid, or usemouse_clickwith viewport coordinates. Keep the returnedopid.Wait for the page operation to settle.
Call
operation_get_requestswith thatopid.If OPID results are empty or incomplete, call
network_list_requestswith the sametabId, time window, and a URL/method filter. This CDP-level list does not depend on Zone-style context propagation. For normal API traffic, use"resourceTypes": ["XHR", "Fetch"]to hide Font, Script, Stylesheet, Image, and other static-resource noise. Use"resourceType": "Document"when checking native form submissions or navigation.Call
request_get_detailsfor bodies and complete page-tracer request details.
Every input CUA action generates an OPID when omitted. Supply opid directly
on the action only when a caller needs a stable custom identifier.
tab_open defaults to active: false, sets autoDiscardable: false, and puts
created tabs in the BrowserTrace MCP tab group. Supply groupName to use a
different group in that Chrome window. The debugger is attached immediately,
so its indicator is present before coordinates are measured.
popup_wait waits for a new tab opened by a managed tab and adopts only that
tab into the current MCP session; it does not enumerate or expose unrelated
Chrome tabs. Use it after an action that opens a popup or target=_blank link.
JavaScript dialogs are exposed through dialog_get, dialog_accept, and
dialog_dismiss. A pending dialog blocks the page until it is handled.
form_action provides targeted fill, select, check, and uncheck
operations. It requires a snapshot uid or portable locator, and dispatches
the normal input and change events for value changes.
Managed tabs also support tab_goto, tab_back, tab_forward, and
tab_reload; each waits for load by default and accepts the same waitUntil
and timeoutMs options as tab_open.
download_list, download_wait, and download_cancel expose only downloads
whose URL origin matches a currently managed tab. Cookie operations are
limited to the current HTTP(S) origin of a managed tab. storage_get,
storage_set, storage_remove, and storage_clear operate on that page's
localStorage or sessionStorage; they do not access extension storage or
other origins.
Screenshots use CSS-pixel output by default, so their PNG dimensions align with
CSS-coordinate bounds and CUA coordinates even when the device pixel ratio is
greater than 1. Set cssPixels: false to request native device pixels.
viewport_get reports the current CSS viewport and scale. viewport_set can
override width, height, deviceScaleFactor, and mobile emulation; pass
clear: true to remove the override.
All screenshots use CDP Page.captureScreenshot; they do not activate the tab
or focus its window. Set fullPage: true to capture the entire rendered page.
The virtual cursor is hidden during capture by default. Set hideCursor: false
to include it in viewport, full-page, element, or workflow screenshots.
If a tab was manually discarded despite autoDiscardable: false, screenshot
and snapshot operations restore it with a background reload first.
Semantic snapshots and element screenshots
screenshot always returns a compact accessibility tree. It is not a complete
HTML DOM dump: it focuses on semantic content such as buttons, links, inputs,
headings, menus, and element state. Nodes that resolve to DOM elements have
stable UIDs for the lifetime of that document. When a stable DOM attribute is
available, the line also includes a portable locator with ordered CSS/XPath
strategies; use that locator for a macro rather than the document-local UID.
Screenshots are uploaded to MCP Center temporary storage by default, and the MCP
result returns filePath as an absolute filename on the MCP Center machine.
includeImage controls only whether the PNG is also returned as MCP image
content. This avoids passing base64 through a shell command when an agent needs
a local file:
{
"tabId": 123,
"includeImage": false,
"saveToFile": true,
"name": "sign-in"
}The upload URL is derived from the configured WebSocket URL, for example
ws://localhost:3000/ws/browsertrace becomes
http://localhost:3000/fs/upload. Files are sent as binary
multipart/form-data in the file field.
Set both includeImage: false and
saveToFile: false for a semantic-only snapshot with no PNG capture. UID and
CUA screenshot actions use the same behavior.
Example snapshot output:
RootWebArea "Sign in" uid=mabc_1
textbox "Username" uid=mabc_4 required=true
textbox "Password" uid=mabc_5 required=true
button "Sign in" uid=mabc_6Pass a UID to scroll to an element, capture only its box, and return only its semantic subtree:
{ "tabId": 123, "uid": "mabc_6", "includeImage": true, "saveToFile": true }Capture the full rendered page without activating it:
{ "tabId": 123, "fullPage": true, "includeImage": true }UIDs are backed by the current document loader and CDP backend DOM node IDs. They are reused while the same DOM node survives, and become invalid after navigation or when a framework replaces the node. Capture a new snapshot after an invalid-UID error. Canvas contents and DOM nodes excluded from the accessibility tree still require coordinate CUA.
Human-like actions
cua_action accepts one action object. Supported action types are move,
hover, click, double_click, right_click, mouse_down, mouse_up,
drag, scroll, type, key_press, key_down, key_up, select_all,
clear, wait, wait_for, and screenshot.
Action parameters vary by type:
Action | Required parameters | Optional target / notes |
|
| Coordinates are the visual fallback. |
|
|
|
|
| Supply |
|
| Supply |
| None | Supply |
|
|
|
| None |
|
|
| Element states require |
| None |
|
Mouse actions accept uid instead of x/y. drag accepts fromUid and
toUid instead of coordinate pairs. Text and keyboard actions may also include
uid; the element is clicked to focus it before input. Coordinate fields remain
available as a visual fallback:
{
"tabId": 123,
"action": { "type": "click", "uid": "mabc_6", "opid": "op_login" }
}Portable locators can be passed instead of a UID. Strategies are tried in
order and must resolve to exactly one visible element (or specify nth):
{
"tabId": 123,
"action": {
"type": "click",
"locator": { "strategies": [{ "kind": "css", "value": "[data-testid='sign-in']" }] }
}
}Use wait_for rather than fixed sleeps when a later step depends on page
state. It supports present, visible, hidden, absent, and CDP-backed
network_idle (WebSocket and EventSource are ignored):
{ "tabId": 123, "action": { "type": "wait_for", "state": "visible", "locator": { "strategies": [{ "kind": "css", "value": ".results" }] }, "timeoutMs": 10000 } }Workflows and macros
Use workflow_run for every multi-step operation, including a simple linear
sequence. It also supports bounded control flow: a step is { "do": <CUA action> }, { "waitFor": <wait_for fields> }, { "if": { "when": ..., "then": [...], "else": [...] } }, or
{ "while": { "when": ..., "maxIterations": 20, "steps": [...] } }.
Conditions use the same element-state or network_idle fields as wait_for.
{ "tabId": 123, "workflow": { "steps": [
{ "do": { "type": "click", "x": 300, "y": 220 } },
{ "do": { "type": "type", "text": "sunwu" } },
{ "do": { "type": "key_press", "key": "Enter" } }
] } }Search workflow with visual checkpoints
Capture the state before and after entering a search, click a previously observed button UID, wait for the resulting requests to settle, and capture the final result:
{
"tabId": 123,
"workflow": {
"steps": [
{ "do": { "type": "screenshot", "output": "file", "name": "search-before" } },
{
"do": {
"type": "type",
"locator": { "strategies": [{ "kind": "css", "value": "input[type='search']" }] },
"text": "search today's tech news"
}
},
{ "do": { "type": "screenshot", "output": "file", "name": "search-entered" } },
{ "do": { "type": "click", "uid": "abc" } },
{ "waitFor": { "state": "network_idle", "idleMs": 500, "timeoutMs": 10000 } },
{ "do": { "type": "screenshot", "output": "file", "name": "search-results" } }
]
}
}Each screenshot step returns exactly one image output: output: "file" returns
steps[].filePath, while output: "base64" returns steps[].image. Use
snapshot when only accessibility text/UIDs are needed. Targeted actions return steps[].target, including the actual
click point and, for UID or locator targets, the element bounds. A Remotion or
HyperFrames composition can use the checkpoint images plus this per-step target
data to animate cursor movement/clicks and produce an operation walkthrough.
Every completed workflow returns a short-lived runId. Call
macro_export with that ID to return a portable, versioned macro configuration. Export only
uses the locator captured while the action ran: UIDs, OPIDs, and coordinates
are deliberately omitted. It does not save browser state; pass the returned
macro.workflow directly to workflow_run to replay it later.
Script, console, and tab tools
evaluate_scriptevaluates a JavaScript expression through CDP, awaits Promises by default, and returns a JSON-serializable value.console_listreturns capturedconsole.*calls, uncaught exceptions, and browser log entries. Uselevelandlimitto filter it.console_clearclears both stored entries and the page console.tab_closecloses a specified tab, or the active tab when omitted. PassgroupNameinstead to close every tab in all same-named groups across Chrome windows, allowing an agent to clean up all tabs it opened:
{ "groupName": "BrowserTrace MCP" }For task-scoped cleanup, supply a stable ownerId to every tab_open call,
then call session_finish with the same ID. It detaches the debugger and
closes every tab the task opened:
{ "ownerId": "agent-task-abc" }For a form field addressed by uid, type replaces the field's current value
by default (including browser-prefilled credentials). Set append: true only
when text should be appended deliberately.
Current scope and limitations
OPID traces page-world
fetchandXMLHttpRequestbut does not correlate browser/CDP request IDs.network_list_requestsseparately captures CDP Network events, including navigation and resource traffic, as a fallback. WebSocket frames and WebTransport activity are not currently listed.A lightweight page tracer propagates operation context through interaction listeners, Promise callbacks, timers, animation/idle callbacks, and
queueMicrotaskwithout installing Zone.js or replacing the page's global Promise implementation. Native async continuations or code that deliberately escapes these patched callbacks may appear as a background request withopid: null.Request and response text is capped at 64 KiB in stored records. Binary bodies are reported as unavailable.
chrome.debuggerdisplays Chrome's debugging indicator and conflicts with a DevTools/CDP debugger attached to the same tab.Restricted Chrome pages cannot be injected or controlled.
The current MCP Center WebSocket bridge does not authenticate registering clients. Keep it local until bridge authentication is added.
Development test page
Serve this repository with any local static server and open
test-page/index.html. Its button makes two delayed fetch requests, which
should appear under the single OPID returned by mouse_click.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityBmaintenanceAn MCP server that provides AI models with full browser automation capabilities through Chrome. It enables navigation, interaction, screenshots, and complete DevTools access by bridging AI clients with a companion Chrome extension.9992Apache 2.0
- Alicense-qualityDmaintenanceMCP server that connects to your browser to capture screenshots, inspect console logs, network requests, and more via Chrome DevTools Protocol.12MIT
- Alicense-qualityCmaintenanceAn MCP server for browser automation and console log capture via a Chrome extension, enabling AI-driven DOM interaction, navigation, and screenshot capabilities.2MIT
- Alicense-qualityAmaintenanceMCP server to control a real Chrome browser from Claude, enabling navigation, DOM snapshots, clicks, typing, screenshots, and JS execution via a Chrome extension bridge.MIT
Related MCP Connectors
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
A paid remote MCP for AI agent browser DevTools MCP, built to return verdicts, receipts, usage logs,
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/sunwu51/browsertrace-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server