Install
$ agentstack add mcp-loworbitlab-chromiumfish-mcp ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
chromiumfish_mcp
chromiumfish_mcp is an independent Model Context Protocol (MCP) server for ChromiumFish. It lets Claude Code, Claude Desktop, Cursor, and other MCP clients drive a ChromiumFish browser through structured tools.
It uses the official ChromiumFish npm package and ships no Chromium source or binaries — on the first tool call that needs a page, the upstream SDK downloads and caches the matching browser build. See [docs/USAGE.md](docs/USAGE.md) for detailed tool usage.
Requirements
- Node.js 20 or later.
- An OS and architecture supported by ChromiumFish.
- Network access for the initial browser download. If no prebuilt asset matches your platform, build ChromiumFish locally and point to it with
--chrome-pathorCHROME_BIN.
Install
npm install --global github:LowOrbitLab/chromiumfish_mcp
chromiumfish_mcp --persona-seed alice
Or run without installing: npx --yes github:LowOrbitLab/chromiumfish_mcp --persona-seed alice.
Configure
Add the server to your MCP client config:
{
"mcpServers": {
"chromiumfish": {
"command": "chromiumfish_mcp",
"args": ["--persona-seed", "alice"]
}
}
}
To run from GitHub instead of a global install, set "command": "npx" and prepend "--yes", "github:LowOrbitLab/chromiumfish_mcp" to args. On Windows, use npx.cmd if your client cannot resolve npx.
Tools
| Tool | Purpose | |------|---------| | list_pages, open_page, select_page, close_page | Manage pages by stable pageId | | navigate, navigate_back, navigate_forward, reload | Navigate and use page history | | snapshot | List visible interactive elements with e1/e2 references | | get_text, take_screenshot | Retrieve page or frame content; take_screenshot crops to one element with target | | click, hover, type_text, select_option, set_checked, press_key, scroll, wait_for | Interact with the page | | drag | Drag onto another element or by a pixel offset, with a human-like path | | handle_dialog | Arm the answer for the next alert/confirm/prompt/beforeunload | | upload_file | Attach local files to a file input — requires --upload-dir | | list_downloads | Report what was downloaded and where it landed — requires --download-dir | | click_at | Click absolute coordinates (for widgets snapshot cannot see) | | list_frames | List frames/iframes with stable IDs | | find_challenge, solve_challenge | Detect and clear interstitial / framed challenges; the result says whether one was observed, interacted with, and verified | | evaluate | Run arbitrary JavaScript — requires --allow-eval | | run_task | Native ChromiumFish agent — requires --allow-native-agent |
A JavaScript dialog is answered the instant it opens, because a page left waiting on one freezes and no later call could finish. Unarmed the answer is dismiss — which is what Playwright already did silently — so a click that only raised confirm("Delete?") did not delete, and the action result now says so under dialogs. Call handle_dialog to arm the next answer, then repeat the action. The four navigation tools also report the HTTP status, since a 404 or a 500 loads like any other page.
Every navigation and interaction tool reports the resulting url, title, navigated, and any newPages, so a client only needs a follow-up snapshot when the page actually changed; returnSnapshot: true returns the action result and a fresh snapshot in one call. An action that navigates waits for the new document before reporting, so those fields describe the page it arrived on; one whose navigation is still in flight after ten seconds reports navigationPending: true rather than describing the page being left as though nothing happened, and one whose navigation was cancelled outright — blocked by --allowed-host, an unresolvable host — reports navigationFailed with the browser's own reason instead of waiting out that bound for a page that is never coming. Reference numbers are never reused, so one held across a snapshot fails with an error instead of acting on a different element; snapshot also reports ARIA roles, so role=button[name="Submit"] works in any target field as a re-render-proof alternative. The server ships MCP instructions describing this workflow, reference lifetime, and the challenge sequence.
Snapshot references, frame-aware interaction, waiting, and the cross-origin challenge workflow are covered in [docs/USAGE.md](docs/USAGE.md).
Command-line options
--persona-seed VALUE Use a stable browser fingerprint persona
--chrome-path PATH Use a local ChromiumFish executable
--browser-version VERSION Select an upstream ChromiumFish build version (rejected with --chrome-path)
--headed Show the browser window
--window-size WIDTHxHEIGHT Set the browser window size
--timezone ZONE Use an IANA time zone, auto, or system (default: auto)
--proxy URL Route browser traffic through a proxy
--allowed-host HOST Allow top-level navigation to a bare host and its subdomains; repeatable
--max-text-chars N Set the hard limit for text and snapshot output
--upload-dir PATH Allow upload_file to read this directory; repeatable
--download-dir PATH Save downloads here; without it they are discarded
--allow-eval Enable arbitrary JavaScript execution
--allow-native-agent Enable the native ChromiumFish browser agent
Proxy credentials can be embedded in the proxy URL, but are then exposed in the client config. Never commit config files containing proxy passwords, cookies, or API keys.
Security
- stdio only — do not expose the Chromium DevTools endpoint to the public internet.
evaluateand the native agent are disabled by default; enable them only in trusted environments.--allowed-host example.comrestricts top-level HTTP/HTTPS navigation (redirects, links, form posts, popups) to a host and its subdomains. Give it a bare host name: matching is on the host alone, so a scheme, path, port, leading dot, or wildcard is rejected at startup rather than quietly matching nothing. Third-party subframes and page assets remain reachable — it is a navigation guard, not a network egress filter. A blocked navigation is reported asnavigationFailedwith reasonnet::ERR_BLOCKED_BY_CLIENT, rather than as a click that appeared to do nothing. Enabling it also turns on request interception, which disables the browser's HTTP cache for the session: expect slower asset-heavy pages, and note that a browser re-fetching everything on a repeat visit is itself a signal to sites that profile behavior.upload_filesends host files to whatever origin the page posts to, so it is unregistered until--upload-dirnames at least one directory, and every path must resolve inside one. Both the path and the roots are resolved through symlinks first, so a link planted inside a root cannot reach outside it. Scope the roots to the files a task actually needs — a page can influence which file the model picks.- Downloads are written only when
--download-dirnames a directory; without it the transfer still runs (so the page's own flow is unchanged) but nothing is kept, and the action result saysdiscarded. The file name comes from the remote server'sContent-Disposition, so it is reduced to a bare base name and the resolved path is checked against the root before anything is written. - A page can raise
confirm()to guard a destructive action. Unarmed dialogs are dismissed, so that guard holds by default;handle_dialogwithaccept: truedeliberately answers the next one. Keep human confirmation in front of it for anything irreversible. - Clients can click and type with real side effects. Keep human confirmation for purchases, publishing, deletion, and permission changes.
solve_challengereturnsok: truewhenever the page is not blocked, including on pages that were never challenged. ReadchallengeObserved,interactionPerformed, andclearanceVerifiedbefore recording or reporting that a challenge was cleared —okalone will overstate what happened.- Each process runs an independent browser context; this is not a shared multi-tenant service.
Development
npm ci
npm test
node dist/index.js --help
The suite uses an in-memory MCP transport to verify tool discovery, dangerous-tool opt-in, and results. It does not download or launch a browser.
License
MIT. ChromiumFish code and trademarks belong to their respective contributors; see [NOTICE](NOTICE) for attribution. This is an independent wrapper, not an official ChromiumFish release.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: LowOrbitLab
- Source: LowOrbitLab/chromiumfish_mcp
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.