Skip to main content
Glama

efferent

A Chrome extension and a local MCP server that let Claude use the browser it is installed in, in a window of its own, without interrupting you. With a labelled eval of 15 page shapes that break browser agents, and of every interruption.

Efferent nerves carry commands out from the brain to the muscles. This is that path for a model: Claude Code (or any MCP client) decides, the extension acts, in your own browser with your own sign-ins.

"Go to my Amazon and find a 6 ft USB-C cable rated 4.5 stars or more, under $10."

Claude opens a tab in a window of its own, behind yours, signed in as you. It searches, sorts and reads the results while you keep typing in whatever you were using. Your keyboard, mouse, tabs and screen stay yours.

Why an extension

Driving a browser over its debugging port (CDP) needs the browser started with a flag, or a permission prompt, and Chrome shows a "being controlled" bar. An extension you load yourself needs none of that. It is not in the Chrome Web Store and never will be: you load it unpacked, it talks only to 127.0.0.1, and there is no account and no server.

Claude Code ──stdio── efferent MCP server ──ws://127.0.0.1:47800── extension in your browser
  • The server listens on the first free port from 47800 to 47807, on 127.0.0.1 only, and accepts a connection only from the extension's own origin (chrome-extension://djkbgokjopagggpagplncnbanmpanhlh, fixed by the key in its manifest). A web page cannot connect to it.

  • The extension dials those ports every 2 seconds, so several Claude sessions and several browsers can be connected at once.

  • Nothing leaves your computer. There are no dependencies.

Related MCP server: zenpilot

Install

Needs Node.js 20 or newer and any Chromium browser 120 or newer: Chrome, Edge, Brave, Arc, Opera, Vivaldi, Thorium.

  1. Get the extension folder:

    npx -y github:brandonmlicea/efferent extension

    It copies the extension to ~/.efferent/extension and prints the path. (Or clone this repository and use its extension folder.)

  2. In your browser open chrome://extensions, turn on Developer mode, click Load unpacked and pick that folder.

  3. Add the server to Claude Code:

    claude mcp add efferent -s user -- npx -y github:brandonmlicea/efferent

    Any other MCP client:

    { "mcpServers": { "efferent": { "command": "npx", "args": ["-y", "github:brandonmlicea/efferent"] } } }

Optional: on the extension's Details page turn on Allow User Scripts, so eval works on pages whose security policy forbids it without falling back to the debugger.

The toolbar button shows whether a server is connected, lets you rename the browser ("Thorium", "Work Chrome") and has one switch to stop Claude from using it.

Tools

Tool

What it does

browsers

Connected browsers by name, with what each has done this session

tabs

Every tab: Claude's own, and yours, marking the one you used last

open

An address in a new tab of Claude's own window, answered with the page's elements by ref

read

A tab's elements by ref. find narrows a long page to the elements and lines holding its words (out of 5 stars | Add to cart); text adds the page's words

act

Steps in one call, waiting for the page to settle after each: click, fill (text, dropdown by option text, checkbox, rich editor), type, press, hover, scroll, go, back, wait (ms, or text to wait for)

screenshot

A picture of a tab

eval

JavaScript in a tab

close

Close a tab

Every tool takes browser to pick one by name; EFFERENT_BROWSER=Thorium sets the default.

How it stays out of your way

  • Its own window. Pages open in one window of Claude's own, created without focus and never brought to the front. Windows does not let a background app put a window over the one you are using; when you are in the browser itself, efferent raises your window straight back.

  • No focus, no tab switches. New tabs are created inactive and switched to inside Claude's window, because a tab created active in an unfocused window makes Chrome activate that window.

  • Synthetic input by default. Clicks, fills and keys are DOM events from the extension's isolated world. They work in a window that is not focused and never touch your real keyboard or mouse. Values go through the native setter, so React and other controlled inputs see them.

  • The debugger only when asked. trusted: true on a step uses chrome.debugger for real input on the rare page that checks event.isTrusted. While it is attached, Chrome shows a "started debugging this browser" bar; start the browser with --silent-debugger-extension-api to hide it.

  • Your tabs stay yours. Claude never navigates a tab in your window unless it is given that tab.

The eval

eval/cases.json is 15 hand-written cases, each a local page (eval/pages) with one shape that breaks browser agents, the steps a model would send, and a check run in the page afterwards. A case passes only when every step ran and the check holds.

