web-ui-tester
web-ui-tester is an MCP server that lets an AI drive and inspect real web pages in persistent browser sessions for UI testing and debugging.
Start, list, and close browser sessions; sessions persist cookies, page state, and history across calls.
Navigate, click, type, press keys, hover, select options, scroll, wait, go back, and handle dialogs.
Inspect pages via accessibility-tree snapshots with element refs, text reads, queries, and screenshots.
Diagnose with console logs, network logs, request/response details, JS evaluation, and element inspection (computed styles, box model).
Delegate multi-step UI tasks to a built-in browser agent via
run_task, returning structured findings and harness-observed errors.Discover and call additional page/DevTools tools: WebMCP tools published by sites and chrome-devtools-mcp tools (Lighthouse, traces, emulation, etc.).
Attach to an existing Chrome over CDP or expose the launched browser to other CDP clients.
Run as a stdio or HTTP MCP server, with configuration via env vars and CLI flags.
Integrates with Google Generative AI (Gemini) for the built-in run_task browser agent, using GOOGLE_GENERATIVE_AI_API_KEY and Gemini models such as gemini-flash-lite-latest to drive multi-step UI tasks and return structured findings.
Drives Google Chrome (or Microsoft Edge/Playwright Chromium) to provide persistent browser sessions, accessibility-tree snapshots with element refs, page interaction, console/network diagnostics, JS evaluation, and CDP/DevTools capabilities.
Exposes Lighthouse audits through the devtools.* tools, allowing the AI to run performance, accessibility, and related audits against the current page.
Click on "Deploy 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., "@web-ui-tester Open the login page, click sign in, and check the console for errors."
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.
web-ui-tester
An MCP server that lets an AI drive and inspect real web pages quickly, over browser sessions that stay alive between tool calls.
Two things make it fast. Pages are exposed as an accessibility tree with element refs rather than screenshots or raw HTML, so the model can find and click things without burning context on markup or waiting on vision. And sessions persist — cookies, page state, and history survive across calls, so a long interaction is a series of cheap steps instead of repeated cold starts.
It also carries DevTools-grade diagnostics — console, network with response bodies, JS evaluation, computed styles — so the AI can work out why something is broken, not just that it is.
Quick start
Claude Desktop (one click)
Go to the latest release and download
web-ui-tester-<version>.mcpb. The same file works on macOS, Windows and Linux.Double-click it. Claude Desktop installs the extension and offers four optional settings: a Gemini and an Anthropic API key (only for
run_task), the agent model, and headless mode.Start a new chat and ask Claude to open a page.
The extension runs on the Node.js that ships with Claude Desktop and brings no browser of its own: it drives Google Chrome or Microsoft Edge if one is installed, or Playwright's Chromium if you have installed that.
As a Claude plugin (Claude Code)
claude plugin marketplace add hofmeister/web-ui-tester
claude plugin install web-ui-tester@web-ui-tester
npx playwright@1.63.0 install chromium # once, unless Google Chrome or Microsoft Edge is installedThe plugin runs the server from the TypeScript source in this repository with your own node (22.18 or newer), and Claude Code installs its dependencies from package-lock.json when you install the plugin. It asks for four optional settings: a Gemini and an Anthropic API key (only for run_task, kept in your system's secure credential store), the agent model, and whether the browser runs headless.
Then ask Claude something like "Open http://localhost:3000, sign up with a test account and tell me what breaks."
To try a working copy, run claude --plugin-dir . in the repository, and claude plugin validate . before you push.
Other MCP clients
claude mcp add web-ui-tester -- npx -y web-ui-testerWith a key for the built-in agent (see run_task):
claude mcp add web-ui-tester \
-e GOOGLE_GENERATIVE_AI_API_KEY=your-key \
-- npx -y web-ui-testerOr in any MCP client's config file:
{
"mcpServers": {
"web-ui-tester": {
"command": "npx",
"args": ["-y", "web-ui-tester"],
"env": { "GOOGLE_GENERATIVE_AI_API_KEY": "your-key" }
}
}
}The server uses Playwright's Chromium when it is installed, and otherwise an installed Google Chrome or Microsoft Edge. To install Playwright's Chromium:
npx playwright install chromiumRelated MCP server: Charlotte
Example prompts
"Open http://localhost:3000, sign up with a new test account, and tell me whether anything errors along the way — console, network or UI."
"Go to our staging checkout page, add the cheapest product to the cart, and check that the total matches the item price plus shipping."
"Why does the 'Save' button on /settings do nothing? Click it and look at the console, the network request and the button's computed styles."
"Log in to the admin as demo@example.com / demo-password and use
run_taskto check that every link in the sidebar opens a page without errors."
How a session works
browser_start → sessionId, kept alive across calls
browser_navigate → page state + snapshot with [ref=eN] handles
browser_click ref=e12 → act on what the snapshot showed you
browser_snapshot → fresh refs after the page changes
browser_close → done (or let it idle out after 30 minutes)Everything after browser_start takes that sessionId. The snapshot is the thing to get used to:
- generic [ref=e1]:
- heading "Signup" [level=1] [ref=e2]
- textbox "Name" [ref=e5]:
- /placeholder: Your name
- combobox "Plan" [ref=e7]
- button "Create account" [ref=e10]
- link "Go to second page" [ref=e12] [cursor=pointer]:
- /url: /second.htmlThose refs go straight into browser_click, browser_type, and the rest. They belong to the page state that produced them: after navigating or a DOM change, snapshot again. When a tool says a ref is no longer valid, re-snapshot rather than retry — the message says so explicitly.
Element-addressing tools also accept css, or role + name, when you already know the selector and would rather skip the snapshot.
Tools
Session — browser_start (options: userAgent, viewportWidth, viewportHeight, headless, baseUrl, url, model, devtools, and for CDP cdpUrl, useBrowserProfile, tab), browser_list, browser_close.
Interaction — browser_navigate, browser_click, browser_type, browser_press_key, browser_hover, browser_select_option, browser_scroll, browser_wait_for, browser_go_back, browser_handle_dialog.
Actions report what they caused: navigation, new console errors, request counts, and any dialog that appeared come back with the result, so a click that quietly broke something doesn't look like a success.
Dialogs need one note. An alert/confirm/prompt blocks the page until it's answered, so the action that opened it can't also answer it — an unanswered dialog is dismissed automatically rather than stalling the click, and the result says so. To accept one, or to fill in a prompt, call browser_handle_dialog before the action that triggers it and the answer is armed for the next dialog.
Inspection — browser_snapshot (scopeable by element, depth-limited, interactiveOnly, offset-paged), browser_query (find by role/name, text, or CSS — returns refs and state), browser_read_text (rendered text of the page or one subtree), browser_screenshot (available, but the tree is usually the better tool).
Diagnostics — browser_console (messages plus uncaught errors with stacks), browser_network (statuses, sizes, timings), browser_request_detail (headers, timing breakdown, request and response bodies), browser_evaluate (run JS in the page), browser_inspect_element (computed styles, box model, form state).
More tools — browser_list_tools, browser_tool_schema, browser_call_tool; see below.
Every result is capped to a character budget, and the large ones (browser_snapshot, browser_read_text, bodies) page with offset instead of truncating silently.
The built-in agent
run_task hands a session to a fast model that drives the browser itself and reports back:
run_task(sessionId, "Log in as demo@example.com / hunter2 and check the
dashboard loads without errors")Reporting is the point. It returns a structured verdict, not just prose:
status: success
model: google:gemini-flash-lite-latest
Logged in and opened the dashboard. The revenue widget rendered empty.
findings (3):
[error] Request failed: GET 500 [observed by the harness]
where: https://app.example.com/api/revenue
evidence: HTTP 500
[error] Console exception on the page [observed by the harness]
where: app.js:214:9
evidence: TypeError: Cannot read properties of undefined (reading 'total')
[warning] The revenue widget shows no empty state, just blank space
where: #revenue-card
evidence: card is present but contains no textFindings come from two places, and the distinction matters. The agent calls report_finding as it goes — so a run that hits its step limit still returns everything it found up to that point. Separately, the harness records every console error, failed request, and dialog during the run and reports those whether or not the agent mentions them, marked [observed by the harness]. A model that misses a 500 or forgets to mention an exception can't hide it.
The agent has the same page and DevTools tools as the caller, as list_tools, tool_schema and call_tool, so a cheap model can use a site's WebMCP tools or run a Lighthouse audit without any of it passing through the calling model's context.
The same report is returned as structuredContent against a declared output schema, so a calling AI can branch on findings[].severity rather than parse text. A task can succeed and still have findings; success reflects whether the task was accomplished, not whether the page was clean.
This is the one part that needs an API key. It defaults to Gemini Flash Lite for latency; Anthropic works too:
Default model | Key | |
|
| |
Anthropic |
|
|
Set WUT_MODEL to pick (anthropic, or google:gemini-flash-latest, or any provider:modelId). A session can override it via browser_start's model, and a single call via run_task's model. Every other tool works without a key.
Page and DevTools tools
Three generic tools reach tools this server doesn't define itself. An MCP client can't pick up new tools partway through a conversation, so the AI discovers and calls them through these instead:
browser_list_tools sessionId → webmcp.* and devtools.* tools for this page
browser_tool_schema sessionId, name → description + JSON input schema
browser_call_tool sessionId, name, argumentswebmcp.* — tools the site publishes. Pages can offer their own tools through WebMCP: registered from script (document.modelContext.registerTool(…)) or declared on a form (<form toolname="…" tooldescription="…">). They're read from the page over the DevTools protocol on every call, so the list follows navigation and re-renders. The listing flags tools the site marks consequential or as returning untrusted content. It's the site's own code: treat its output as the site's word, and a consequential tool as one that can place orders or send messages. WebMCP needs Chrome 150 or newer; browsers this server launches have the feature switched on, and a Chrome you attach to needs --enable-features=WebMCP.
devtools.* — chrome-devtools-mcp's tools: performance traces and insights, Lighthouse audits, device and network emulation, heap snapshots, and more. The server runs chrome-devtools-mcp itself (it's installed as a dependency) against the session's browser, so nothing else needs configuring. They're on by default: each launched browser gets a private DevTools port on 127.0.0.1, at a random number, for chrome-devtools-mcp to connect to (browser_start reports it). browser_start devtools: false, or WUT_DEVTOOLS=0 for every session, launches without one — and without these tools. Sessions attached over CDP always have them. Calls land on the session's own tab: its pageId parameter is hidden and filled in for you. Element uids for these tools come from devtools.take_snapshot, not from browser_snapshot's refs.
HTTP mode
web-ui-tester --port 7399
claude mcp add --transport http web-ui-tester http://127.0.0.1:7399/mcpIn this mode the browser sessions live in the long-running server rather than in a client-owned process, so they survive client restarts and reconnects — reconnect, pass the same sessionId, and the page is still there. GET /health reports session and connection counts.
It binds to 127.0.0.1 by default, where DNS-rebinding protection is enabled. --host widens that, and the server warns when you do: there is no authentication, and anyone who can reach the port can drive a browser and run JavaScript through it. Put it behind a proxy or firewall.
Chrome DevTools Protocol (CDP)
CDP works in both directions.
Attach to a Chrome that is already running
Point the server at a Chrome started with remote debugging, and sessions drive that browser instead of launching one:
# Chrome 136+ ignores --remote-debugging-port on your default profile, so give it its own directory
google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.chrome-debug"
claude mcp add web-ui-tester -e WUT_CDP_URL=http://127.0.0.1:9222 -- npx -y web-ui-testerOr per session: browser_start with cdpUrl: "http://127.0.0.1:9222" (a ws://…/devtools/browser/… URL works too).
By default an attached session uses that browser's own profile — its cookies and logins — in a new tab, and keeps the browser's own User-Agent and window size. It only ever acts on tabs it opened (or popups they open), never on the tabs you have open. Two options change that:
tab: "<url substring>"takes over an existing tab instead of opening one — handy for picking up a page you logged in to by hand. Closing the session leaves that tab open.useBrowserProfile: falseuses a fresh isolated context inside the attached browser, as a launched browser would.
Closing a session closes only the tabs it opened; stopping the server disconnects without closing Chrome.
Expose the launched browser to other CDP clients
Set WUT_CDP_PORT (or --cdp-port) and the browser the server launches listens for DevTools-protocol clients on that local port; browser_start and browser_list report the endpoint. Another MCP server, a Playwright script (chromium.connectOverCDP) or plain curl http://127.0.0.1:9222/json/list can then work on the same pages as web-ui-tester.
MCP clients generally cannot add a server partway through a conversation, so give the port a fixed value and configure the other server up front — it connects when it is first used, by which time the browser is running:
claude mcp add web-ui-tester -e WUT_CDP_PORT=9222 -- npx -y web-ui-tester
claude mcp add chrome-devtools -- npx -y chrome-devtools-mcp@latest --browserUrl http://127.0.0.1:9222If the port is taken, or a second browser is launched (headed and headless run separately), it gets a free port instead; 0 always picks a free one. The port is bound to 127.0.0.1, but any local process can drive the browser through it. (Launched browsers already get a random private port for the devtools.* tools unless WUT_DEVTOOLS=0; WUT_CDP_PORT just makes it predictable.)
Configuration
Variable | Default | Purpose |
|
| Model for |
| — | Key for Gemini |
| — | Key for Anthropic |
|
| Default User-Agent for new sessions |
|
| Default headless mode |
|
| Close sessions unused this long |
|
| Character cap per tool result |
|
| Timeout for a single element action |
|
| Default step budget for |
| — | Explicit Chromium binary |
| — | Attach to this running Chrome over CDP instead of launching one |
| — | Expose launched browsers' DevTools protocol on this local port ( |
|
| Default for |
| installed copy | Command that starts chrome-devtools-mcp (the endpoint flags are appended), e.g. |
| — | Where Playwright looks for browsers |
CLI flags: --port, --host, --headless / --no-headless, --idle-timeout, --cdp-url, --cdp-port, --version, --help.
If Playwright's expected Chromium revision isn't installed but another one is, the server finds and uses it rather than failing — handy in prebuilt containers. WUT_EXECUTABLE_PATH overrides the search entirely.
Development
npm install
npm run build
npm test # agent loop (mocked model) + full end-to-end suite
npm run typechecknpm run bundle (after npm run build) builds the Claude Desktop extension into bundles/.
npm test runs the agent loop against a scripted mock model, then drives the built server as a real MCP client over both transports against a local fixture app — covering refs, stale-ref handling, diagnostics, session persistence across reconnects, and idle reaping. npm run test:agent:live additionally exercises run_task against a real provider, and skips itself when no key is set.
CI runs the typecheck, build, a start of the server from source, and both suites on Node 22 and 24 for every push and pull request. The live agent test runs separately — on demand via the Live agent test workflow, and weekly — because it makes real API calls; it needs GOOGLE_GENERATIVE_AI_API_KEY or ANTHROPIC_API_KEY as a repository secret, and the scheduled run skips itself when neither is set.
Releasing
Run the Release workflow from the Actions tab and pick patch, minor or major. It works off master: the tests run, the new version is written to package.json, .claude-plugin/plugin.json and src/index.ts, committed and tagged (vX.Y.Z), and the Claude Desktop extension is built and attached to a new GitHub Release. The version counts up from the newest vX.Y.Z tag; with no tags yet, the version already in package.json is released as it stands. Pushing a tag vX.Y.Z that matches package.json releases the commit it points at.
Privacy
The server runs on your computer. It has no server of its own, collects no analytics or telemetry, and sends nothing to its author or to Anthropic.
What it runs and fetches: a local Chromium-based browser (Playwright's Chromium, or your installed Google Chrome or Microsoft Edge, in a fresh temporary profile that never touches your own browsing profile), through Playwright, which loads the pages you or Claude point it at — along with everything those pages load themselves — and runs JavaScript in them when
browser_evaluateis called. Treat it like any browser you hand to someone else: it can reach whatever your computer can reach, includinglocalhostand your intranet.What it sends to AI providers: only
run_taskdoes. It sends the task, the page's accessibility snapshots, and the results of the agent's browser actions to the model provider you configured — Google's Gemini API (generativelanguage.googleapis.com) or Anthropic's API (api.anthropic.com) — with your own API key. Every other tool is local, and without a keyrun_taskis off.What it stores: nothing on disk. Browser sessions use fresh in-memory profiles; their cookies, storage, console and network logs live in memory and are discarded when a session is closed, idles out (30 minutes by default), or the server stops. API keys are kept by Claude Code in your system's secure credential store and held only in memory while the server runs.
Third parties: the sites you visit see an ordinary browser (User-Agent
AITester/1.0by default). Google or Anthropic receive therun_taskdata above under their own API terms and privacy policies (Google, Anthropic). Tool results go back to Claude as part of your conversation.CDP: with
WUT_CDP_URLset, sessions drive the Chrome you point them at, by default in its own profile — the sites see your cookies and logins, and anything the session does happens there. WithWUT_CDP_PORTset, the launched browser accepts DevTools-protocol connections from any process on your computer. Both are off unless you set them; see CDP.Page and DevTools tools:
webmcp.*tools run code the site supplies, inside the page.devtools.*tools run chrome-devtools-mcp as a local child process with its usage statistics, CrUX lookups and update checks switched off; it sends nothing anywhere of its own accord. For it, each launched browser listens on a random127.0.0.1DevTools port that any local process could also use;WUT_DEVTOOLS=0turns that off.HTTP mode (
--port) has no authentication; see HTTP mode. The plugin uses stdio and does not open a port.Contact: open an issue at github.com/hofmeister/web-ui-tester/issues for questions about privacy or security.
Support
Report bugs and ask questions at github.com/hofmeister/web-ui-tester/issues. Report security vulnerabilities privately, as described in SECURITY.md.
License
MIT — see LICENSE.
Available Tools
26 toolsbrowser_call_toolCall a page or DevTools toolA
Runs a tool from browser_list_tools against the session's page, with arguments matching its browser_tool_schema. WebMCP tools are code the site supplies: their output is the site's word, and one marked CONSEQUENTIAL can take real actions (orders, payments, messages).
Inputs: name (required), sessionId (required), arguments, timeoutMs.
browser_clickClickA
Clicks an element. Address the element by ref (from the latest browser_snapshot), or by css, or by role+name. Reports any navigation, console errors, or network activity the click triggered.
Inputs: sessionId (required), css, ref, name, +5 more.
browser_closeClose sessionA
Closes a browser session and frees its resources.
Inputs: sessionId (required).
browser_consoleConsole logA
Returns buffered console messages and uncaught page errors (with stacks). Check this whenever the page misbehaves — it usually names the failure directly.
Inputs: sessionId (required), clear, level, limit, +1 more.
browser_evaluateEvaluate JavaScriptA
Runs JavaScript in the page and returns the JSON-serialized result. Accepts a bare expression ("document.title") or a function ("el => el.value"). When an element is targeted, it is bound to el. Use it to read state the accessibility tree does not expose.
Inputs: sessionId (required), expression (required), css, ref, +4 more.
browser_go_backGo backB
Navigates back in history and returns the new page state with fresh refs.
Inputs: sessionId (required).
browser_handle_dialogHandle dialogA
Answers an alert/confirm/prompt. A dialog blocks the page until it is answered, so an unanswered one is dismissed automatically rather than stalling the action that opened it. Call this BEFORE the action that triggers a dialog to arm the answer — that is the only way to accept one or supply prompt() text. Called while a dialog is open, it answers that dialog immediately.
Inputs: accept (required), sessionId (required), promptText.
browser_hoverHoverA
Hovers an element, e.g. to reveal a menu or tooltip. Address the element by ref (from the latest browser_snapshot), or by css, or by role+name.
Inputs: sessionId (required), css, ref, name, +2 more.
browser_inspect_elementInspect elementARead-only
DevTools-style inspection of one element: tag, attributes, box model, form state, and computed styles. Use it to diagnose layout and visibility problems.
Inputs: sessionId (required), css, ref, name, +3 more.
browser_listList sessionsARead-only
Lists open browser sessions with their current URL, age, and idle time.
Inputs: no named parameters.
browser_list_toolsList page and DevTools toolsARead-only
Lists tools beyond this server's own that can run against the session's page, by qualified name: "webmcp." for tools the site itself publishes through WebMCP (read live — they change as the page navigates), and "devtools." for chrome-devtools-mcp's tools (performance traces, Lighthouse, emulation, heap snapshots…), which this server runs for you — no extra MCP server to configure. Follow with browser_tool_schema, then browser_call_tool.
Inputs: sessionId (required), source.
browser_networkNetwork logARead-only
Lists network requests the session has made, with status, size, and duration. Each line carries an #id for browser_request_detail. WebSockets appear as WS entries with their frame counts. Filter by URL substring or by failure status.
Inputs: sessionId (required), limit, filter, status.
browser_press_keyPress keyB
Presses a key, optionally focused on an element. Key names follow Playwright ("Enter", "Escape", "ArrowDown", "Control+a").
Inputs: key (required), sessionId (required), css, ref, +3 more.
browser_queryQuery elementsARead-only
Finds elements by role+name, visible text, or CSS, and returns a compact line per match including its ref and visible/enabled state. Use this instead of a full snapshot when you already know what you are looking for.
Inputs: sessionId (required), css, name, role, +2 more.
browser_read_textRead textARead-only
Returns the rendered text of the page or of one element subtree — the readable content without markup. Use it to verify copy, read results, or check an error message.
Inputs: sessionId (required), css, ref, name, +4 more.
browser_request_detailRequest detailARead-only
Inspects one request from browser_network: headers, timing breakdown, request body, or response body. Small text responses are cached, so they stay readable after navigation. For a WebSocket entry, any part returns its frame stream.
Inputs: id (required), sessionId (required), part, offset, +1 more.
browser_screenshotScreenshotARead-only
Captures a JPEG of the page or an element. Use this only for genuinely visual questions (layout, styling, rendering); browser_snapshot and browser_read_text are faster and cheaper for finding and verifying content.
Inputs: sessionId (required), css, ref, name, +3 more.
browser_scrollScrollA
Scrolls an element into view, or scrolls the page by a pixel delta when no element is given.
Inputs: sessionId (required), dx, dy, css, +4 more.
browser_select_optionSelect optionA
Selects one or more options in a . Address the element by ref (from the latest browser_snapshot), or by css, or by role+name.
Inputs: values (required), sessionId (required), css, ref, +3 more.
browser_snapshotSnapshot pageARead-only
Returns the accessibility tree of the page as compact YAML, with a [ref=eN] handle on every element. This is the primary way to see the page — use these refs to click and type. Far cheaper than HTML or screenshots. Scope it with ref/css/role, cap it with depth, or page through it with offset when a page is large.
Inputs: sessionId (required), css, ref, name, +7 more.
browser_startStart browser sessionA
Opens a new browser session and returns its sessionId. The session (cookies, storage, page state) stays alive across tool calls until closed or idle-timed-out, so you can interact with the same page over many turns.
Inputs: tab, url, model, cdpUrl, +7 more.
browser_tool_schemaGet a tool's schemaARead-only
Full description and JSON input schema of a tool from browser_list_tools, e.g. "webmcp.search" or "devtools.performance_start_trace".
Inputs: name (required), sessionId (required).
browser_typeType textA
Types text into an input or textarea. Address the element by ref (from the latest browser_snapshot), or by css, or by role+name.
Inputs: text (required), sessionId (required), css, ref, +5 more.
browser_wait_forWait for conditionA
Waits for text to appear, text to disappear, or a selector to become visible. Use after actions that trigger async updates.
Inputs: sessionId (required), text, selector, textGone, +1 more.
run_taskRun UI taskA
Delegates a multi-step UI task to a fast built-in browser agent, which drives the session itself and reports back. Use it for goal-shaped work ("log in as demo@example.com and check the dashboard loads", "walk the checkout flow and report anything broken") rather than driving each click yourself.
Returns a structured report: a success flag, a summary, and findings — each with a severity, what is wrong, where, and the evidence observed. Findings come from two places: what the agent noticed, and what the harness itself recorded (console errors, failed requests, dialogs), so problems are reported even when the agent does not mention them or runs out of steps. The session is left on whatever page the agent ended on, so you can inspect it further with the browser_* tools.
Inputs: sessionId (required), instruction (required), model, maxSteps, +1 more. Returns: model, steps, success, summary, +6 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 26 tools
Most tools have clearly distinct purposes: interaction (click/type/hover/press_key/select_option), navigation, and session management are unambiguous. The main soft overlap is among the page-reading tools (browser_snapshot, browser_query, browser_read_text, browser_inspect_element, browser_screenshot), but the descriptions explicitly explain when to prefer each, so misselection risk is low.
Nearly all tools use a browser_ prefix with snake_case, which is highly predictable. Slight deviation: some are verb-first (browser_navigate, browser_click) while others are noun-first (browser_console, browser_network, browser_snapshot), and run_task drops the prefix, but the style is coherent overall.
At 26 tools the surface is on the heavy side, but browser automation is a genuinely broad domain spanning sessions, interaction, inspection, network, dialogs, and delegation. Few tools feel redundant, though the count is borderline rather than tightly scoped.
The surface covers the full automation lifecycle: session start/list/close, navigation and history, element interaction, form filling, dialog handling, waiting, accessibility/text/visual inspection, JS evaluation, console and network diagnostics, plus a meta-tool layer and a delegated run_task agent. No obvious dead ends for typical UI testing.
Maintenance
Related MCP Connectors
Give AI agents a real cloud Chrome: open sessions, navigate, read pages, click, type and screenshot.
Hosted browser for AI agents: screenshots, post-JS DOM, console, WCAG. No install, no API key.
Let your AI agent operate any website through a real, logged-in browser session.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables AI agents to browse and interact with web pages through a persistent headless Chromium session, serving compact structured orientations, targeted element queries, and full detail only when explicitly requested. It supports navigation, observation, form filling, monitoring, and session management while cutting token overhead by up to ~140x versus raw accessibility-tree dumps.4 npm-
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to browse and interact with websites through a persistent headless Chromium session, returning compact structured page representations instead of full accessibility-tree dumps. Agents can navigate, query specific elements and forms, click, type, manage tabs and cookies, and monitor console or network activity while paying a fraction of the tokens.4 npm-
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to browse and interact with web pages through a token-efficient, structured page representation — orientation summaries, targeted element queries, and full detail only on request — instead of raw accessibility-tree dumps. Supports navigation, interaction, forms, screenshots, console and network monitoring, session/tab management, and browser-based development auditing.4 npm-
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to browse and interact with web pages through a persistent headless Chromium session, returning compact structured page summaries, targeted element queries, and full detail only on request. This keeps token usage far below full accessibility-tree snapshots while still supporting navigation, forms, screenshots, and session control.4 npm-