Skip to main content
Glama

Jev Ultrafast ⚡

A browser agent with a dynamic, indexed action space.

Give it one natural-language goal. TypeSafe's Jev picks the next operation and the target element in a single request. A small LLM writes text only when the operation is TYPE_TEXT. Model output never becomes selectors, coordinates, shell commands, or executable JavaScript.

IMPORTANT

Ships with a ready-made MCP server — jev-browser. Register it once with make install and your existing coding agents — Claude Code, Codex, Qwen Code, ZCode, Cursor, VS Code, Gemini CLI, OpenCode, Google Antigravity — drive a real, indexed browser through jev_navigate / jev_observe / jev_act / jev_close on their own license. No extra API keys: your agent is the brain, the MCP server only observes and executes. See MCP server.

Watch the MP4 · Measurements · Read the loop

How it works

Every observation produces a fresh element table with stable indexes:

[1] button    Change ticket type · Round trip
[2] combobox  Where from?        · San Francisco
[3] combobox  Where to?          · empty
[4] textbox   Departure          · empty

Operations: CLICK, TYPE_TEXT, SELECT, SCROLL_UP, SCROLL_DOWN, WAIT, DONE, BLOCKED. One TypeSafe request returns an operation plus operation-specific target heads; only the selected operation's target executes — two decisions, one network round trip.

page → element table → TypeSafe (operation + targets) → matching target → browser
                                                       └→ TYPE_TEXT → small LLM → text → browser

There are no site-specific action scripts or prepared field values. Every executed target is resolved from an observed DOM node, rechecked for freshness and click occlusion, and the outcome is verified independently — a DONE choice alone is not proof of success.

Related MCP server: OpenCode in Chrome

Installation

Prerequisites

Steps

git clone https://github.com/browser-use/jev-ultrafast.git
cd jev-ultrafast
make build

make build prepares everything: dependencies (including Browser Harness), a .env scaffold, JS syntax checks, lint, tests, and the package build.

Add your keys to .env, make sure Chrome is running, then start the inspector:

uv run jev
# open http://127.0.0.1:8766 → Start demo → Run automatically

The inspector shows numbered elements, operation/target probabilities, and executed actions. Choose next pauses before execution.

Browser Harness

Browser Harness is the local daemon that bridges Python and Chrome over the Chrome DevTools Protocol (CDP). It ships as a pinned dependency (browser-harness) and is installed automatically by uv sync / make build — no separate install step.

  • The daemon auto-starts the first time a browser session is created (demo, library, or MCP server). It attaches to your running Chrome and opens its own background tab — your active tab is never taken over, and owned tabs share your existing Chrome profile.

  • Check health at any time:

uv run browser-harness --version   # installed version
uv run browser-harness --doctor    # diagnose install, daemon, and browser state
  • Linux with Snap-packaged Chromium: Snap sandboxing blocks CDP. Run uv run browser-harness doctor --fix-snap for the fix, or use a non-Snap Chrome/Chromium.

  • make doctor runs this check as part of the full stack report.

Chrome remote debugging

The agent drives Chrome through its remote-debugging (CDP) channel, which Browser Harness enables on first connect. You start Chrome normally — no manual --remote-debugging-port flag, no restart.

  • macOS: the first time the daemon connects, Chrome shows a native "Allow remote debugging" permission sheet. Click Allow, or pre-approve it from the terminal:

uv run browser-harness mac-approve
  • Linux/Windows: no extra permission step; if the connection fails, run uv run browser-harness --doctor and follow its output.

  • Chrome should be open before you start the demo. make doctor warns if it is not running yet.

TypeSafe API

TypeSafe is the decision engine of the agent loop: each step sends it the element table, and it returns the operation plus target in a single request. Without a key, the demo and library loops cannot choose actions.

  • Get a key from TypeSafe, put it in .env as TYPESAFE_API_KEY. Requests go to https://api.typesafe.ai/v1; the model defaults to jev-latest (override with TYPESAFE_MODEL).

  • Who needs it: the demo inspector and the Python library loop. The MCP server does not — there your coding agent (Claude Code, Codex, Qwen Code, ZCode, …) is the brain and the server only observes and executes.

  • TYPE_TEXT additionally needs TEXT_MODEL_API_KEY (any OpenAI-compatible provider — see Configuration). Without it, everything works except typing text.

  • Only the demo, live examples, and recording scripts make paid TypeSafe calls; tests are offline and never do.