Case

Shape

form

A whole signup form in one call: text, email, dropdown by option text, checkbox, radio, textarea, submit

controlled

An input that, like React, ignores a value set through the element's own setter

enter

A search box with no button, submitted by Enter

shadow

A button inside an open shadow root

editor

A contenteditable editor with a draft in it, replaced

late

A button that appears 1.2 s after load

blank

A target=_blank link, which a synthetic click loses to the popup blocker

frame

A button inside an iframe, by its frame ref

trusted

A button that only acts on event.isTrusted

csp

eval on a page whose CSP forbids eval

tt

eval on a page that requires Trusted Types

lazy

An infinite feed that loads as its end scrolls into view

listbox

A custom ARIA combobox that opens on mousedown

hover

A menu that shows its link only on hover

keys

A keyboard shortcut the page listens for

Alongside pass or fail, every case records interruptions:

  • Foreground steals: the window in front (from the operating system, on Windows) differs before and after the case.

  • Browser focus changes: any browser window gained focus while efferent was working.

  • Your tab switches: the active tab of any window that is not Claude's changed.

  • Debugger attaches: how many times the debugger bar could have shown.

Run it with the extension loaded and the browser open:

node eval/run.mjs --trials=5
node eval/run.mjs --case=listbox

Results

Thorium 144 on Windows 11, 5 trials of all 15 cases (4 November 2026, eval/runs.jsonl):

Passed

Median, p90

Foreground steals

Browser focus changes

Your tab switches

Debugger attaches

Run 1

75 of 75

573 ms, 2309 ms

0

0

0

5 (the trusted case)

Run 2

75 of 75

502 ms, 2279 ms

0

0

0

5 (the trusted case)

Development build

11 of 14

505 ms, 3220 ms

0

2

0

1

The development build created Claude's window minimized. A minimized window gives every new site process a 0 by 0 viewport, so pages laid out empty (listbox, lazy) and the trusted click had nowhere to land; and a tab created active in it brought the window forward. The first two lines of runs.jsonl are that build, kept as the record of why the window works the way it does.

Medians include the page settling after each step (load, then 250 ms with no DOM change). form and late are the slow ones: seven steps, and a 1.2 s wait by design.

Limits

  • 15 cases is small, and I wrote them. They cover the shapes I have hit, not every page. New cases, especially ones it fails, are the most useful contribution.

  • One browser and one operating system were measured. The foreground check is Windows only; on macOS and Linux the other three counts still run.

  • Synthetic events are not isTrusted. Pages that check it need trusted: true, and with it the debugger bar unless the browser runs with --silent-debugger-extension-api.

  • Closed shadow roots, cross-origin frames' trusted clicks and file pickers are out of reach.

  • It does what it is told in your signed-in browser. Pause it from the toolbar button when you do not want that.

Developing

Edit the files in extension/, then call browsers with reload: true (or click Reload on chrome://extensions). node eval/client.mjs 'open {"url":"example.com"}' 'read {"find":"more"}' calls tools from a shell.

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    A Chrome browser automation MCP server. Connect Claude (or any MCP client) to a real Chrome session — using your existing profiles with their cookies, saved passwords, and history.
    3
    -
  • A
    license
    B
    quality
    B
    maintenance
    An MCP server that enables Claude Desktop and Claude Code to drive a running Zen Browser over WebDriver BiDi, letting Claude list, open, switch, and close tabs, navigate pages, read page content, click, type, scroll, take screenshots, and extract text from a live browser session.
    14
    824 PyPI
    6
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    A local MCP server that lets AI coding tools drive the user's own already-logged-in Chrome — clicking, typing, reading pages, taking screenshots, and inspecting cookies, network, and console through the extension rather than a debug port. All communication stays on the machine, with agent-opened tabs grouped and kept out of focus.
    1 npm
    ISC
  • A
    license
    Not graded
    quality
    A
    maintenance
    A local MCP server that lets AI coding assistants drive the user's own already-signed-in Chrome, so agents can read logged-in pages, click, fill forms, navigate, screenshot, inspect network traffic and storage, and run multi-step browser workflows without a separate headless browser or remote debugging port. All communication stays on the user's machine and agent-opened tabs are grouped so they never steal focus.
    1 npm
    ISC