Docs

Jev Browser Control lets Claude and Codex drive a real Chrome. Claude plans; Jev, TypeSafe's decision model, chooses the clicks when you hand it a task. The MCP server opens its own Chrome window, so there is nothing to install in your browser. If you'd rather Claude worked in your everyday Chrome, there is an extension for that.

Install

You need Node.js 18 or newer and Google Chrome. The MCP server starts on your computer whenever Claude or Codex starts, and opens a Chrome window the first time it is used.

Add your key

Every browser step is one Jev call, and typing a value is one call to a small text model. Both come off your prepaid credits.

  1. Create an account in the dashboard. Your key (it starts with jbc_) is shown once, so copy it.
  2. Add credits by card, from $10. Credits don't expire.
  3. Pass the key when you connect Claude or Codex (next step), with -e JBC_API_KEY=jbc_….

To keep the key out of Claude's and Codex's config, put it in a file on your computer instead, and leave out -e in the next step:

mkdir -p ~/.jev-browser-control
echo 'JBC_API_KEY=jbc_…your key…' >> ~/.jev-browser-control/config.env
chmod 600 ~/.jev-browser-control/config.env

Each call costs five times what OpenRouter charges for it. Your dashboard lists every call and what it cost.

Connect Claude and Codex

Claude Code

claude mcp add -s user -e JBC_API_KEY=jbc_…your key… jev-browser -- npx -y https://jevbrowsercontrol.com/downloads/jev-browser-control-mcp-0.4.2.tgz

Or paste the key into Claude and ask it to install Jev Browser Control: it runs this command for you.

Codex

codex mcp add jev-browser --env JBC_API_KEY=jbc_…your key… -- npx -y https://jevbrowsercontrol.com/downloads/jev-browser-control-mcp-0.4.2.tgz

The first start downloads the server and Playwright, which takes about ten seconds. If Codex reports a startup timeout, add startup_timeout_sec = 60 under [mcp_servers.jev-browser] in ~/.codex/config.toml.

Claude Desktop

Settings → Developer → Edit Config, add this, and restart Claude Desktop:

{
  "mcpServers": {
    "jev-browser": {
      "command": "npx",
      "args": ["-y", "https://jevbrowsercontrol.com/downloads/jev-browser-control-mcp-0.4.2.tgz"],
      "env": { "JBC_API_KEY": "jbc_…your key…" }
    }
  }
}

From source

git clone https://github.com/nexibeo/jev-browser-control
cd jev-browser-control
node scripts/install-agents.mjs

That registers the server for Claude Code and Codex and also installs a skill and a Claude Code subagent that know how to use the tools well.

Restart Claude and ask “check the browser status”. A Chrome window opens, and Claude reports Browser: ready and Jev: jevbrowsercontrol.com credits.

The window has its own profile, in ~/.jev-browser-control/chrome-profile. When a site needs a login, sign in there yourself once; the login is kept for the next session. Several Claude and Codex sessions share the one window, and when the session that opened it ends, the next one takes over.

Your everyday Chrome: the extension

With the extension, Claude works in your normal Chrome, with your logins and open tabs. It also gives you a side panel to run tasks yourself, and it is what Grok Bot and other remote apps connect to.

  1. Download the extension (.zip, version 0.2.3) and unzip it.
  2. Open chrome://extensions and switch on Developer mode (top right).
  3. Click Load unpacked and choose the unzipped folder.
  4. Pin the orange cursor icon. Clicking it opens the side panel; the settings page opens by itself the first time. Paste your key there and press Test connection. It answers with your balance.
  5. Register the MCP server in extension mode:
claude mcp add -s user -e JBC_MODE=extension jev-browser -- npx -y https://jevbrowsercontrol.com/downloads/jev-browser-control-mcp-0.4.2.tgz

In extension mode the server opens a bridge on 127.0.0.1:10522, and the extension connects to it. “Check the browser status” should report the extension as connected, and the side panel shows Claude connected. The extension works in Chrome, Edge, Brave and other Chromium browsers, version 120 or newer. A Chrome Web Store listing is on its way; until then Chrome keeps the unpacked extension installed, it just won't update itself.

claude.ai, ChatGPT, Grok Bot and other remote AI apps

Apps that run in the cloud can't start a program on your computer. For them, jevbrowsercontrol.com runs the same tools as a remote MCP server at https://jevbrowsercontrol.com/mcp, and passes each call to your extension, so the app works in your own Chrome with your logins.

  1. Create an account in the dashboard and add credits. Remote control itself is free; Jev's calls come off your credits.
  2. In the extension's settings, under Remote AI apps, switch on “Let remote AI apps control this browser”. It uses your credits key, or a separate key you paste there. The side panel shows Remote on once it is connected.
  3. Add Jev Browser Control to the app:
    • claude.ai (and the Claude apps): Settings → Connectors → Add custom connector. Name it “Jev Browser Control”, enter the URL https://jevbrowsercontrol.com/mcp and connect.
    • ChatGPT (developer mode): create an app or connector with the same URL and choose OAuth sign-in.
    • In both, a jevbrowsercontrol.com page opens: sign in (with an email link or one of your API keys) and click Allow.

Apps that take a key instead of a sign-in, such as Grok Bot, use the URL with your key as a bearer token:

URL:           https://jevbrowsercontrol.com/mcp
Authorization: Bearer jbc_…your key…

For Grok Bot there is a ready-made template, Jev Browser Operator, that sets this up and knows how to use the tools.

Each app you allow gets its own key, named “OAuth · app name”, in your dashboard. Revoke that key to disconnect the app. The sign-in uses OAuth 2.1 with PKCE and dynamic client registration; the details are at /.well-known/oauth-authorization-server.

Anyone with a key, and any app you allowed, can control your browser while remote control is on. Keep keys secret, revoke one in the dashboard if it leaks, and switch remote control off when you don't need it. Clicks that buy, pay, send, post or delete always wait for your OK in the Jev side panel, and a remote app can't skip that.

Each remote call adds a round trip through the relay (about 0.3 seconds), and a single jev_task stops after 85 seconds, so split longer work into several tasks. Screen recordings and reading the page's clipboard work only with the MCP server on your own computer.

Use it

From Claude or Codex

Ask in plain words: “Use the browser to find the opening hours of the Rijksmuseum,” or “Fill in the contact form on example.com with my details: …”. Claude decides when to drive the browser itself and when to hand a sub-task to Jev with jev_task. Put every value that has to be typed into your request; Jev's text helper never makes up personal details. You can watch every step in the Chrome window.

From the side panel (extension)

Click the toolbar icon, type a goal such as “Find the cheapest one-way flight from Zürich to London on 20 October”, and press Run. Each step shows what Jev chose, how sure it was and how long it took. Stop ends the task at once.

Tools

ToolArgumentsWhat it does
jev_taskgoal, details, url, newTab, maxSteps, maxSeconds, allowIrreversibleRuns a task with Jev. Returns the status, every step, the cost and the final page's text.
jev_finddescriptionThe visible element that best matches a description, with probabilities.
jev_checkstatementThe probability that a statement about the page is true.
jev_stopStops running Jev tasks.
browser_snapshotfullNumbered elements and visible text. full lists the whole page.
browser_clickrefClicks element [ref].
browser_typeref, text, submitReplaces a field's text; submit presses Enter.
browser_selectref, optionChooses a dropdown option by its label.
browser_press_keykey, refEnter, Tab, Escape, arrows, or combos like Control+A.
browser_scrolldirection, amountScrolls about one screen.
browser_navigateurl, newTabOpens a URL, optionally in a new tab.
browser_tabsaction, tabIdLists tabs, or selects one.
browser_close_tabtabIdCloses a tab.
browser_backforwardHistory back or forward.
browser_readformat, offset, limitThe whole page as markdown, text or links.
browser_screenshotqualityA JPEG of the visible page.
browser_hoverrefMoves the mouse onto an element, for menus that open on hover (reaction pickers, navigation menus).
browser_clipboardThe text the page just copied, for example after a “Copy link” menu item.
browser_recordaction (start, stop), nameRecords the browser window; stop saves an MP4 on your computer and returns its path.
browser_waittext, secondsWaits for text to appear.
browser_statusBrowser, current tab, key and limits. The first call opens the Chrome window.

How a jev_task ends

StatusMeaning
doneJev chose DONE and its separate goal check agreed.
done_unconfirmedJev chose DONE but the goal check disagreed. Look at the page.
needs_confirmationThe next click may buy, pay, send, post or delete. It was not clicked.
needs_inputA field needs a value the goal doesn't give. Nothing was made up.
blocked / stuckNo useful action left, or three actions in a row changed nothing.
budgetA limit on actions, seconds or cost was reached.

Safety

  • Jev only chooses among options the page snapshot offered. Its answer is an element number that code maps to a real element; it never becomes a selector, coordinates or a script.
  • Password and file-upload fields are never offered, to Jev or to Claude.
  • Clicks that buy, pay, send, post or delete stop for confirmation (setting: on by default). So does a Comment, Reply or Send button next to a text box that holds text, because it would publish it.
  • Blocked sites: neither Jev nor Claude acts on domains you list.
  • Page text is sent to Jev as untrusted data. Prompt injection on a web page can still mislead a model, so keep limits on and check results.
  • The MCP server listens on 127.0.0.1 only. Other Claude sessions need a local token, and in extension mode only Chrome extensions can connect (web pages can't).
  • The Chrome window of the MCP server has its own profile, with only the logins you make there. The extension acts in your normal Chrome profile with all your logins; for risky work, use a separate Chrome profile.

Settings

For the MCP server's own Chrome window, put these in ~/.jev-browser-control/config.env, one per line:

LineDefault
JBC_MAX_STEPS=30, JBC_MAX_SECONDS=120, JBC_MAX_COST_USD=0.10Limits per task
JBC_BLOCKED_SITES=mybank.com,paypal.comNone. Domains the browser may not open or act on.
JBC_CONFIRM_IRREVERSIBLE=0On: tasks stop before clicks that buy, pay, send, post or delete.
JBC_HEADLESS=1Off: the window is visible.
CHROME_PATH=/path/to/chromeThe installed Google Chrome.
JBC_PROFILE_DIR=/path~/.jev-browser-control/chrome-profile

In the extension, the same choices are on its settings page:

SettingDefault
Jev model~typesafe/jev-latest (always the newest; the tilde is required)
Text modelinception/mercury-2.5
Limits per task30 actions, 120 seconds, $0.10
Ask before irreversible clicksOn
InputTrusted (Chrome shows “started debugging this browser” while Jev acts). Synthetic events avoid the bar, but some sites ignore them.
Claude bridge port10522 (set JBC_PORT for the MCP server too if you change it)

Your key stays on this computer, in config.env or in Chrome's local extension storage, and is sent only to jevbrowsercontrol.com.

Credits API

With a credits key you can call Jev from your own code. The requests and responses match OpenRouter's, so an OpenRouter client only needs a new base URL and key.

EndpointUse
POST /api/v1/decisionsJev decisions: {model, state, questions}. Also at /api/alpha/decisions.
POST /api/v1/chat/completionsThe small text models (no streaming).
GET /api/v1/balanceYour remaining credits.
GET /api/v1/modelsAllowed models and their price here.
curl https://jevbrowsercontrol.com/api/v1/decisions \
  -H "Authorization: Bearer $JBC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "~typesafe/jev-latest",
    "state": { "page": "Checkout: 2 items, total $31.50" },
    "questions": {
      "has_items": { "type": "noul", "instructions": "Does the cart in `page` contain items?" }
    }
  }'

Each response's usage.cost is what you were charged (5× OpenRouter's cost for that call), and usage.credits_remaining is your balance after it. Failed calls are free. Errors use OpenRouter's shape: 401 bad key, 402 out of credits, 429 too many requests per minute.

Troubleshooting

“Chrome could not start”

Install Google Chrome, or point CHROME_PATH in config.env at a Chrome or Chromium binary. If it says the profile is in use, a Chrome window from an earlier session is still open: close it and ask again.

“No key for Jev”

Add JBC_API_KEY=jbc_… to ~/.jev-browser-control/config.env and ask again. There is no need to restart Claude.

Claude says the extension is not connected

Keep Chrome open and click the Jev toolbar icon; that wakes the extension, and it connects within a second. Check that “Let Claude control this browser” is on in the settings, and that nothing else uses port 10522.

“This page can't be controlled by extensions”

Chrome doesn't let extensions script chrome:// pages, the Chrome Web Store or other extensions. Open a normal website first.

Clicks do nothing while DevTools is open

Only one debugger can attach to a tab. With DevTools open the extension falls back to synthetic events, which some sites ignore. Close DevTools.

Jev picked the wrong thing

Jev can be confidently wrong between look-alikes (“Cold Email” and “Cold Outreach”). Name the target precisely in the goal, and verify the result with jev_check or a snapshot.

Open source

The extension and MCP server are MIT-licensed at github.com/nexibeo/jev-browser-control. The loop's design (one request for the operation plus a target for every operation, freshness checks before input) comes from Browser Use's Jev Ultrafast, also MIT. Issues and pull requests are welcome.