jev-browser
Drives a real, indexed Google Chrome browser through the Browser Harness daemon (over CDP), letting an agent open URLs, observe a numbered table of interactive elements, and click, type into, or select those elements — while reusing the user's existing Chrome profile in an owned background tab.
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., "@jev-browserGo to Google Flights and find the cheapest round-trip from SFO to NYC next Friday."
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.
Jev Ultrafast ⚡
A browser agent with a dynamic, indexed action space.
Give it one natural-language goal. TypeSafe's Jev picks the next operation and the target element in a single request. A small LLM writes text only when the operation is TYPE_TEXT. Model output never becomes selectors, coordinates, shell commands, or executable JavaScript.
Ships with a ready-made MCP server — jev-browser. Register it once with make install and your existing coding agents — Claude Code, Codex, Qwen Code, ZCode, Cursor, VS Code, Gemini CLI, OpenCode, Google Antigravity — drive a real, indexed browser through jev_navigate / jev_observe / jev_act / jev_close on their own license. No extra API keys: your agent is the brain, the MCP server only observes and executes. See MCP server.
Watch the MP4 · Measurements · Read the loop
How it works
Every observation produces a fresh element table with stable indexes:
[1] button Change ticket type · Round trip
[2] combobox Where from? · San Francisco
[3] combobox Where to? · empty
[4] textbox Departure · emptyOperations: CLICK, TYPE_TEXT, SELECT, SCROLL_UP, SCROLL_DOWN, WAIT, DONE, BLOCKED. One TypeSafe request returns an operation plus operation-specific target heads; only the selected operation's target executes — two decisions, one network round trip.
page → element table → TypeSafe (operation + targets) → matching target → browser
└→ TYPE_TEXT → small LLM → text → browserThere are no site-specific action scripts or prepared field values. Every executed target is resolved from an observed DOM node, rechecked for freshness and click occlusion, and the outcome is verified independently — a DONE choice alone is not proof of success.
Related MCP server: OpenCode in Chrome
Installation
Prerequisites
uv —
curl -LsSf https://astral.sh/uv/install.sh | shNode.js — for JS syntax checks
Google Chrome — see Chrome remote debugging below
Browser Harness — see Browser Harness below
API keys — see TypeSafe API below
Steps
git clone https://github.com/browser-use/jev-ultrafast.git
cd jev-ultrafast
make buildmake build prepares everything: dependencies (including Browser Harness), a .env scaffold, JS syntax checks, lint, tests, and the package build.
Add your keys to .env, make sure Chrome is running, then start the inspector:
uv run jev
# open http://127.0.0.1:8766 → Start demo → Run automaticallyThe inspector shows numbered elements, operation/target probabilities, and executed actions. Choose next pauses before execution.
Browser Harness
Browser Harness is the local daemon that bridges Python and Chrome over the Chrome DevTools Protocol (CDP). It ships as a pinned dependency (browser-harness) and is installed automatically by uv sync / make build — no separate install step.
The daemon auto-starts the first time a browser session is created (demo, library, or MCP server). It attaches to your running Chrome and opens its own background tab — your active tab is never taken over, and owned tabs share your existing Chrome profile.
Check health at any time:
uv run browser-harness --version # installed version
uv run browser-harness --doctor # diagnose install, daemon, and browser stateLinux with Snap-packaged Chromium: Snap sandboxing blocks CDP. Run
uv run browser-harness doctor --fix-snapfor the fix, or use a non-Snap Chrome/Chromium.make doctorruns this check as part of the full stack report.
Chrome remote debugging
The agent drives Chrome through its remote-debugging (CDP) channel, which Browser Harness enables on first connect. You start Chrome normally — no manual --remote-debugging-port flag, no restart.
macOS: the first time the daemon connects, Chrome shows a native "Allow remote debugging" permission sheet. Click Allow, or pre-approve it from the terminal:
uv run browser-harness mac-approveLinux/Windows: no extra permission step; if the connection fails, run
uv run browser-harness --doctorand follow its output.Chrome should be open before you start the demo.
make doctorwarns if it is not running yet.
TypeSafe API
TypeSafe is the decision engine of the agent loop: each step sends it the element table, and it returns the operation plus target in a single request. Without a key, the demo and library loops cannot choose actions.
Get a key from TypeSafe, put it in
.envasTYPESAFE_API_KEY. Requests go tohttps://api.typesafe.ai/v1; the model defaults tojev-latest(override withTYPESAFE_MODEL).Who needs it: the demo inspector and the Python library loop. The MCP server does not — there your coding agent (Claude Code, Codex, Qwen Code, ZCode, …) is the brain and the server only observes and executes.
TYPE_TEXTadditionally needsTEXT_MODEL_API_KEY(any OpenAI-compatible provider — see Configuration). Without it, everything works except typing text.Only the demo, live examples, and recording scripts make paid TypeSafe calls; tests are offline and never do.
Steps
git clone https://github.com/browser-use/jev-ultrafast.git
cd jev-ultrafast
make buildmake build prepares everything: dependencies, a .env scaffold, JS syntax checks, lint, tests, and the package build.
Add your keys to .env, then start the inspector:
uv run jev
# open http://127.0.0.1:8766 → Start demo → Run automaticallyThe inspector shows numbered elements, operation/target probabilities, and executed actions. Choose next pauses before execution. When Chrome prompts for remote debugging, allow it; if the connection needs fixing, run uv run browser-harness --doctor.
Configuration
Environment variables (.env, git-ignored)
Variable | Required | Default | Purpose |
| yes | — | TypeSafe Jev: operation + target selection |
| no |
| TypeSafe model id |
| for | — | Text helper used only by |
| no |
| OpenAI-compatible endpoint |
| no |
| Text model id |
| no |
| Set to |
| no |
| Inspector port |
URLs
URL | What it is |
| Local demo inspector ( |
| TypeSafe API used by the agent loop |
| Default text-model endpoint ( |
The text helper works with any OpenAI-compatible provider — DeepSeek (https://api.deepseek.com/v1, deepseek-chat is the code-level fallback), OpenAI, Gemini, GLM, or local Ollama. Set TEXT_MODEL_BASE_URL, TEXT_MODEL, and TEXT_MODEL_API_KEY accordingly. For a programmatic custom provider, see docs/text-provider-guide.md and examples/custom_text_provider.py.
MCP server (jev-browser)
The browser layer ships as a standalone MCP stdio server (jev-mcp) so coding agents — Claude Code, Codex, Qwen Code, ZCode, Cursor, VS Code, and any other MCP client — can drive a real browser with their existing licenses. The server only observes and executes; your coding agent is the brain and makes every decision from the indexed element table. The server itself calls no model, so no API keys are required to use it.
flowchart LR
subgraph agents["Your coding agents — bring your own license"]
direction TB
CC[Claude Code]
CX[OpenAI Codex]
QW[Qwen Code]
ZC[ZCode]
MX["Cursor · VS Code · Gemini CLI · OpenCode · Antigravity"]
end
subgraph standalone["Standalone loop — demo inspector + Python library"]
direction TB
TS["TypeSafe API<br/>operation + target in one request"]
TXT["text LLM<br/>TYPE_TEXT only"]
end
MCP["jev-browser MCP server (jev-mcp)<br/>jev_navigate · jev_observe · jev_act · jev_close"]
BH["Browser Harness daemon"]
CHROME["Chrome<br/>jev's own background tab · shared profile"]
agents -- "MCP stdio — agent decides, server executes" --> MCP
TS --- TXT
MCP --> BH
standalone --> BH
BH -- "CDP" --> CHROMEThe same Browser Harness + Chrome layer serves both paths: through the MCP server your coding agent decides each step from the element table; through the standalone loop TypeSafe decides.
Tools
Tool | Arguments | Does |
|
| Open a URL; creates the browser session if needed |
|
| Return URL, title, text preview, and numbered interactive elements |
|
| Click, type ( |
| — | Close the browser session |
| API key/url/model fields | Update TypeSafe/text-model config at runtime |
One-command install
make install # register with every detected agent
make install cursor # one agent only (claude, codex, qwen, zcode, ...)
make install-dry # show what would be written, change nothing
make doctor # deps, API keys, Chrome, browser-harness, MCP registrations
uv run python scripts/install_mcp.py --status # current registration statusRegistration is idempotent: re-running replaces only the jev-browser entry and leaves every other configured server untouched.
Supported agents
Key | Agent | Config file written |
| Claude Code |
|
| OpenAI Codex CLI |
|
| Command Code |
|
| VS Code |
|
| Cursor |
|
| Qwen Code |
|
| Google Antigravity |
|
| Gemini CLI |
|
| OpenCode |
|
| ZCode |
|
Credentials are never written into agent configs. Every entry spawns uv --directory <project> run --env-file <project>/.env jev-mcp, so the server loads keys from the git-ignored .env at startup.
Manual registration (any MCP client)
{
"mcpServers": {
"jev-browser": {
"type": "stdio",
"command": "/absolute/path/to/uv",
"args": [
"--directory",
"/absolute/path/to/jev-ultrafast",
"run",
"--env-file",
"/absolute/path/to/jev-ultrafast/.env",
"jev-mcp"
]
}
}
}Replace /absolute/path/to/uv with your real uv binary (which uv, typically ~/.local/bin/uv) and /absolute/path/to/jev-ultrafast with the project directory. The absolute command matters: some agents spawn MCP servers without your shell's PATH, where a bare uv fails to resolve. --env-file loads the git-ignored .env so keys never appear in the agent config; drop that flag if you keep no .env.
Or run it by hand to verify: uv run jev-mcp from the project directory.
How agents use it
Once registered, just give your agent a goal in its normal chat — Claude Code, Codex, Qwen Code, and ZCode all drive the same three-tool loop:
You: Open google.com and search for "browser-use jev-ultrafast"
Agent: 1. jev_navigate("https://www.google.com")
2. jev_observe() → [1] textbox Search [2] button Google Search …
3. jev_act("e1", "browser-use jev-ultrafast")
4. jev_act("e2") → results page
5. jev_close()Rules the host agent should follow:
Call
jev_observeafter every navigation or action — element ids change with each snapshot, so never reuse an id from an older observation.Pass
textfor fill/type actions; click and select take onlyaction_id.If
jev_actreports an error, observe again and re-decide instead of retrying the same id.
Use as a library
The full TypeSafe loop:
from jev_ultrafast import Agent
with Agent(
"https://www.google.com/travel/flights?hl=en",
"Find one-way flights from Zurich to London on September 20, 2026, "
"for one adult in economy. Stop when matching flight options are visible.",
) as agent:
for state in agent.run():
print(state["elapsed_ms"], state["status"])Run with uv run --env-file .env python your_script.py. A generic task:
uv run --env-file .env python examples/run.py \
--url https://en.wikipedia.org/wiki/Main_Page \
--goal 'Find and open the Wikipedia article about Gödel’s incompleteness theorems.'Or swap the TypeSafe agent for your own — the browser layer is standalone:
from jev_ultrafast.browser import Browser
browser = Browser("https://example.com")
page = browser.observe() # numbered element table
action = next(a for a in page["actions"] if a["id"] == "e2")
browser.act(action, page, text="hello")See examples/external_agent.py and docs/architecture.md. examples/flights.py runs the verified flight search (--keep-open keeps the browser open).
Project layout
File | Job |
CDP connection, DOM observation, action execution | |
Atomic DOM snapshot, indexed controls, freshness guards | |
The complete loop and text-helper handoff | |
TypeSafe operation/target heads and text generation | |
| |
Local inspector ( | |
MCP registration for coding agents | |
Stack health check |
Development
uv run ruff check .
uv run pytest
node --check jev_ultrafast/static/app.js
node --check jev_ultrafast/browser/snapshot.js
uv buildTests are offline. uv run python scripts/check_guards.py checks real controls in a local browser without model calls. Live examples and the recording scripts (scripts/record_flights.py, scripts/render_demo.py) make paid API calls; credentials and raw traces stay ignored. Run boundaries and raw evidence live in docs/performance.md.
Scope and limits
The DOM reader handles common HTML and ARIA controls, not the full accessible-name specification. Shadow roots, frames, canvas, uploads, pop-up tabs, nested scrolling, and arbitrary keyboard widgets remain outside this MVP. Owned tabs share the existing Chrome profile.
Browser Use · Browser Harness · TypeSafe speculative fan-out
Available Tools
5 toolsjev_actA
Execute an action on an element. Use action_id from jev_observe.
Args: action_id: Element ID from jev_observe (e.g., 'e1', 'e2') text: Text to type (required for fill actions)
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | ||
| action_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses that text is required for fill actions and that action_id comes from observation, but says nothing about side effects, waiting behavior, error handling, or reversibility—significant gaps for a mutating execute tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the purpose, then the prerequisite, then a compact Args block that is necessary given zero schema descriptions. Every sentence earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. The description covers purpose, prerequisite, and parameters, but leaves action types and behavioral traits underspecified, which matters for an execute tool with no annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It explains action_id as an element ID from jev_observe with examples ('e1','e2') and text as required for fill actions, adding real meaning beyond the bare schema. It leaves action-type mapping somewhat implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Execute'), resource ('an action on an element'), and ties the action_id to sibling tool jev_observe, distinguishing it as the acting counterpart to observing. It does not enumerate action types, but the core purpose is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use action_id from jev_observe' gives the prerequisite and workflow relation, making it clear this tool is used after observing. It stops short of explicit when-not guidance or naming alternative siblings like jev_navigate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jev_closeB
Close the browser session.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does not say whether closing is destructive to session state, whether subsequent calls in the same session fail, or whether the operation is idempotent — all relevant for a terminate-style tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It is efficient, though arguably terse enough that it omits useful context rather than being optimally sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. However, for a session-terminating tool with no annotations, the description omits the post-close behavior (state loss, effect on other jev_* tools), leaving an agent to guess at consequences.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. Schema coverage is 100% and no additional parameter meaning is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ("Close") and resource ("browser session"), so an agent immediately knows the operation. It does not differentiate itself from siblings like jev_navigate or jev_act, but those are clearly distinct actions, so ambiguity is low.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: call this when finished with the browser session. There is no explicit statement of when to use it versus alternatives, nor any prerequisite or sequencing guidance relative to jev_observe/jev_navigate/jev_act.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jev_configB
Set or update API configuration at runtime.
Args: typesafe_api_key: TypeSafe API key for operation/target selection typesafe_base_url: TypeSafe API base URL (default: https://api.typesafe.ai/v1) text_model_api_key: Text model API key for TYPE_TEXT operations text_model_base_url: Text model API base URL (default: https://api.deepseek.com/v1) text_model: Text model name (default: deepseek-chat)
| Name | Required | Description | Default |
|---|---|---|---|
| text_model | No | ||
| typesafe_api_key | No | ||
| typesafe_base_url | No | ||
| text_model_api_key | No | ||
| text_model_base_url | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It does disclose that configuration is applied at runtime and lists per-field defaults, but it omits critical behaviors for a mutation tool: whether settings persist across sessions or are process-global, whether partial updates are allowed, and what passing null (the schema default for every field) actually does.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The primary purpose is stated in a single front-loaded sentence, followed by a compact Args list that adds real information per field. No wasted prose, though the Args block is a plain list rather than tightly integrated guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and all five parameters are documented. However, for a mutation tool with zero annotation coverage, the description should say more about persistence, permission requirements, and null/partial-update behavior before an agent could call it confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate, and it largely does: all five parameters are explained with their purpose (key vs base URL vs model name) plus defaults for the base URLs and model. The one gap is that null semantics for each optional field are never clarified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Set or update API configuration at runtime'. This is unambiguous about what the tool does. It does not explicitly differentiate itself from siblings (jev_observe, jev_navigate, jev_act, jev_close), though those are plainly a different functional domain, so differentiation is largely self-evident.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'at runtime' hints at the context of use, but there is no explicit when-to-use guidance, no prerequisites, and no statement of when not to call it. With no alternative config tool named, the agent must infer the trigger conditions on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
jev_observeA
Read current page state: URL, title, text, and interactive elements with IDs.
Args: screenshot: Include screenshot (base64 JPEG). Default: false
| Name | Required | Description | Default |
|---|---|---|---|
| screenshot | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It discloses the read-only nature implicitly ('Read') and documents the screenshot format (base64 JPEG), but says nothing about cost, latency, or performance implications of capturing a screenshot, nor anything about page-state freshness or permissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight lines, front-loaded with the core purpose followed by the parameter note. No filler sentences, and the returned fields are summarized efficiently in a single clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so explaining return values in detail is unnecessary, and for a one-parameter read tool the description is nearly sufficient. The remaining gap is the absence of any guidance on when to observe versus act, which would help an agent sequence calls.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must document the single parameter, and it does: 'screenshot: Include screenshot (base64 JPEG). Default: false'. The added format detail (base64 JPEG) goes beyond the bare boolean in the schema, though payload size or cost implications are not addressed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read current page state') and enumerates exactly what is returned: URL, title, text, and interactive elements with IDs. This distinguishes it from jev_navigate/jev_act/jev_close/jev_config by implication, but the description never explicitly names those siblings or contrasts the roles.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance and no mention of the alternative tools (jev_act, jev_navigate) or the typical observe-then-act loop. The agent can infer it is the inspection step from the name and description, but nothing is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
jev_act - First observed
jev_close - First observed
jev_config - First observed
jev_navigate - First observed
jev_observe
TDQS
Scored across 5 tools
Each tool maps to a distinct phase of browser control: observe reads state, navigate opens URLs, act performs element actions, close ends the session, and config handles configuration. The only mild overlap is that act can perform many action types, but it remains clearly separated from the read-only observe.
All five tools follow an identical 'jev_' prefix plus a concise snake_case verb pattern (observe, navigate, act, close, config), making the set highly predictable and readable.
Five tools is lean but well-scoped for a browser automation agent, with each tool earning its place in the observe-navigate-act-close loop. The addition of config is justified for runtime setup.
The core browser lifecycle (navigate, observe, act, close) is covered, and act likely encompasses clicks, typing, and scrolling via element IDs. Minor gaps like explicit back/forward navigation, tab management, or scroll-only primitives exist but agents can work around them.
Maintenance
Related MCP Connectors
Real Chrome for agents: start a browser, read pages as numbered markdown, click, type, hand off.
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Hyperbrowser MCP — wraps the Hyperbrowser AI-agent browsing API
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceLets coding agents control and inspect a live Chrome browser via MCP, providing Chrome DevTools capabilities for automation, debugging, and performance analysis.1,305,336 npmApache 2.0
- AlicenseNot gradedqualityAmaintenanceEnables local opencode agents to control a live Chrome browser via MCP tools, including tab management, JavaScript execution, clicking, form filling, page reading, screenshots, and console log retrieval.MIT
- AlicenseNot gradedqualityAmaintenanceEnables MCP clients to drive a live Chrome or Brave browser over stdio, with tools for navigation, clicking, typing, screenshots, and executing automation goals.3MIT

orchords-web-pilotofficial
FlicenseAqualityCmaintenanceEnables coding agents to drive a real Playwright-backed browser session, navigating, observing, interacting, and capturing proof on web pages via MCP tools across stdio and Streamable HTTP transports.152-