Skip to main content
Glama

YaviControl

Let Claude Code and Codex drive the Chrome you're already signed into.

Most browser-automation tooling for AI agents launches its own clean browser — no cookies, no sessions, no logins. That's the right default for CI, and the wrong one when you want an agent to read your Gmail, post from your LinkedIn, pull a report out of a dashboard behind SSO, or check something on a site you authenticated into six months ago.

YaviControl is a Manifest V3 extension plus a small local bridge. Load the extension into your everyday Chrome profile and your agent works the browser you already use — logged in, extensions and all. Load it into the managed profile instead when you want isolation. Same tool, your choice.

Claude Code ─stdio(MCP)─▶ mcp/server.js ─HTTP─┐
                           ├─▶ bridge/server.js ─WS─▶ YaviControl extension ─▶ Chrome
Codex / CLI ─HTTP POST────── tools/yavi.js ───┘   (hub: HTTP + WS, dependency-free)

Everything is loopback-only and dependency-free apart from the MCP SDK.

Why not Playwright MCP or Chrome DevTools MCP?

Use those when you want a disposable, reproducible browser — they're excellent at it, and they're maintained by Microsoft and Google respectively.

Reach for YaviControl when the session is the point:

Playwright MCP / Chrome DevTools MCP

YaviControl

Browser used

Spawns its own instance by default

Whichever profile you load the extension into

Your logins

Absent — fresh profile

Present, if you use your everyday profile

Setup

npx, nothing to install in Chrome

Load an unpacked extension once

Raw CDP

Partial

Full debugger.* passthrough

Trusted input

Varies

CDP clicks/keys that work on reCAPTCHA, Stripe, Turnstile

Best for

Tests, scraping public pages, CI

Anything behind a login you already have

They are not mutually exclusive — plenty of people run both and pick per task.

Related MCP server: Tabryn

Requirements

  • Google Chrome 116 or newer

  • Node.js 18 or newer

Quick start

git clone https://github.com/Yavinesh2025/YaviControl.git
cd YaviControl
npm --prefix mcp install

Then pick how you want the extension to run.

Option A — your everyday Chrome (keeps your logins)

  1. Open chrome://extensions

  2. Enable Developer mode

  3. Load unpacked → select the extension/ folder

  4. Start the bridge: npm start (or double-click start-bridge.cmd)

The toolbar badge shows ON in green once connected. This is the mode that gives an agent access to your signed-in sessions — see Security notes before you use it, because it means exactly what it sounds like.

Option B — managed profile (isolated, no logins)

node tools/launch-chrome.js

One command: starts the bridge, opens Chrome with a dedicated profile at %LOCALAPPDATA%\YaviControl\ChromeProfile, loads the extension over CDP (Extensions.loadUnpacked, which still works on Chrome 137+ after branded Chrome dropped --load-extension), and verifies the handshake.

It also passes --silent-debugger-extension-api, --no-default-browser-check, and --hide-crash-restore-bubble, so the debugger infobar never shifts page geometry — which keeps trusted click coordinates accurate — and startup bubbles never cover the page.

Windows shortcut: double-click start-yavichrome.cmd, or npm run chrome.

Confirm it works

node tools/yavi.js doctor

[READY] Browser control is available. means the bridge and the extension are both connected.

Use it from Claude Code (MCP)

claude mcp add --transport stdio yavicontrol -- node "$PWD/mcp/server.js"

Or add it to ~/.claude.json with an absolute path:

{
  "mcpServers": {
    "yavicontrol": {
      "type": "stdio",
      "command": "node",
      "args": ["C:/path/to/YaviControl/mcp/server.js"]
    }
  }
}

Restart Claude Code, run /mcp to confirm yavicontrol is connected, then ask for something like "Go to news.ycombinator.com and list the top 5 story titles."

The MCP server starts the hub automatically. If no extension is connected it will also launch the managed profile for you — set YAVICONTROL_AUTOLAUNCH=0 to disable that, which you want if you're using Option A.

Tools: browser_navigate, browser_screenshot, browser_get_content, browser_click, browser_type, browser_press_key, browser_evaluate, browser_wait_for, browser_scroll, browser_list_tabs, browser_switch_tab, browser_back, browser_forward.

Use it from Codex or the terminal (HTTP + CLI)

Start the hub if nothing else has:

node bridge/server.js     # or: npm start

Change the port with YAVICONTROL_PORT=32200 (then save the matching URL in the extension popup).

node tools/yavi.js health
node tools/yavi.js commands
node tools/yavi.js open https://example.com
node tools/yavi.js command tabs.query '{"active":true,"currentWindow":true}'
node tools/yavi.js command browser_click '{"selector":"#submit"}'
node tools/yavi.js command browser_type '{"selector":"[contenteditable]","text":"hello"}'
node tools/yavi.js eval active "document.title"
node tools/yavi.js cdp 123 Runtime.evaluate '{"expression":"location.href","returnByValue":true}'
node tools/yavi.js screenshot active screenshot.png

HTTP API

POST /command:

{ "command": "tabs.query", "params": { "active": true, "currentWindow": true } }
{ "id": "cmd-...", "type": "response", "ok": true, "result": [] }

If more than one Chrome profile is connected, GET /health lists each extension.sessions[].sessionId. Pass that sessionId in the command body, or set YAVICONTROL_SESSION_ID, so commands can't silently hit the wrong profile.

Both front-ends converge on the same hub, so Claude Code and Codex can share one running browser.

Control surface

High-level browser_* tools — shadow-DOM-piercing selectors, wait and scroll helpers, plus:

  • browser_click is trusted by default (mode "auto"): a real CDP click that works on reCAPTCHA, Stripe, and Turnstile, with a synthetic fallback. x/y are CSS pixels, matching screenshot pixels 1:1.

  • browser_press_key sends trusted CDP key presses (Enter, Tab, arrows, …).

  • browser_type handles regular inputs and contenteditable rich editors (Gmail, Notion, Docs-style).

  • browser_screenshot auto-scales the PNG so 1 image pixel = 1 CSS pixel, fixing the Windows DPI/zoom "clicked in the wrong place" problem.

Low-level Chrome + CDP:

  • tabs.* / windows.* — navigation and window control

  • scripting.execute — injected script functions

  • debugger.* — raw Chrome DevTools Protocol

  • input.click / input.type — via the debugger protocol

  • cookies.getAll, history.search, downloads.download, storage.*

  • chrome.call — call any available Chrome extension API by path

node tools/yavi.js commands prints the live list.

Extension popup

The toolbar action shows live bridge state, a manual Reconnect, and the WebSocket URL. The URL is deliberately restricted to ws://127.0.0.1:<port>/ws or ws://localhost:<port>/ws.

Extension ID

Pinned to:

kjgcjhjkedeiliffkaajbmbaenifdcna

Chrome normally derives an unpacked extension's ID from its install path, so it would otherwise differ per machine and change whenever the folder moves. The key field in extension/manifest.json holds the public half of an RSA keypair, and Chrome derives the ID from that instead. node tools/validate.js re-derives it and fails if the two ever drift apart.

The private key is not in this repository. It's needed only to sign a .crx — the pinned ID survives without it:

chrome.exe --pack-extension=extension --pack-extension-key=yavicontrol-key.pem

Troubleshooting

Start with node tools/yavi.js doctor.

Symptom

Recovery

Bridge is not reachable

Run node bridge/server.js, or node tools/launch-chrome.js for the full stack.

Bridge running, Chrome not connected

Confirm the unpacked extension is enabled, or open the managed profile with node tools/launch-chrome.js.

Popup says auto reconnect is paused

Choose Reconnect, or re-enable Auto reconnect and save.

More than one Chrome session connected

Run doctor, then set YAVICONTROL_SESSION_ID to the session you want.

Port already in use

Reuse the running bridge, or set YAVICONTROL_PORT and save the same port in the popup.

Extension updated while popup was open

Close and reopen the popup so it binds to the new service worker.

A Chrome internal page won't respond

Navigate to a normal http:///https:// page — Chrome blocks extensions on internal and Web Store pages.

Validate

node tools/validate.js   # static checks: manifest, icons, pinned ID, command coverage
node tools/smoke.js      # isolated bridge + request-protection checks
node tools/test.js       # popup / reconnect / bridge regression tests
node tools/launch-chrome.js --temp-profile --exit-after-verify   # full handshake

Security notes

This is authorised local browser automation for a single operator. It requests broad Chrome permissions and exposes raw CDP on purpose. Read this section before using Option A.

  • Running in your everyday profile means an agent can act as you on every site you're signed into — read mail, send messages, move money. That is the feature, and it is also the risk. Use the managed profile if you aren't comfortable with that.

  • Any local process that can reach the bridge can drive your browser. The bridge refuses non-loopback hosts, requires Content-Type: application/json, and rejects browser Origin headers, so a drive-by web page can't send commands. WebSocket clients must present a chrome-extension://<id> origin. But there is no per-caller authentication — run only software you trust.

  • browser_evaluate, scripting.execute, and debugger.eval run arbitrary JavaScript in the page by design. browser_evaluate runs in the page's MAIN world and can be blocked by a strict page CSP; use debugger.eval there. Only send code you trust.

  • Chrome shows a "debugging this browser" banner while a debugger-based command is attached. Expected. The managed profile suppresses it with --silent-debugger-extension-api so it can't shift page geometry; a manually loaded extension will still show it.

  • Not distributable via the Chrome Web Store. Runtime evaluation of externally supplied code violates the store's Remote Code policy. Install by loading the extension unpacked.

Licence

MIT — see LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Connects AI agents to your Chrome browser via MCP, enabling real-time control of existing tabs, sessions, and application state for development workflows.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables any MCP-compatible AI agent to drive your own Chrome browser with your existing login state, filling forms, clicking elements, fetching data, and handling captchas without API keys or re-authentication.
    338 npm
    483
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to control an existing signed-in Chrome profile through MCP stdio, using its current tabs, cookies, and logins without pairing or a separate browser. It exposes tab management, page interaction, screenshots, and Chrome DevTools Protocol commands.
    293 npm
    MIT