Steps

git clone https://github.com/browser-use/jev-ultrafast.git
cd jev-ultrafast
make build

make build prepares everything: dependencies, a .env scaffold, JS syntax checks, lint, tests, and the package build.

Add your keys to .env, then start the inspector:

uv run jev
# open http://127.0.0.1:8766 → Start demo → Run automatically

The inspector shows numbered elements, operation/target probabilities, and executed actions. Choose next pauses before execution. When Chrome prompts for remote debugging, allow it; if the connection needs fixing, run uv run browser-harness --doctor.

Configuration

Environment variables (.env, git-ignored)

Variable

Required

Default

Purpose

TYPESAFE_API_KEY

yes

—

TypeSafe Jev: operation + target selection

TYPESAFE_MODEL

no

jev-latest

TypeSafe model id

TEXT_MODEL_API_KEY

for TYPE_TEXT

—

Text helper used only by TYPE_TEXT

TEXT_MODEL_BASE_URL

no

https://openrouter.ai/api/v1

OpenAI-compatible endpoint

TEXT_MODEL

no

inception/mercury-2.5

Text model id

TEXT_MODEL_REASONING

no

none

Set to none to disable reasoning in the text helper

TYPESAFE_DEMO_PORT

no

8766

Inspector port

URLs

URL

What it is

http://127.0.0.1:8766

Local demo inspector (uv run jev)

https://api.typesafe.ai/v1

TypeSafe API used by the agent loop

https://openrouter.ai/api/v1

Default text-model endpoint (.env.example)

The text helper works with any OpenAI-compatible provider — DeepSeek (https://api.deepseek.com/v1, deepseek-chat is the code-level fallback), OpenAI, Gemini, GLM, or local Ollama. Set TEXT_MODEL_BASE_URL, TEXT_MODEL, and TEXT_MODEL_API_KEY accordingly. For a programmatic custom provider, see docs/text-provider-guide.md and examples/custom_text_provider.py.

MCP server (jev-browser)

The browser layer ships as a standalone MCP stdio server (jev-mcp) so coding agents — Claude Code, Codex, Qwen Code, ZCode, Cursor, VS Code, and any other MCP client — can drive a real browser with their existing licenses. The server only observes and executes; your coding agent is the brain and makes every decision from the indexed element table. The server itself calls no model, so no API keys are required to use it.

flowchart LR
    subgraph agents["Your coding agents — bring your own license"]
        direction TB
        CC[Claude Code]
        CX[OpenAI Codex]
        QW[Qwen Code]
        ZC[ZCode]
        MX["Cursor · VS Code · Gemini CLI · OpenCode · Antigravity"]
    end

    subgraph standalone["Standalone loop — demo inspector + Python library"]
        direction TB
        TS["TypeSafe API<br/>operation + target in one request"]
        TXT["text LLM<br/>TYPE_TEXT only"]
    end

    MCP["jev-browser MCP server (jev-mcp)<br/>jev_navigate · jev_observe · jev_act · jev_close"]
    BH["Browser Harness daemon"]
    CHROME["Chrome<br/>jev's own background tab · shared profile"]

    agents -- "MCP stdio — agent decides, server executes" --> MCP
    TS --- TXT
    MCP --> BH
    standalone --> BH
    BH -- "CDP" --> CHROME

The same Browser Harness + Chrome layer serves both paths: through the MCP server your coding agent decides each step from the element table; through the standalone loop TypeSafe decides.

Tools

Tool

Arguments

Does

jev_navigate

url

Open a URL; creates the browser session if needed

jev_observe

screenshot?

Return URL, title, text preview, and numbered interactive elements

jev_act

action_id, text?

Click, type (text required for fill actions), or select an element by id

jev_close

—

Close the browser session

jev_config

API key/url/model fields

Update TypeSafe/text-model config at runtime

One-command install

make install              # register with every detected agent
make install cursor       # one agent only (claude, codex, qwen, zcode, ...)
make install-dry          # show what would be written, change nothing
make doctor               # deps, API keys, Chrome, browser-harness, MCP registrations
uv run python scripts/install_mcp.py --status   # current registration status

Registration is idempotent: re-running replaces only the jev-browser entry and leaves every other configured server untouched.

Supported agents

Key

Agent

Config file written

claude

Claude Code

~/.claude.json (claude mcp add, user scope)

codex

OpenAI Codex CLI

~/.codex/config.toml ([mcp_servers."jev-browser"])

commandcode

Command Code

~/.commandcode/mcp.json

vscode

VS Code

…/Code/User/mcp.json (servers)

cursor

Cursor

~/.cursor/mcp.json

qwen

Qwen Code

~/.qwen/settings.json

ayg

Google Antigravity

~/.gemini/config/mcp_config.json

gemini

Gemini CLI

~/.gemini/settings.json

opencode

OpenCode

~/.config/opencode/opencode.json

zcode

ZCode

~/.zcode/cli/config.json

Credentials are never written into agent configs. Every entry spawns uv --directory <project> run --env-file <project>/.env jev-mcp, so the server loads keys from the git-ignored .env at startup.

Manual registration (any MCP client)

{
  "mcpServers": {
    "jev-browser": {
      "type": "stdio",
      "command": "/absolute/path/to/uv",
      "args": [
        "--directory",
        "/absolute/path/to/jev-ultrafast",
        "run",
        "--env-file",
        "/absolute/path/to/jev-ultrafast/.env",
        "jev-mcp"
      ]
    }
  }
}

Replace /absolute/path/to/uv with your real uv binary (which uv, typically ~/.local/bin/uv) and /absolute/path/to/jev-ultrafast with the project directory. The absolute command matters: some agents spawn MCP servers without your shell's PATH, where a bare uv fails to resolve. --env-file loads the git-ignored .env so keys never appear in the agent config; drop that flag if you keep no .env.

Or run it by hand to verify: uv run jev-mcp from the project directory.

How agents use it

Once registered, just give your agent a goal in its normal chat — Claude Code, Codex, Qwen Code, and ZCode all drive the same three-tool loop:

You: Open google.com and search for "browser-use jev-ultrafast"

Agent: 1. jev_navigate("https://www.google.com")
       2. jev_observe()                 → [1] textbox Search  [2] button Google Search …
       3. jev_act("e1", "browser-use jev-ultrafast")
       4. jev_act("e2")                 → results page
       5. jev_close()

Rules the host agent should follow:

  • Call jev_observe after every navigation or action — element ids change with each snapshot, so never reuse an id from an older observation.

  • Pass text for fill/type actions; click and select take only action_id.

  • If jev_act reports an error, observe again and re-decide instead of retrying the same id.

Use as a library

The full TypeSafe loop:

from jev_ultrafast import Agent

with Agent(
    "https://www.google.com/travel/flights?hl=en",
    "Find one-way flights from Zurich to London on September 20, 2026, "
    "for one adult in economy. Stop when matching flight options are visible.",
) as agent:
    for state in agent.run():
        print(state["elapsed_ms"], state["status"])

Run with uv run --env-file .env python your_script.py. A generic task:

uv run --env-file .env python examples/run.py \
  --url https://en.wikipedia.org/wiki/Main_Page \
  --goal 'Find and open the Wikipedia article about Gödel’s incompleteness theorems.'

Or swap the TypeSafe agent for your own — the browser layer is standalone:

from jev_ultrafast.browser import Browser

browser = Browser("https://example.com")
page = browser.observe()          # numbered element table

action = next(a for a in page["actions"] if a["id"] == "e2")
browser.act(action, page, text="hello")

See examples/external_agent.py and docs/architecture.md. examples/flights.py runs the verified flight search (--keep-open keeps the browser open).

Project layout

File

Job

jev_ultrafast/browser/browser.py

CDP connection, DOM observation, action execution

jev_ultrafast/browser/snapshot.js

Atomic DOM snapshot, indexed controls, freshness guards

jev_ultrafast/agent/agent.py

The complete loop and text-helper handoff

jev_ultrafast/agent/model.py

TypeSafe operation/target heads and text generation

jev_ultrafast/mcp_server.py

jev-browser MCP server

jev_ultrafast/demo.py

Local inspector (jev)

scripts/install_mcp.py

MCP registration for coding agents

scripts/doctor.py

Stack health check

Development

uv run ruff check .
uv run pytest
node --check jev_ultrafast/static/app.js
node --check jev_ultrafast/browser/snapshot.js
uv build

Tests are offline. uv run python scripts/check_guards.py checks real controls in a local browser without model calls. Live examples and the recording scripts (scripts/record_flights.py, scripts/render_demo.py) make paid API calls; credentials and raw traces stay ignored. Run boundaries and raw evidence live in docs/performance.md.

Scope and limits

The DOM reader handles common HTML and ARIA controls, not the full accessible-name specification. Shadow roots, frames, canvas, uploads, pop-up tabs, nested scrolling, and arbitrary keyboard widgets remain outside this MVP. Owned tabs share the existing Chrome profile.


Browser Use · Browser Harness · TypeSafe speculative fan-out

Available Tools

5 tools
jev_actA

Execute an action on an element. Use action_id from jev_observe.

Args: action_id: Element ID from jev_observe (e.g., 'e1', 'e2') text: Text to type (required for fill actions)

ParametersJSON Schema
NameRequiredDescriptionDefault
textNo
action_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It discloses that text is required for fill actions and that action_id comes from observation, but says nothing about side effects, waiting behavior, error handling, or reversibility—significant gaps for a mutating execute tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, then the prerequisite, then a compact Args block that is necessary given zero schema descriptions. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. The description covers purpose, prerequisite, and parameters, but leaves action types and behavioral traits underspecified, which matters for an execute tool with no annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It explains action_id as an element ID from jev_observe with examples ('e1','e2') and text as required for fill actions, adding real meaning beyond the bare schema. It leaves action-type mapping somewhat implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Execute'), resource ('an action on an element'), and ties the action_id to sibling tool jev_observe, distinguishing it as the acting counterpart to observing. It does not enumerate action types, but the core purpose is clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use action_id from jev_observe' gives the prerequisite and workflow relation, making it clear this tool is used after observing. It stops short of explicit when-not guidance or naming alternative siblings like jev_navigate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jev_closeB

Close the browser session.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It does not say whether closing is destructive to session state, whether subsequent calls in the same session fail, or whether the operation is idempotent — all relevant for a terminate-style tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler. It is efficient, though arguably terse enough that it omits useful context rather than being optimally sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. However, for a session-terminating tool with no annotations, the description omits the post-close behavior (state loss, effect on other jev_* tools), leaving an agent to guess at consequences.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. Schema coverage is 100% and no additional parameter meaning is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Close") and resource ("browser session"), so an agent immediately knows the operation. It does not differentiate itself from siblings like jev_navigate or jev_act, but those are clearly distinct actions, so ambiguity is low.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: call this when finished with the browser session. There is no explicit statement of when to use it versus alternatives, nor any prerequisite or sequencing guidance relative to jev_observe/jev_navigate/jev_act.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jev_configB

Set or update API configuration at runtime.

Args: typesafe_api_key: TypeSafe API key for operation/target selection typesafe_base_url: TypeSafe API base URL (default: https://api.typesafe.ai/v1) text_model_api_key: Text model API key for TYPE_TEXT operations text_model_base_url: Text model API base URL (default: https://api.deepseek.com/v1) text_model: Text model name (default: deepseek-chat)

ParametersJSON Schema
NameRequiredDescriptionDefault
text_modelNo
typesafe_api_keyNo
typesafe_base_urlNo
text_model_api_keyNo
text_model_base_urlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It does disclose that configuration is applied at runtime and lists per-field defaults, but it omits critical behaviors for a mutation tool: whether settings persist across sessions or are process-global, whether partial updates are allowed, and what passing null (the schema default for every field) actually does.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The primary purpose is stated in a single front-loaded sentence, followed by a compact Args list that adds real information per field. No wasted prose, though the Args block is a plain list rather than tightly integrated guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and all five parameters are documented. However, for a mutation tool with zero annotation coverage, the description should say more about persistence, permission requirements, and null/partial-update behavior before an agent could call it confidently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it largely does: all five parameters are explained with their purpose (key vs base URL vs model name) plus defaults for the base URLs and model. The one gap is that null semantics for each optional field are never clarified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Set or update API configuration at runtime'. This is unambiguous about what the tool does. It does not explicitly differentiate itself from siblings (jev_observe, jev_navigate, jev_act, jev_close), though those are plainly a different functional domain, so differentiation is largely self-evident.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'at runtime' hints at the context of use, but there is no explicit when-to-use guidance, no prerequisites, and no statement of when not to call it. With no alternative config tool named, the agent must infer the trigger conditions on its own.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jev_navigateB

Open a URL in the browser. Creates a new browser session if none exists.

Args: url: URL to navigate to

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It usefully discloses side-effect behavior ('Creates a new browser session if none exists'), but says nothing about whether navigation blocks until page load, how errors surface, or fetch/auth requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences front-load the action and the session side effect. The 'Args:' block is mildly redundant with the schema but costs little and does name the required input.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained. For a simple one-parameter tool the description is serviceable, but it omits load/error behavior that an agent orchestrating a browser session would benefit from.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% for the single 'url' parameter. The description's 'url: URL to navigate to' merely restates the parameter name, adding no format detail (scheme requirements, absolute vs relative, encoding) that the bare schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource: 'Open a URL in the browser.' An agent can tell this is the navigation action, distinct from observe/act/close/config siblings, though no sibling is named explicitly for contrast.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use guidance or prerequisite ordering relative to jev_observe/jev_act. The session-creation note implies this is a valid entry point, but the agent must infer that this is typically the first call in a workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

jev_observeA

Read current page state: URL, title, text, and interactive elements with IDs.

Args: screenshot: Include screenshot (base64 JPEG). Default: false

ParametersJSON Schema
NameRequiredDescriptionDefault
screenshotNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It discloses the read-only nature implicitly ('Read') and documents the screenshot format (base64 JPEG), but says nothing about cost, latency, or performance implications of capturing a screenshot, nor anything about page-state freshness or permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight lines, front-loaded with the core purpose followed by the parameter note. No filler sentences, and the returned fields are summarized efficiently in a single clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so explaining return values in detail is unnecessary, and for a one-parameter read tool the description is nearly sufficient. The remaining gap is the absence of any guidance on when to observe versus act, which would help an agent sequence calls.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must document the single parameter, and it does: 'screenshot: Include screenshot (base64 JPEG). Default: false'. The added format detail (base64 JPEG) goes beyond the bare boolean in the schema, though payload size or cost implications are not addressed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Read current page state') and enumerates exactly what is returned: URL, title, text, and interactive elements with IDs. This distinguishes it from jev_navigate/jev_act/jev_close/jev_config by implication, but the description never explicitly names those siblings or contrasts the roles.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use or when-not-to-use guidance and no mention of the alternative tools (jev_act, jev_navigate) or the typical observe-then-act loop. The agent can infer it is the inspection step from the name and description, but nothing is stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedjev_act
    • First observedjev_close
    • First observedjev_config
    • First observedjev_navigate
    • First observedjev_observe

TDQS

A3.5/5.0

Scored across 5 tools

Disambiguation4/5

Each tool maps to a distinct phase of browser control: observe reads state, navigate opens URLs, act performs element actions, close ends the session, and config handles configuration. The only mild overlap is that act can perform many action types, but it remains clearly separated from the read-only observe.

Naming Consistency5/5

All five tools follow an identical 'jev_' prefix plus a concise snake_case verb pattern (observe, navigate, act, close, config), making the set highly predictable and readable.

Tool Count4/5

Five tools is lean but well-scoped for a browser automation agent, with each tool earning its place in the observe-navigate-act-close loop. The addition of config is justified for runtime setup.

Completeness4/5

The core browser lifecycle (navigate, observe, act, close) is covered, and act likely encompasses clicks, typing, and scrolling via element IDs. Minor gaps like explicit back/forward navigation, tab management, or scroll-only primitives exist but agents can work around them.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers