Skip to main content
Glama
wikydtron

brightdata-mcp-plus

by wikydtron

brightdata-mcp-plus is a Model Context Protocol server that gives AI agents (Claude Code, Claude Desktop, Cursor, VS Code, any MCP client) reliable access to live web data: page fetching, search, 1,200+ pre-built scrapers, datasets and remote browsers.

It is a ground-up TypeScript rebuild of the official @brightdata/mcp, keeping its tool names and environment variables so it works as a drop-in replacement, and adding what it was missing: free direct fetching and local Chrome rendering, with Bright Data only as the fallback for bot walls, spending guards, caching, pagination, cancellation, retries, an SSRF guard, a built-in HTTP transport and a real test suite.

Unofficial project, not affiliated with Bright Data. Bright Data features (search, scrapers, unblocking, remote browsers) need your own Bright Data API token and are billed by Bright Data. Page fetching, including JavaScript apps rendered in your own Chrome, works with no account at all.

Contents

Related MCP server: Spider MCP Server

Why it costs less

Bright Data charges per request. Most pages an agent reads (docs, blogs, news, GitHub, package registries, Wikipedia) don't block ordinary requests, so paying a proxy network to fetch them is wasted money. This server tries two free routes first:

  1. Direct fetch from your machine: plain HTTP, fast, works for most of the web.

  2. Local headless Chrome (or Edge) when the page is a JavaScript-only app shell: Spotify, Instagram, YouTube, TikTok, Figma, Duolingo and other single-page apps render for free on your own browser.

Only real bot walls (Cloudflare challenges, DataDome, PerimeterX, CAPTCHAs) go to Bright Data. Repeated fetches come from a cache, also free.

That screenshot is a real run of scripts/live-smoke.mjs against live websites with no API token. Wikipedia, Hacker News and GitHub were fetched directly. Spotify, Instagram, YouTube and TikTok, which send an empty shell to plain HTTP clients, were rendered in a local headless Chrome and returned their real content (follower counts, bios, video and track lists). G2's Cloudflare challenge and Reddit's CAPTCHA were detected; with a token these go to Bright Data automatically. An attempt to read the cloud-metadata address was refused by the SSRF guard. Every result tells the agent how it was fetched:

[server] Fetched directly (free).
[server] Rendered in a local headless browser (free): the page needs JavaScript.
[server] Fetched via Bright Data (billed): free routes were not usable (needs_javascript > render:captcha).
[server] Served from cache (originally via free direct fetch; no cost).

Quick start

Requires Node.js 22+. Google Chrome or Microsoft Edge is optional: with one installed, JavaScript apps are rendered locally for free; without one they go to Bright Data (or fail in free mode).

git clone https://github.com/wikydtron/brightdata-mcp-plus.git
cd brightdata-mcp-plus
npm install        # also builds (prepare script)
npm test           # optional: 70 tests, ~10 s

Or run it straight from GitHub without cloning:

npx -y github:wikydtron/brightdata-mcp-plus --list-tools

Free mode (no account): start it without API_TOKEN. You get scrape_as_markdown, scrape_batch, scrape_as_html, extract and session_stats, fetching directly and rendering JavaScript apps in your local Chrome or Edge (found automatically; set CHROME_PATH otherwise). Add BROWSER_CDP_ENDPOINT to drive your own Chrome with the interactive browser tools too.

Full mode: set API_TOKEN to unlock search, scrapers, datasets, AI-insights and Bright Data's remote browsers. Page fetching still tries the free routes (direct, then local Chrome) first, so only bot-walled pages are billed. Check your token and zones first:

API_TOKEN=your_token node dist/src/index.js --check

Connect your client

claude mcp add brightdata -e API_TOKEN=your_token -- node /absolute/path/to/brightdata-mcp-plus/dist/src/index.js

Leave out -e API_TOKEN=... for free mode.

{
  "mcpServers": {
    "brightdata": {
      "command": "node",
      "args": ["/absolute/path/to/brightdata-mcp-plus/dist/src/index.js"],
      "env": { "API_TOKEN": "your_token", "BUDGET_MAX_REQUESTS": "500" }
    }
  }
}
{
  "mcpServers": {
    "brightdata": {
      "command": "node",
      "args": ["/absolute/path/to/brightdata-mcp-plus/dist/src/index.js"],
      "env": { "API_TOKEN": "your_token" }
    }
  }
}

VS Code uses "servers" instead of "mcpServers" as the top-level key.

node dist/src/index.js --transport http --port 3000

Clients connect to http://127.0.0.1:3000/mcp with Authorization: Bearer <bright data token>. Each MCP session gets its own token, cache, budget and browser, so one server can serve several people. ?groups= and ?tools= work like on Bright Data's hosted server; ?token= is accepted for compatibility but logs a warning because URLs end up in logs. Binding to a non-loopback address with a shared API_TOKEN requires HTTP_AUTH_SECRET (sent by clients as x-mcp-auth). Health check: GET /healthz.

docker build -t brightdata-mcp-plus .
docker run -i --rm -e API_TOKEN=your_token brightdata-mcp-plus

The image is a slim Node.js image without a browser, so local rendering is skipped there and JavaScript apps go to Bright Data. Run it with Node directly if you want free rendering.

How page fetching works

FETCH_STRATEGY

Behaviour

Cost

auto (default)

Direct, then local Chrome for JavaScript apps, then Bright Data Web Unlocker for bot walls and failures

Only bot-walled pages are billed

direct

Direct and local Chrome only; blocked pages return an error with the reason

Never billed

brightdata

Always Web Unlocker (upstream behaviour)

Every fetch billed

(no API_TOKEN)

Free mode: direct, Bright Data tools hidden

Free

Details:

  • Bot-wall detection looks for Cloudflare challenges, DataDome, Imperva, PerimeterX, AWS WAF, Google's "unusual traffic" page, CAPTCHA widgets and JavaScript-only shells. CAPTCHA keywords only count on short pages, so an article with a reCAPTCHA contact form is still fetched for free. Rendered pages are classified again, so a bot wall that only appears after JavaScript runs is still caught.

  • Local rendering uses your installed Chrome or Edge through playwright-core (no browser download). One headless browser is shared by all sessions, each render gets a fresh incognito context, images, media and fonts are skipped, and the browser closes after 2 idle minutes. A render finishes as soon as the app has produced text or its network goes quiet, so an empty shell fails over in about a second instead of waiting out a timeout. The first render after the browser has been closed can take several seconds longer while it starts. It renders pages; it does not try to evade bot detection, so walls still go to Bright Data, which exists for that.

  • Host memory: for 30 minutes, a host that needed rendering skips the direct attempt, and a host that blocked goes straight to Bright Data.

  • Country routing (country: "de") always uses Bright Data, since geo-targeting needs a proxy.

  • Direct fetches follow up to 5 redirects, decode gzip/deflate/brotli, honour the page charset, stop at 15 s and 10 MB, and convert HTML to Markdown with absolute links.

  • Limits: apps that keep streaming data after the first paint (Google Maps, live trading charts) may render only their UI chrome. For structured data from those, use a pre-built scraper (search_scrapers "google maps") or the interactive scraping_browser_* tools.

Tools (34)

Tool

What it does

Key options

search_engine

Google (ranked JSON), Bing or Yandex (Markdown)

engine, geo_location, language, time_range, cursor, fresh

search_engine_batch

Up to 10 searches in parallel

queries[]

scrape_as_markdown

One page as compact Markdown via direct → local Chrome → Bright Data; a note says which

format (markdown/text/raw), offset, max_chars, country, fresh

scrape_batch

Up to 10 pages in parallel, each with its source (direct, local_browser, brightdata, cache)

urls[], max_chars_per_url

scrape_as_html

HTML, paginated (the rendered DOM when the page needed JavaScript)

offset, max_chars

extract

Page to JSON using your own model via MCP sampling; fetches like scrape_as_markdown

extraction_prompt, schema (JSON Schema)

Tool

What it does

search_scrapers

Ranked search of the scraper catalog by site, domain, data type or gd_ id

get_scraper_details

Input fields (with required flags), example input, output fields

run_scraper

Validates input before anything is billed, enforces MAX_RECORDS_PER_RUN, waits up to wait_seconds, pages records

get_scraper_progress

Job status

get_scraper_results

Records with offset/limit; finished snapshots are cached so paging is free

refresh_scrapers

Reload the catalog now

Tool

What it does

list_dataset_fields / search_dataset

Filter search over LinkedIn people and company datasets

chatgpt_ai_insights / perplexity_ai_insights

Ask ChatGPT or Perplexity (for GEO / brand visibility); long jobs return a snapshot_id instead of failing

ask_brightdata_assistant

Bright Data's support assistant, with threaded follow-ups

session_stats

Calls, errors, p50/p95 latency, cache hits, billable units, estimated cost, free direct fetches and local renders, savings, local-rendering status, budget left

scraping_browser_navigate, _go_back, _go_forward, _snapshot (ARIA refs, optional filtering), _click_ref, _type_ref, _press_key, _fill_form, _screenshot (JPEG by default), _get_text, _get_html (both paginated), _scroll (top/bottom/up/down), _scroll_to_ref, _wait_for_ref, _network_requests (filter by type or URL), _close. Idle browsers close automatically and open sessions are capped.

Prompts: web_scraping_strategy and diagnose_scraping_approach (takes a url).

Configuration

All settings are environment variables (names compatible with @brightdata/mcp). Run --help for CLI flags.

Variable

Default

Purpose

API_TOKEN

—

Bright Data API token. Without it: free mode

FETCH_STRATEGY

auto

auto, direct or brightdata (see above)

DIRECT_TIMEOUT / DIRECT_MAX_BYTES

15 s / 10000000

Limits for direct fetches

DIRECT_USER_AGENT

Chrome UA

User-Agent for direct fetches

DIRECT_ALLOW_PRIVATE

false

Allow direct fetches and renders of localhost/LAN addresses

LOCAL_RENDER

on

Render JavaScript apps in local Chrome/Edge before paying Bright Data (off to disable)

CHROME_PATH

auto

Browser executable if Chrome/Edge isn't in its standard location

LOCAL_RENDER_TIMEOUT / LOCAL_RENDER_IDLE

25 s / 120 s

Per-render limit; close the browser after this idle time

LOCAL_RENDER_ON

needs_javascript,empty

Direct-fetch results that trigger a local render

LOCAL_RENDER_CONCURRENCY

2

Parallel renders

WEB_UNLOCKER_ZONE / BROWSER_ZONE

mcp_unlocker / mcp_browser

Zone names

AUTO_CREATE_ZONES

true

Create missing zones at startup

GROUPS / TOOLS

all

Limit tools; legacy web_data_* names map to the new tools

BUDGET_MAX_REQUESTS

0 (off)

Max billable units per session

MAX_RECORDS_PER_RUN

200

Refuse scraper runs that could return more billed records

RATE_LIMIT

off

Local limit for all tools, e.g. 100/1h

PRICE_PER_1K

1.5

USD per 1K results, for estimates only

BASE_TIMEOUT / BASE_MAX_RETRIES

90 s / 2

Bright Data API timeout and retries

MAX_CONCURRENCY

5

Concurrent upstream requests per session

CACHE_TTL / CACHE_MAX_ENTRIES

300 s / 200

Response cache (0 disables)

MAX_OUTPUT_CHARS

60000

Default page size for content tools

CONTENT_GATE / CONTENT_GATE_TIMEOUT

on / 120 s

Prompt-injection gate

BROWSER_IDLE_TIMEOUT / MAX_BROWSER_SESSIONS

300 s / 3

Browser reaping and cap

BROWSER_CDP_ENDPOINT

—

Use your own Chromium (ws://…/devtools/browser/…)

BROWSER_FILTERED_SNAPSHOT

off

Always filter snapshots

MCP_TRANSPORT, HOST, PORT

stdio, 127.0.0.1, 3000

Transport

HTTP_AUTH_SECRET, HTTP_SESSION_IDLE_TIMEOUT

—, 1800 s

HTTP access secret, idle timeout

LOG_LEVEL

info

debug, info, warn, error, silent

Cost control

  • Budget: BUDGET_MAX_REQUESTS=500 stops a session before its 501st billable unit. Units are reserved before each call, so parallel calls can't overshoot together. Cached pages stay available after the budget is spent.

  • Scraper guard: run_scraper refuses discover_by_* runs whose worst case (inputs × limit_per_input) exceeds MAX_RECORDS_PER_RUN, and checks required input fields before triggering, so typos are never billed.

  • No double billing: job triggers are retried only when Bright Data rejected them (429), never after a timeout that may have started a job.

  • Visibility: session_stats returns

{
  "fetch_strategy": "auto",
  "local_rendering": "on",
  "billable": { "unlocker_requests": 3, "scraper_records": 10, "dataset_records": 0, "browser_navigations": 0 },
  "estimated_cost_usd": 0.0195,
  "free": { "direct_fetches": 42, "local_renders": 9, "fallbacks": 3, "estimated_savings_usd": 0.0765 },
  "budget": { "max": 500, "used": 13, "remaining": 487 },
  "tools": { "scrape_as_markdown": { "calls": 45, "errors": 0, "cache_hits": 6, "p50_ms": 410, "p95_ms": 1890 } }
}

Security model

Threat

Defence

Prompt injection in web content

Every web result is wrapped between =====UNTRUSTED_<random nonce>_BEGIN/END===== markers with a notice; forged markers are scrubbed

Pages telling the agent to change its MCP config

Content gate: matching content is withheld unless the user approves it through MCP elicitation

SSRF (agent tricked into reading 169.254.169.254, your router, local services)

Direct fetches resolve DNS and refuse private, loopback, link-local and metadata ranges on every redirect hop; the local renderer only opens URLs whose redirect chain passed that check, blocks every in-page request to those ranges, and discards a page that ends up on one

Credential leaks

API token, zone passwords and URL credentials are redacted from logs and errors; the token is never put in a URL

Ambiguous browser refs

A ref that appears more than once in the snapshot (e.g. echoed by page text) is refused

Exposed HTTP server

Loopback by default, DNS-rebinding protection, HTTP_AUTH_SECRET required for shared tokens on public interfaces

Architecture

src/
  index.ts            CLI: flags, --check, --list-tools, stdio startup, graceful shutdown
  config.ts           Validated config (env + flags)
  server.ts           createSession(): one isolated McpServer + services; the tool pipeline
  http/client.ts      The only path to the Bright Data API: auth, timeouts, retries, concurrency, typed errors
  http/server.ts      Streamable HTTP transport with per-session isolation
  services/           pages (direct → render → Bright Data), direct (SSRF-safe fetch + classifier),
                      render (local headless Chrome), unlocker, serp, scrapers, datasets, assistant,
                      browser, zones
  tools/              Tool definitions (zod schemas, annotations), grouped by area
  security/           Untrusted-content wrapping, prompt-injection content gate
  usage.ts            Stats, budget reservations, rate limiting, savings
  util/               Cache, semaphore, pagination, Markdown minifier, redaction

Compared with @brightdata/mcp

Area

@brightdata/mcp 4.1.0

brightdata-mcp-plus

Page fetching

Every fetch billed

Direct, then local headless Chrome for JavaScript apps (both free), Bright Data only for bot walls; free mode with no account

Language

~2.8k lines of untyped JS

Strict TypeScript, layered

Timeouts

None by default; two tools ignore BASE_TIMEOUT

Every call (90 s default)

Retries

Off by default, no backoff

Jittered backoff, Retry-After, never re-triggers billed jobs

Cancellation

Ignored; polling can run 10 min after the client gave up

Aborts requests, polling and queued work

Batch size

Docs say 10, code allows 5

10

Caching

None

TTL + LRU, single-flight

Large pages

Returned whole

Paginated with next_offset

Cost guards

None

Budget, per-run record cap, pre-billing input validation

Free-tier message

Missing for scraper and browser tools

Every tool

RATE_LIMIT

Browser tools skip it

Every tool

extract

Samples from the first session, not the caller

Calling session, optional JSON Schema

HTTP

Hosted only, token in URL

Built in, header auth, per-session isolation

SSRF protection

n/a

Private-range guard on every redirect hop and on every request inside the local browser

Docker

Image copies 3 of 15 modules

Multi-stage, non-root, healthcheck

Tests

Unit and stub tests

70: unit, fake Bright Data API, real MCP clients over in-memory/stdio/HTTP, real headless Chrome (CDP and local rendering)

Development

npm run build          # tsc
npm test               # build + 70 tests (browser and render tests use local Chrome/Edge if found)
npm run typecheck
node scripts/live-smoke.mjs                                 # real sites, free mode, no cost
node scripts/live-smoke.mjs --json assets/src/live-run.json # refresh demo data
node scripts/render-assets.mjs                              # re-render README images (needs Chrome/Edge)

Test suites: unit (config, cache, semaphore, errors, security, SERP, pagination, scoring, budget), client (retries, Retry-After, timeouts, cancellation, headers), e2e (all tool families through a real MCP client), direct (direct fetching, bot-wall detection, fallback, SSRF, free mode), render (local Chrome: client-rendered pages, XHR, walls that appear after JavaScript, host memory, in-browser SSRF guard), http (multi-tenant HTTP), stdio (the built CLI as a subprocess) and browser (a real headless Chrome over CDP).

FAQ

Is it free? Fetching pages directly and rendering them in your own Chrome is free. Bright Data's own services (search, scrapers, unblocking protected sites, remote browsers) run on their infrastructure and are billed to your Bright Data account; their free tier is 5,000 requests a month. This server just makes sure you only use them when needed.

Why did a page cost a request? The result note says why, e.g. cloudflare_challenge or needs_javascript > render:captcha (a JavaScript app that showed a CAPTCHA even to a real browser). Use FETCH_STRATEGY=direct to never pay, at the cost of failing on protected sites.

Do I need Chrome? No. Without Chrome or Edge the render step is skipped: the first page that needs it falls through to Bright Data with the reason render:unavailable, and from then on session_stats shows local_rendering: "unavailable (no Chrome/Edge found)". Set CHROME_PATH if your browser is in a non-standard place, or LOCAL_RENDER=off to skip the attempt entirely.

Is direct fetching and local rendering allowed? Both are ordinary requests from your machine, the same as opening the page in your browser. You are responsible for respecting each site's terms and robots rules.

Is this official? No. It's an independent MIT-licensed project derived from brightdata/brightdata-mcp (MIT, see LICENSE.upstream).

License

MIT

Available Tools

5 tools
extractExtract Structured DataA
Read-only

Fetch a page and turn it into JSON using your own model via MCP sampling (no extra Bright Data cost beyond the page fetch). Pass extraction_prompt and optionally a JSON Schema in schema to shape the output.

NameRequiredDescriptionDefault
urlYes
freshNoBypass the response cache and fetch again (costs a request)
schemaNoOptional JSON Schema the output must follow
countryNo2-letter country code to route the request through (e.g. "us", "de")
extraction_promptNoWhat to extract

TDQS

A3.8/5.0
Behavior4/5

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

Adds genuine context beyond the annotations: extraction runs through MCP sampling on the caller's model, and there is no extra Bright Data cost beyond the page fetch. It also implicitly signals caching via the fresh parameter's cost note. It doesn't disclose failure behavior when the model returns schema-invalid JSON, which is the main remaining gap.

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 sentences, no waste; the mechanism and cost note come first and the parameter call-to-action second. Every clause carries information an agent needs.

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?

With no output schema, the description must convey the return shape and does (JSON, optionally constrained by a provided schema), and the cost model is covered. Missing only edge-case behavior such as what happens on extraction or schema-validation failure.

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 80%, so most parameters are already documented in-schema (fresh, country, schema, extraction_prompt). The description reinforces that extraction_prompt is the core input and schema is optional shaping, but adds no syntax or format detail beyond the schema. Baseline 3 is appropriate.

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 ('Fetch a page') and transformation ('turn it into JSON') plus the non-obvious mechanism (MCP sampling with the caller's own model). This distinguishes it functionally from scrape_as_markdown/scrape_as_html, though it never names those siblings, so an agent 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?

The description implies when to use it (when you want structured JSON shaped by a prompt/schema) and notes the cost profile, but gives no explicit when-to-use/when-not guidance relative to scrape_as_markdown or scrape_as_html. The choice must be inferred from the output format implied by each tool name.

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

scrape_as_htmlScrape as HTMLA
Read-onlyIdempotent

Fetch one page and return its raw HTML, paginated with offset/max_chars. Prefer scrape_as_markdown unless you need markup, attributes or embedded JSON. Pages are fetched directly for free when the site allows it, rendered in a local headless browser (also free) when they need JavaScript, and fetched through Bright Data Web Unlocker (billed) only when the site blocks; a note after the result says which.

NameRequiredDescriptionDefault
urlYes
freshNoBypass the response cache and fetch again (costs a request)
offsetNoCharacter offset to start from; use next_offset from a truncated result
countryNo2-letter country code to route the request through (e.g. "us", "de")
max_charsNoMaximum characters to return (default: server MAX_OUTPUT_CHARS)

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/idempotent/non-destructive, but the description adds substantive behavior beyond them: a three-tier fetch strategy (free direct, free headless render, billed Bright Data unlocker) and the fact that the result includes a note stating which path was taken. This billing/cost disclosure is exactly the kind of context annotations cannot convey.

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?

Three tight sentences, each front-loaded with the most actionable information: what it returns first, the alternative second, the cost model third. No filler.

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?

With no output schema, the description still covers return format (raw HTML, character offsets), the cost/billing implications, and the fallback ladder. Nothing an agent needs to select or call this tool correctly is missing.

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 80%, so the schema already documents most params. The description adds workflow meaning by framing offset/max_chars as a pagination pair and implying the truncated-result flow, though it doesn't explain the interaction with next_offset beyond what the schema says.

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?

States a specific verb and resource ('Fetch one page and return its raw HTML') plus its pagination model, and explicitly contrasts with the scrape_as_markdown sibling so an agent can choose without opening either schema.

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

Usage Guidelines5/5

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

Explicitly names the preferred alternative and the exact condition to deviate: 'Prefer scrape_as_markdown unless you need markup, attributes or embedded JSON.' That is a clear when-to-use and when-not-to-use rule.

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

scrape_as_markdownScrape as MarkdownA
Read-onlyIdempotent

Fetch one web page and return it as compact Markdown. Pages are fetched directly for free when the site allows it, rendered in a local headless browser (also free) when they need JavaScript, and fetched through Bright Data Web Unlocker (billed) only when the site blocks; a note after the result says which. Long pages are paginated: when truncated, call again with the returned offset. Use format=raw for the unprocessed Markdown.

NameRequiredDescriptionDefault
urlYes
freshNoBypass the response cache and fetch again (costs a request)
formatNomarkdown: compact Markdown keeping headings, lists, tables, links (default); text: plain text with links; raw: as fetchedmarkdown
offsetNoCharacter offset to start from; use next_offset from a truncated result
countryNo2-letter country code to route the request through (e.g. "us", "de")
max_charsNoMaximum characters to return (default: server MAX_OUTPUT_CHARS)

TDQS

A4.1/5.0
Behavior5/5

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

Beyond the readOnly/openWorld/idempotent annotations, the description discloses the three-tier fetch strategy (direct free, headless browser free, Bright Data billed only on block) and that a note after the result identifies which path was used. The truncation/pagination behavior is also spelled out, which is exactly the kind of cost and output behavior annotations cannot convey.

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?

Three tight sentences, front-loaded with the core action, then cost behavior, then pagination and format tips. Every sentence carries distinct information with no repetitive restatement of the title.

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?

With no output schema, the description carries return-value burden and does explain the post-result note and pagination offsets. Minor gap: it says 'returned offset' while the schema field is next_offset, and it doesn't describe the shape of the Markdown payload beyond 'compact'.

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 83%, so the schema already documents nearly every parameter, including format, offset, fresh, and max_chars. The description adds only the format=raw recommendation and the offset-retry loop, which is marginal value over structured data. The 3 baseline applies.

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 opens with a specific verb and resource — 'Fetch one web page and return it as compact Markdown' — and the 'one web page' scope implicitly separates it from scrape_batch. It doesn't explicitly name siblings like scrape_as_html or extract, so the differentiation is inferred rather than stated.

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?

It gives clear operational guidance: use format=raw for unprocessed Markdown, and call again with the returned offset when a page is truncated. It also explains the fetch cost ladder, which tells an agent what to expect. It stops short of saying when to prefer scrape_as_html or extract over this tool.

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

scrape_batchScrape BatchA
Read-onlyIdempotent

Fetch up to 10 pages in parallel and return [{url, ok, source, content | error}] as JSON. Each page is capped (max_chars_per_url); fetch a single page with scrape_as_markdown to read past the cap. Pages are fetched directly for free when the site allows it, rendered in a local headless browser (also free) when they need JavaScript, and fetched through Bright Data Web Unlocker (billed) only when the site blocks; source says which.

NameRequiredDescriptionDefault
urlsYes
freshNoBypass the response cache and fetch again (costs a request)
formatNomarkdown: compact Markdown keeping headings, lists, tables, links (default); text: plain text with links; raw: as fetchedmarkdown
countryNo2-letter country code to route the request through (e.g. "us", "de")
max_chars_per_urlNo

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only say readOnly/idempotent/openWorld; the description adds the critical non-obvious behavior: a three-tier fetch strategy (free direct, free local headless browser, billed Bright Data Web Unlocker only when blocked) and the fact that `source` reports which tier was used. That cost/permission disclosure is exactly the context annotations cannot carry.

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?

Three sentences, no waste: return shape first, then the cap plus escape hatch, then the fetch/cost model. Each sentence carries distinct information the agent needs.

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?

No output schema exists, and the description compensates by specifying the exact response shape and the meaning of `ok`, `source`, `content`/`error`. Combined with the disclosed billing model for the Bright Data tier, an agent has everything needed to call it correctly and predict cost.

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 60%; the description supplies meaning for the undocumented max_chars_per_url (each page is capped) and explains the `source` field in the response, which the schema does not cover. It does not add anything about `country`, `fresh`, or `format` beyond what the schema already documents.

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?

States a specific verb (fetch), resource (up to 10 pages in parallel) and the exact return shape [{url, ok, source, content | error}], plus names the sibling scrape_as_markdown as the single-page alternative. An agent can distinguish it from scrape_as_markdown, scrape_as_html and extract without opening any schema.

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?

Explicitly routes the agent to scrape_as_markdown when it needs to read past the per-page cap, which is a real selection criterion. It does not spell out when to prefer batch vs. the other siblings (scrape_as_html, extract), so it stops short of full when/when-not coverage.

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

session_statsSession StatsA
Read-only

Usage this session: calls, errors, latency (p50/p95) and cache hits per tool, billable units, estimated cost, free direct fetches and savings, remaining budget, zone status and open browser sessions.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
freeYes
cacheYes
toolsYes
zonesYes
budgetYes
billableYes
uptime_sYes
fetch_strategyYes
upstream_callsYes
local_renderingYes
estimated_cost_usdYes
open_browser_sessionsYes

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, openWorldHint=false, and destructiveHint=false, so the safety profile is clear. The description adds the list of reported metrics, which is useful but overlaps with the output schema and does not disclose other behavioral traits (e.g., refresh cadence or whether the stats are real-time). With annotations covering safety, a 3 is appropriate.

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 description is a single, front-loaded sentence that enumerates the metrics efficiently. It is dense but not wasteful, though a brief introductory verb (e.g., 'Returns') would make it slightly more scannable.

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?

Given a zero-parameter read-only tool with an output schema and clear annotations, the description is sufficiently complete: it tells the agent what categories of data are available. It could be improved by specifying when to call it, but that is covered under usage guidelines.

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 parameters, so the baseline is 4. The description adds no parameter semantics because none exist, but the schema is empty and needs no further explanation.

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 clearly indicates this tool returns session usage statistics, enumerating the specific metrics (calls, errors, latency, cost, budget, zone status, browser sessions). The resource and scope are identifiable, and the sibling tools (scraping/extraction) are unrelated, so no differentiation is needed.

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: an agent would infer this is for checking session health and cost. There is no explicit when-to-use guidance, no mention of alternatives, and no exclusions. It is adequate but minimal.

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 updatesv1.2.0
    • First observedextract
    • First observedscrape_as_html
    • First observedscrape_as_markdown
    • First observedscrape_batch
    • First observedsession_stats

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: single-page Markdown, single-page HTML, parallel batch fetching, structured extraction, and session statistics. The descriptions explicitly distinguish when to use HTML versus Markdown and when to use batch versus single-page calls. There is little risk of misselection.

Naming Consistency4/5

Three scraping tools use a consistent scrape_* pattern, but extract and session_stats deviate from that prefix. All names are readable snake_case and descriptive, so the inconsistency is minor rather than confusing.

Tool Count5/5

Five tools is well-scoped for a web scraping server. Each tool earns its place by covering a distinct access mode or operational need.

Completeness4/5

The surface covers single-page Markdown, raw HTML, batch fetching, structured extraction, and usage monitoring, which is strong lifecycle coverage for scraping. Minor gaps could include explicit cache management or site-status checks, but core workflows are covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers