AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Jev Browser

mcp-ying-kai-liao-jev-browser · by Ying-Kai-Liao

Browser automation where an LLM plans and Jev (Typesafe System One) decides. Library, CLI and MCP server.

— No reviews yet
0 installs
21 views
0.0% view→install

Install

$ agentstack add mcp-ying-kai-liao-jev-browser

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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 Used
  • ✓ 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-ying-kai-liao-jev-browser)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 8d ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

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 →
Are you the author of Jev Browser? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

jev-browser

Browser automation where an LLM plans and Jev decides.

> Unofficial project, not affiliated with TypeSafe. It calls the TypeSafe System One API > with your own API key.

The calling LLM (Claude, via MCP) says what outcome it wants, one step at a time, and hands over any text to type. For each round of a step, code describes the page. Then one ~300 ms Typesafe System One request asks Jev several questions at once: which element, which action, which value, and is the step done / blocked / showing an error / about to do something irreversible. Playwright performs the action. The LLM never reads page snapshots unless it chooses to take over.

Claude ── browser_do("Log in", {email, password}) ──▶ jev-browser
                                                       │  loop until done / stuck / needs confirmation
                                                       │   1. settle   (network + DOM quiet)
                                                       │   2. describe (elements, labels, state, visible text, diff, counts)
                                                       │   3. Jev      (done? error? irreversible? tool? target? value?)
                                                       │   4. act      (Playwright)
Claude ◀── { status: "done", url, actions[], done_score } ─┘

https://github.com/user-attachments/assets/2e688df9-4985-4854-8ebe-ba97c9d13d68

Jev only answers with probability distributions: yes/no (noul), pick one option (choice) or a rating (score). It never writes text. So everything free-form comes from the caller as candidates, and code turns disagreement or low confidence into a status the LLM can act on.

Results

42 tasks in 16 categories on live sites (see [RESULTS.md](RESULTS.md)):

  • 40/42 correct in the latest run, 0 false "done" claims (38/41 twice before the latest

fixes). Remaining misses: counting ("add until 3", flagged likely_done) and verifying a sort.

  • ~300 ms per Jev call, 2–4 calls for most steps; a 5-step checkout takes ~14 s end to end.
  • Pause before irreversible actions: across ~200 rounds it flagged only saucedemo's

"Finish" (place order) button.

  • Less page content for the LLM than a Playwright-MCP-style loop on the same tasks

(estimate): median 5× per task, ≈8k vs ≈557k tokens in total. Big pages dominate the total: a Wikipedia article is ~149k snapshot tokens. On tiny pages there is no saving. The page reading moves to Jev.

Works on: forms, native and custom dropdowns, checkboxes and radios (including styled replacements), dynamic loading, modals, JS dialogs, hover, right-click, drag and drop, key presses, file upload, iframes, shadow DOM, new tabs, pages with 2,000+ elements (two-stage selection), and non-English UIs.

Known limits, so write steps around them:

  • Ordered sub-goals in one step ("add two todos, complete one, clear completed") → split

into one outcome per step.

  • Open-ended goals ("scroll to load more") → make them measurable or check yourself.
  • Judgements that compare many values (is this table sorted, did exactly one thing change)

→ verify with browser_check or browser_snapshot.

Quick start (MCP, from npm)

npx playwright install chromium          # once
claude mcp add jev-browser -e TYPESAFE_API_KEY=your-key -- npx -y -p jev-browser jev-browser-mcp

Any MCP client works the same way: command npx, args -y -p jev-browser jev-browser-mcp, env TYPESAFE_API_KEY. Add JEV_BROWSER_HEADED=1 to watch it work.

Setup (from source)

git clone https://github.com/Ying-Kai-Liao/jev-browser && cd jev-browser
npm install
npm run setup                    # downloads Chromium for Playwright
cp .env.example .env             # add TYPESAFE_API_KEY
npm test                         # offline tests (no network, no key)
npm run test:e2e                 # MCP server end to end (network + key)

Use from Claude Code (MCP, from source)

claude mcp add jev-browser -- node /absolute/path/to/jev-browser/bin/jev-browser-mcp.mjs

From a source checkout the server reads TYPESAFE_API_KEY from the repo's .env.

| tool | purpose | |---|---| | browser_open(url) | navigate and wait for the page to settle | | browser_do(goal, values?, max_actions?, allow_irreversible?, explain?) | work toward one outcome; returns a status | | browser_check(question) | yes/no about the page → p_yes | | browser_choose(question, options) | pick among given options → distribution | | browser_snapshot() | compact numbered element list, for taking over | | browser_act(action, element, value?, key?, destination?, accept_dialog?) | act on an element directly, no model; confirm/prompt dialogs are dismissed unless accept_dialog | | browser_screenshot(full_page?) | PNG image | | browser_close() | end the session |

browser_do statuses:

| status | meaning / what the caller should do | |---|---| | done | goal reached | | likely_done | the page looks done but Jev is unsure: verify before moving on | | needs_login | a sign-in wall and no credentials in values; log in yourself (headed + JEV_BROWSER_PROFILE) or pass credentials | | needs_confirmation | next action, or a confirm dialog it opened (then dismissed), looks irreversible (order, pay, send, delete); see pending, re-call with allow_irreversible: true only if the user wants it | | error | the page shows an error after the last action (e.g. wrong password); see page_text | | stuck / max_actions | no progress; see info, page_text, candidates | | ambiguous | low confidence in the target; pick from candidates with browser_act | | blocked | captcha, access denied, error page |

Env: JEV_BROWSER_HEADED=1 shows the browser, JEV_BROWSER_PROFILE=/dir keeps a persistent profile (logins survive restarts), JEV_BROWSER_LOG=1 prints per-round decisions to stderr.

Library

// npm install jev-browser && npx playwright install chromium
import { JevBrowser } from "jev-browser";

const b = await JevBrowser.launch({ headed: true });
await b.open("https://www.saucedemo.com/");
await b.do("Log in", { values: { username: "standard_user", password: "secret_sauce" } });
await b.do("Add the Sauce Labs Backpack to the cart");
const p = await b.check("Does the cart badge show 1 item?");   // 0..1
await b.close();

Watch it

node examples/x-profile-demo.mjs     # headed, read-only x.com walkthrough with decision highlights

Each action is outlined in red with Jev's choice and scores before it happens (highlight: true, on by default in the MCP server when JEV_BROWSER_HEADED=1). Some sites, x.com included, serve a blank page to headless Chromium: use headed mode there.

CLI

node bin/jev-browser.mjs do https://the-internet.herokuapp.com/login "Log in" username=tomsmith 'password=SuperSecretPassword!'
node bin/jev-browser.mjs run examples/flows/todomvc.json --headed

Writing good steps

  • One observable outcome per step: "Log in", "Open the Pull requests tab", "Mark 'buy milk' completed".
  • Every string goes in values with a meaningful key (email, postal_code, file).
  • Treat likely_done, needs_confirmation, ambiguous and stuck as your turn: check,

snapshot or ask the user, don't just retry.

  • After steps with side effects, browser_check what must not have changed.

Benchmark

node bench/run.mjs --set all            # base, hard, guard (+ bench/tasks.local.mjs if present)
node bench/run.mjs --only ti-login,drag
node bench/context-cost.mjs bench/results/.json

Private sites and credentials go in bench/tasks.local.mjs (git-ignored), exporting LOCAL.

Layout

src/session.mjs      JevBrowser: settle, snapshot, decide (1 or 2 stages), resolve, act, do, check, choose
src/page-script.mjs  runs in each frame: elements, labels, state, visible text, metrics, dialogs
src/page-model.mjs   pure helpers: diff between pages, counts, compact rendering
src/jev.mjs          System One API client
src/flow.mjs         JSON flow runner
bin/                 CLI and MCP server
bench/               tasks with ground-truth checks, runner, context-cost estimate
test/                offline fixture tests, MCP end-to-end test
NOTES.md             design notes: what works with Jev, what doesn't, and why

Releasing

CI runs the offline tests on every push and pull request. To publish, bump the version and push the tag; .github/workflows/release.yml tests, publishes to npm with provenance and creates a GitHub release:

npm version patch            # or minor / major: commits and tags vX.Y.Z
git push --follow-tags

Publishing uses npm trusted publishing, set up once with npx npm@latest trust github jev-browser --file release.yml --repo Ying-Kai-Liao/jev-browser --allow-publish.

License

MIT

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.