Skip to main content
Glama

A stealth headless browser engine in Rust. Passes Cloudflare without Chromium.

Real V8 and a DOM, a Chrome TLS/HTTP fingerprint (JA3/JA4) and JS-level stealth, driven over the Chrome DevTools Protocol: Puppeteer and Playwright connect as usual. Also an MCP server for AI agents.

CI Release PyPI npm Docker Rust License: MIT OR Apache-2.0 Status: alpha

scrapingcourse.com's Cloudflare test page, one run from a home connection; medians across sites are in the tables below.

The nøkk is a shapeshifting water-spirit of Norse myth that takes on a familiar shape to pass unnoticed. This one takes the shape of Chrome.


Install

pip install nokk                    # Python: the prebuilt binary is in the wheel
npm install @koloss777/nokk         # Node: run it with `npx nokk`
docker run --rm -p 9222:9222 ghcr.io/koloss777/nokk:latest

No browser to download. Prebuilt for Linux (x86_64, ARM64), macOS on Apple Silicon and Windows x64; anything else builds from source.

Related MCP server: Airbrowser

Quick start

# Load a page behind Cloudflare, clear the challenge, print what is behind it
nokk --load https://www.scrapingcourse.com/cloudflare-challenge --solve-challenge 30 \
     --eval "document.querySelector('h2').textContent.trim()"

# Or run the CDP server and drive it from any client
nokk --port 9222 --auto-solve   # ws://127.0.0.1:9222/devtools/browser/nokk
import nokk
from playwright.sync_api import sync_playwright

with nokk.launch(auto_solve=True) as server, sync_playwright() as pw:
    page = pw.chromium.connect_over_cdp(server.ws_endpoint).new_page()
    page.goto("https://www.scrapingcourse.com/cloudflare-challenge")
    print(page.title())

For AI agents, uvx nokk-mcp runs it as an MCP server. Puppeteer, Node, sessions and the Cloudflare options are below.

Why nokk

Puppeteer and Playwright drive a real Chromium, and anti-bot systems spot it through navigator.webdriver, CDP artifacts and a headless TLS handshake. nokk is built to look like Chrome from the TLS handshake to the JavaScript environment, and has no rendering engine at all.

nokk 0.1.35

Chrome 151 (Puppeteer / Playwright)

Start until CDP answers

~0.05 s

~0.2 s

Idle memory (PSS)

~60 MB, 1 process

~330 MB, 12–14 processes

Cloudflare solve, median wall time

12.4 s

12.4 s

Slowest solve

15.6 s

27.8 s

CPU per solve

6.4 s

9.5 s

Peak memory per solve

~570 MB

~720 MB

Solved

24/24

24/24

TLS fingerprint (JA3/JA4)

matches Chrome 151

Chrome

Screenshots, PDF, layout

no

yes

CDP coverage

the common path

full

Measured on nokk 0.1.35, an 8-core Linux box, October 2026. Cloudflare row: 8 production sites × 3 runs through one proxy, nokk with --until-clearance, Chrome driven by a checkbox-clicking harness; a solve counts only if the site then opens with the cookie.

Not for you if you need screenshots, PDFs, layout or paint, or the whole Playwright/CDP surface: nokk has no rendering engine by design, and its CDP coverage is the path Puppeteer and Playwright use for navigation and scripting.

Measured on public pages

Three runs per page from the CLI with --solve-challenge 30 and no proxy, on an 8-core Linux box (October 2026). The time is the whole command, from process start to the printed result. Run them yourself with tools/cf-check.sh.

Page

Challenge

Solved

Median

Slowest

chess.com/login

invisible Turnstile widget on a live site

3/3

7 s

9 s

scrapingcourse.com/cloudflare-challenge

managed interstitial

3/3

5 s

7 s

peet.ws/turnstile-test/managed.html

managed widget

3/3

7 s

8 s

peet.ws/turnstile-test/non-interactive.html

non-interactive widget

3/3

3 s

4 s

nopecha.com/demo/cloudflare

interactive interstitial with a checkbox

3/3

10 s

11 s

On production sites behind Cloudflare the result is in the comparison above: 8 sites, 24 of 24 solved. Those sites are not named here.

Usage

Command line

nokk --fetch https://tls.browserleaks.com/json                   # Chrome TLS + HTTP/2 fingerprint
nokk --load https://example.com --eval 'document.title'          # run the page, query the DOM
nokk --load https://quotes.toscrape.com --dump-requests          # every request the page makes
nokk --load https://target --proxy socks5://host:1080            # through a proxy
nokk --port 9222 --rotate-fingerprint --geoip-timezone           # CDP server, a machine per context

Ad, analytics and tracker requests are dropped by default; --allow-trackers loads them. Anti-bot vendors are never blocked, because they must run to hand out a token.

Puppeteer

import puppeteer from 'puppeteer';

const browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://127.0.0.1:9222/devtools/browser/nokk',   // nokk --port 9222
});
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());

Node and Python

Both packages carry the prebuilt binary and start the CDP server for you.

const server = await require("@koloss777/nokk").launch({ autoSolve: true });
// server.wsEndpoint -> puppeteer.connect / chromium.connectOverCDP
with nokk.launch(auto_solve=True) as server:   # or: await nokk.launch_async()
    ...  # server.ws_endpoint -> connect_over_cdp

crawl4ai, Scrapy, Playwright MCP and other CDP tools

Anything that drives Chrome over CDP can drive nokk instead. crawl4ai, stopped by Cloudflare with its own Chromium, gets the page behind it through nokk: BrowserConfig(browser_mode="custom", cdp_url=server.ws_endpoint). Scrapy (scrapy-playwright's PLAYWRIGHT_CDP_URL) and Playwright MCP (--cdp-endpoint) work the same way. See docs/integrations.md.

For AI agents (MCP)

nokk runs as a Model Context Protocol server, so an agent such as Claude Desktop or Claude Code browses through the fingerprinted engine. With uv nothing needs installing first:

{ "mcpServers": { "nokk": { "command": "uvx", "args": ["nokk-mcp", "--rotate-fingerprint"] } } }

Without uv: pip install "nokk[mcp]", then "command": "python", "args": ["-m", "nokk.mcp"]. Tools: open, read_text, read_html, click, fill, evaluate, links, solve_challenge, challenge_state, reset.

Cloudflare challenges

nokk clears Turnstile by itself: the invisible widget, the managed interstitial and the interactive Verify you are human checkbox. Nothing is configured per site. Where a widget needs a press, the engine presses it like a person would.

  • --solve-challenge N sets the time budget, and --fail-on-challenge exits 3 if a gate is still up.

  • --until-clearance stops at a fresh cf_clearance and skips the heavy page behind the gate.

  • --auto-solve does the same for every page.goto() over CDP; Nokk.solveChallenge does it on demand.

  • A cf_clearance from a real browser can be imported, because nokk's JA4 matches Chrome 151.

Details, the CDP methods and events: docs/cloudflare.md.

Persistent sessions

--session-store ./sessions saves each named session's cookie jar, cf_clearance included, to disk and reloads it in a new process. Warm a session once and reuse it instead of solving the challenge on every run. See docs/sessions.md.

Rotating fingerprints

--rotate-fingerprint gives every browser context its own coherent machine: TLS emulation, User-Agent, client hints, platform, screen and WebGL all agree. --geoip-timezone matches the timezone and languages to the proxy's exit IP. See docs/fingerprints.md.

Builds

Build

What it adds

Where

light (default)

everything above; canvas and WebGL pixels are synthesised

pip, npm, ghcr.io/koloss777/nokk:latest, nokk-*.tar.gz

render

real canvas 2D and WebGL rasterisation, about 100 MB more at peak

:render image, nokk-render-*.tar.gz, --features render,webgl

Prebuilt for Linux x86_64 and ARM64, macOS on Apple Silicon and Windows x64; the render build for Linux x86_64. Docker variants, the archives and building from source are in docs/install.md.

How it works

A Cargo workspace of small crates: a V8 isolate pool, a Chrome-fingerprinted HTTP client on BoringSSL, an html5ever DOM, the stealth layer and a CDP server. Concurrency is one isolate per thread with many contexts each, all IO runs on tokio off the isolate threads, and the JS fingerprint and the TLS fingerprint always agree. More in docs/architecture.md.

Project status

Alpha. The engine is real and end-to-end: V8 executes page JS against a parsed DOM, the fingerprinted transport clears Cloudflare's TLS/HTTP checks, the engine solves Turnstile on live sites — invisible, managed and interactive — and Puppeteer and Playwright connect over CDP to open a page, navigate, and evaluate.

What is not done yet, and where the sharp edges are:

  • JS-fingerprint hardening is ongoing. Much of the hardening is in place — native toString masking, internals hidden from Object.getOwnPropertyNames, navigator/screen as real prototype instances, an IP-coherent timezone, and per-context coherent fingerprint rotation, Web Workers, canvas/WebGL/WebGPU/audio with Chrome's pixels and samples, Trusted Types and CSP. nokk solves Cloudflare's challenges today, and the comparison against Chrome section by section is how the remaining tells get found; it is not yet a match for a dedicated fingerprinting suite like CreepJS. See the roadmap.

  • CDP coverage is the common path, not the whole protocol. Puppeteer and Playwright connect over CDP: navigation, evaluate, $ / $eval / $$eval, title(), url(), new pages and CDP sessions are tested; less-common domains are not implemented yet.

  • Per-context cookie isolation and per-session persistence work (each browser context gets its own jar; named sessions persist across runs); per-host / per-proxy / global connection limits are not yet enforced (Phase 7).

  • No rendering — screenshots, PDF, and layout/paint are out of scope by design.

See ROADMAP.md for the phased plan and the concrete hardening backlog.

Contributing

Issues and PRs are welcome — the hardening backlog in the roadmap is a good place to start. Before sending a change:

cargo fmt
cargo clippy --all-targets
cargo test

License

Licensed under either of MIT or Apache-2.0 at your option.

Unless you explicitly state otherwise, any contribution you submit for inclusion in this work, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.


Available Tools

10 tools
challenge_stateA

Which gate the current page shows: kind is "none", "cloudflare-interstitial", "turnstile-widget", "aws-waf", "recaptcha-widget" or "datadome" (recognised, not solvable); solvable says whether solve_challenge can take it on.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/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 output fields and the notable behavior that datadome is recognised but not solvable, but it does not explicitly confirm the call is side-effect-free or safe to poll.

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?

The single sentence is front-loaded with what the tool reports, then lists only the necessary enum values and the solvable linkage. No sentence is redundant for a state-query tool.

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

Completeness5/5

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

For a zero-parameter state query with an output schema present, the description supplies the key enum meanings and the relationship to solve_challenge. An agent has enough context to call it and interpret the result.

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?

There are zero input parameters, so the baseline is 4. The description does not need to document parameter syntax, and it adds useful output-field semantics instead.

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

Purpose5/5

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

It states exactly what is reported: the gate shown on the current page, with enumerated kind values. It also names solve_challenge and clarifies that solvable indicates whether solve_challenge can handle the gate, distinguishing this state check from the solving action.

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?

The mention that solvable indicates whether solve_challenge can take it on implies this tool should be consulted before solving, but it does not explicitly say when to call it, when not to call it, or what to do for each gate kind. Usage is inferable rather than spelled out.

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

clickC

Click the first element matching the CSS selector.

NameRequiredDescriptionDefault
selectorYes

Output Schema

NameRequiredDescription
resultYes

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations provided, the description carries the full behavioral burden, yet it does not disclose whether clicking waits for the element, scrolls it into view, what happens if no element matches, or what side effects (e.g., navigation) may occur. It only notes that the first matching element is targeted, leaving critical interaction behavior unclear.

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?

A single, front-loaded sentence that contains no wasted words. The action and targeting rule are conveyed immediately.

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

Completeness2/5

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

For a browser-automation click tool with no annotations and an output schema, the description is missing key behavioral context: whether the click is synchronous, how failures are handled, and what preconditions exist. Output schema may cover return values, but the description is too sparse for the complexity of the action.

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

Parameters3/5

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

Schema coverage is 0%, so the schema itself provides no meaning beyond 'Selector: string'. The description compensates partially by clarifying that selector is a CSS selector and that the first matching element is clicked, but it adds no syntax details, examples, or constraints.

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 states a specific verb (click) and target (first element matching the CSS selector), making the basic action clear. However, it does not differentiate this tool from siblings like fill or evaluate, which could also interact with elements.

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 guidance on when to use click versus alternatives such as fill or evaluate, nor are there any stated prerequisites or exclusions. The agent must infer usage from the tool name and one-sentence description alone.

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

evaluateC

Evaluate a JavaScript expression in the current page and return its value.

NameRequiredDescriptionDefault
expressionYes

TDQS

C2.9/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 burden for an arbitrary-code-execution tool, yet it says nothing about side effects, whether the expression can mutate page state, whether it runs before or after page load, or how failures surface. It does at least anchor execution to 'the current page', which is minimal but useful context.

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?

One sentence, front-loaded with the action and ending with the return behavior; nothing is wasted. It is terse to the point of under-specification, but the structure itself is clean.

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

Completeness2/5

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

No output schema exists, so the description should explain what 'its value' looks like when serialized (primitives vs. objects vs. DOM nodes) and how errors are returned. For a tool that executes arbitrary code, these omissions leave meaningful ambiguity for correct invocation.

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

Parameters3/5

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

Schema description coverage is 0% for the single 'expression' parameter, so the description must compensate; it does partially by clarifying the value is a JavaScript expression whose result is returned. It adds no information on whether statements, multi-line bodies, or async expressions are accepted.

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 ('Evaluate a JavaScript expression in the current page') with the effect ('return its value'), which is far more informative than the bare name. It does not explicitly contrast with read_text/read_html, which are the obvious alternatives for extracting page content, so it falls short of full sibling differentiation.

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 guidance on when to choose this over read_text, read_html, or links, nor any warning about when not to use it. The agent must infer that this is for computed extraction that the other read tools cannot express.

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

fillB

Set the value of the form field matching selector and fire input/change.

NameRequiredDescriptionDefault
valueYes
selectorYes

Output 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 behavioral burden. It usefully discloses that input and change events are dispatched (important for framework-driven pages), but omits whether the existing value is replaced or appended, whether the element is scrolled into view, and how failures are reported.

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?

One tight sentence with the operation front-loaded and no filler. The doubled backticks around selector are a minor formatting blemish but cost no comprehension.

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, with zero annotations and zero schema descriptions on a mutation-style DOM interaction, the description should say more about value replacement semantics and failure behavior to be fully sufficient.

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 both required parameters. The description only says the selector 'matches' a form field; it does not specify accepted selector syntax (CSS vs XPath) or clarify that value is a raw string assignment rather than e.g. key-by-key typing.

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 the value of the form field matching selector') plus a behavioral effect (fire input/change), which clearly separates it from siblings like click or read_text. It does not explicitly name an alternative, but the resource-level specificity is enough to identify the operation.

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?

No guidance on when to use this instead of click or evaluate, no prerequisites such as the element needing to be visible, enabled, or already focused, and no mention of what happens when the selector matches nothing or multiple elements.

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

openA

Navigate the stealth browser to url. Returns the final {url, title}.

A Cloudflare challenge on the way is solved before this returns (unless the server runs with --no-auto-solve); challenge then reports what was met: kind, solved, and remaining ("none" when through).

NameRequiredDescriptionDefault
urlYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

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

No annotations are provided, so the description carries the behavioral burden, and it does disclose the non-obvious automatic Cloudflare challenge solving plus the `--no-auto-solve` exception. It also explains that `challenge` reports `kind`, `solved`, and `remaining`, though it omits timeout, error, and session/cookie effects.

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?

The definition is two sentences, front-loaded with the navigation action and return shape, then adding the Cloudflare caveat. The parenthetical detail is purposeful and does not obscure the core operation.

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 return values need not be fully explained, and the description adds important context about challenge handling. It is mostly complete for a one-parameter navigation tool, though explicit sibling usage guidance is still missing.

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?

The only parameter is `url`, and schema description coverage is 0%, so the description must compensate for the missing documentation. It repeats `url` in context but adds no format details, validation rules, or absolute/relative URL semantics.

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 states a specific verb and resource: navigate the stealth browser to `url`, and it identifies the returned `{url, title}`. It does not explicitly distinguish this from sibling tools such as `solve_challenge`, `challenge_state`, or `read_html`, so it falls short of a 5.

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?

The description implies this is the navigation tool and notes automatic Cloudflare challenge solving unless `--no-auto-solve` is set. However, it does not say when to choose `open` versus siblings like `solve_challenge`, `challenge_state`, or `read_text`, leaving usage largely inferred.

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

read_htmlA

Outer HTML of the current page, or of the first element matching the CSS selector if given.

NameRequiredDescriptionDefault
selectorNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

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

No annotations, so the description carries the full burden. It does disclose two useful behaviors: omitting the selector returns the whole page, and when a selector is given only the FIRST match is returned. It omits what happens on a non-matching selector (empty result vs. error), whether the call scopes to the top-level document or includes iframes/shadow DOM, and any size limits.

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?

One sentence, front-loaded with the primary return value, with the conditional selector case appended. Nothing wasted.

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 return shape needn't be described, and the description covers the main behavioral question (whole page vs. single matched element). The remaining gap is failure/miss semantics, which matters more here because there are no annotations to fall back on.

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 supply meaning and it largely does: the sole parameter is a CSS selector, it is optional (default yields the full page), and only the first match is used. Missing only a concrete selector syntax example.

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 resource and the exact thing returned: the outer HTML of the current page, or of the first element matching the CSS selector. This implicitly separates it from read_text (markup vs. text) without naming that sibling, so an agent can still route correctly but must infer the boundary.

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 only implied: you'd reach for it when you need raw markup rather than extracted text. There is no explicit 'use this instead of read_text when...' guidance and no stated preconditions such as requiring an open page.

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

read_textA

Visible text of the current page, or of the first element matching the CSS selector if given.

NameRequiredDescriptionDefault
selectorNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations, the description carries full behavioral burden. 'Visible text' usefully discloses that non-rendered content is skipped, but nothing is said about what happens when the selector matches nothing, whether it throws or returns empty, or whether any page navigation is triggered.

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?

A single front-loaded sentence with the default behavior folded into a subordinate clause. Nothing redundant and nothing padded.

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 shape need not be explained, and there is only one optional parameter. The remaining gap is a no-match / empty-result behavior, which matters for an agent deciding whether to fall back to read_html.

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% (the selector param is an undescribed string with an empty default), so the description must compensate. It does so meaningfully: selector is a CSS selector, matching is first-element-only, and omitting it defaults to the whole page's text.

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+resource ('read_text') and scopes it: visible text of the current page, or of the first element matching a CSS selector. That contrasts implicitly with the sibling read_html (raw markup vs rendered text), though it never names the sibling.

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?

The word 'visible' implies rendered text extraction as opposed to markup, which nudges toward read_html for structure. But there is no explicit when-to-use statement, no exclusion (e.g., iframes, hidden elements), and no alternatives named.

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

resetA

Discard the current browsing session (a fresh, coherent identity is used for the next navigation).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

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

No annotations are provided, so the description must carry the behavioral burden. It does disclose the key side effect (the session is discarded) and the post-condition (new identity on next navigation), but says nothing about what exactly is lost (cookies, storage, challenge state) or whether the reset affects in-flight state used by solve_challenge/challenge_state.

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?

A single sentence with the action front-loaded and the consequence in a compact parenthetical. Every clause adds information; nothing is redundant.

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?

For a zero-parameter reset with an output schema covering return values, the definition gives enough to call it correctly. The one gap is the interaction with sibling state tools (challenge_state, solve_challenge), which an agent might reasonably wonder about.

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 the baseline is 4; there is nothing for the description to disambiguate. It does not need to explain any inputs.

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 ('discard') and a specific resource ('the current browsing session'), plus the resulting state ('a fresh, coherent identity is used for the next navigation'). That is clear enough to separate it from open/click/fill, though it never names a sibling to contrast against.

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?

The parenthetical implies the reason to call it (you want a clean identity before the next navigation), but there is no explicit when-to-use / when-not-to-use statement or reference to alternatives such as opening a new page or clearing challenge state. Usage is inferable rather than stated.

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

solve_challengeA

Solve the Cloudflare challenge the current page shows — the "Just a moment…" interstitial or a Turnstile widget — pressing its checkbox if it puts one up. Returns status, solved, remaining, title, url.

NameRequiredDescriptionDefault
timeout_secondsNo

Output 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 burden and does explain the interaction (checkbox press if offered) and lists returned fields. It omits key behavior: whether it blocks/polls until solved, what happens when it times out, and whether it is safe to re-invoke.

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 tight sentences with the action front-loaded and the return fields enumerated at the end. Little waste, though the return-value list partly duplicates the existing output schema.

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?

The output schema already documents the return shape, so listing status/solved/remaining/title/url is redundant but harmless. For a no-annotation, no-required-param tool the remaining gap is failure/timeout behavior, which is a moderate rather than fatal omission.

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

Parameters3/5

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

The single optional timeout_seconds parameter has a self-explanatory name and a schema default, but schema coverage is 0% and the description says nothing about it — notably what happens when the timeout is exceeded, despite 'remaining' hinting at a waiting loop.

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?

Names a specific action and target: solving the Cloudflare interstitial or Turnstile widget by pressing its checkbox. It is clearly distinct from read_text/click/fill, but it never mentions the sibling challenge_state, which is the obvious diagnostic counterpart.

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?

Implicitly scoped to 'the current page' showing a challenge, but there is no guidance on when to call it versus challenge_state, nor what to do if no challenge is present or if it recurs after solving.

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. 10 tool updatesv0.1.46
    • First observedchallenge_state
    • First observedclick
    • First observedevaluate
    • First observedfill
    • First observedlinks
    • First observedopen
    • First observedread_html
    • First observedread_text
    • First observedreset
    • First observedsolve_challenge

TDQS

A3.5/5.0

Scored across 10 tools

Disambiguation4/5

Each tool maps to a distinct action on the browser session: navigate (open), interact (click/fill), read (read_text/read_html/links), execute JS (evaluate), and Cloudflare handling (solve_challenge vs challenge_state, one acting and one querying). The only mild overlap is that `open` can auto-solve challenges while `solve_challenge` does so manually, but the description explicitly flags this and reports the challenge outcome, so an agent can tell them apart.

Naming Consistency4/5

Names are uniformly short, lowercase snake_case, with related tools grouped by prefix (read_text/read_html, challenge_state/solve_challenge). Some tools are bare verbs (open, click, fill, evaluate) and one is a bare noun (links), so it is not a strict verb_noun pattern throughout, but the convention is predictable and readable.

Tool Count5/5

Ten tools is well-scoped for a stealth browser driver: navigation, two readers, two interaction primitives, JS evaluation, link extraction, challenge state/solve, and session reset. Nothing looks redundant or padded.

Completeness4/5

The core browse-inspect-interact lifecycle plus Cloudflare bypass and session reset is covered, but there is no wait-for-element, screenshot, keyboard press/Enter, select-option, or history navigation tool. Most of these gaps are workaroundable via `evaluate` and `click`/`fill`, so they are minor rather than blocking.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers