Skip to main content
Glama
@readfetch/mcp-x402-proxy

@readfetch/mcp-x402-proxy

readfetch MCP + x402 signing proxy

Most MCP hosts (Cursor, Claude Desktop, etc.) cannot attach PAYMENT-SIGNATURE on tools/call. This stdio MCP server lists tools from https://readfetch.com/mcp, executes tools/call against /v1/{endpoint} on the same host (so HTTP 402 triggers @x402/fetch payment), and signs retries automatically.

Requirements

  • Node.js 20+

  • A wallet on Base mainnet with a little USDC for paid tools (readfetch_text, …). tools/list does not load your key; the first tools/call does.

  • Private key in env — never commit it

Related MCP server: x402 MCP Proxy

Cursor / Claude MCP config

{
  "mcpServers": {
    "readfetch": {
      "command": "npx",
      "args": ["-y", "@readfetch/mcp-x402-proxy@0.1.14"],
      "env": {
        "EVM_PRIVATE_KEY": "0xYOUR_KEY"
      }
    }
  }
}

From a checkout:

{
  "mcpServers": {
    "readfetch": {
      "command": "node",
      "args": ["/absolute/path/to/readfetch/tools/mcp-x402-proxy/index.mjs"],
      "env": {
        "EVM_PRIVATE_KEY": "0xYOUR_KEY"
      }
    }
  }
}

Optional: READFETCH_MCP_URL (default https://readfetch.com/mcp; https only for readfetch.com / www.readfetch.com, or localhost / 127.0.0.1 / [::1] with READFETCH_DEV=1). Upstream redirects are rejected. READFETCH_MAX_PAYMENT_USD (default 1, max 100) caps each x402 authorization. On readfetch.com upstream, payments must match READFETCH_EXPECTED_PAYTO (default catalog payee). READFETCH_DEV=1 is only for local MCP URLs and enables Sepolia there — never set it when READFETCH_MCP_URL points at production.

Wallet risk: any tool the model invokes (readfetch_crawl, batch, …) can spend USDC from your key until the wallet is empty (subject to the per-payment cap). Use a dedicated low-balance wallet.

Install from a checkout:

cd tools/mcp-x402-proxy
npm ci

npm ci in a git checkout uses the committed package-lock.json. npx @readfetch/mcp-x402-proxy installs exact dependency versions pinned in package.json (npm does not ship the lockfile in the published tarball).

Local smoke (checkout)

npm ci && npm test
npm run smoke                                    # readfetch_probe (free)
SMOKE_TOOL=readfetch_text npm run smoke          # paid REST path; needs Base USDC

From this directory — not the repo root:

cd tools/mcp-x402-proxy
npm login                    # user must own or belong to npm org @readfetch
npm publish --access public  # first publish of a scoped package

Wrong: npm publish @readfetch/mcp-x402-proxy from ReadFetch/ (404 — nothing to publish there).

If the @readfetch org does not exist on npmjs.com, create it or temporarily change name in package.json to an unscoped name you control.

Default tool path

  1. readfetch_probe with { "url": "…" } (free; may include preview ~400 chars when HTML, not a bot wall)

  2. readfetch_text with the same url

  3. If probe reports challenge: true, use readfetch_scrape (then readfetch_scrape_residential if needed)

Feedback (integration issues)

After a confusing 402, MCP result, or doc mismatch, call readfetch_feedback (free — no EVM_PRIVATE_KEY) with:

{ "request_id": "<X-Request-Id from that call>", "category": "integration", "message": "…" }

Paid delivery disputes use POST /v1/claims, not feedback. Details: readfetch.com/docs#feedback.

Without this proxy

  • REST: awal x402 pay https://readfetch.com/v1/text -d '{"url":"…"}' or @x402/fetch in your app

  • Direct MCP URL: only works if your host can set payment headers on the HTTP request to /mcp

See also readfetch integrations and SKILL.md.

Directory: Official MCP Registry io.github.readfetch/mcp-x402-proxy · Glama listing steps in readfetch/readfetch docs/GLAMA.md (operator).

Available Tools

15 tools
readfetch_batchA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Read a fixed list of public HTML pages in one call—the same article extraction as POST /v1/text for each URL (Markdown or plain text plus title and metadata). One x402 payment covers the batch (minimum 10 pages quoted; URLs deduped, max 50). Returns results in input order: each item has url, status_code, text, billed, and hint when undelivered, plus batch-level delivered, failed, billed_pages, and optional credit for unused pages. Undelivered pages are not billed. Use readfetch_text for one URL, readfetch_map then readfetch_crawl to discover and walk a site, readfetch_scrape when JavaScript is required. Read-only; 402 without PAYMENT-SIGNATURE like other paid tools.

NameRequiredDescriptionDefault
urlsYesURLs to read, deduped before quoting.
formatNoPer-item output flavour, same as /v1/text: markdown (default) or plain text.markdown
pipelineNotext (default) = HTTP-first per URL, same as readfetch_text; use render when probe reported challenge:true or items need JavaScript — bills like scrape per undelivered page, not like plain text.text
timeout_sNoTotal budget for the whole batch in seconds; every item shares it and no item restarts it.
accept_languageNoAccept-Language header for every item, e.g. 'de-DE,de;q=0.9'. Defaults to en-US when omitted.

Output Schema

NameRequiredDescription
creditNo
failedNo
statusNo
resultsNo
deliveredNo
billed_pagesNo

TDQS

A4.5/5.0
Behavior4/5

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

Annotations only supply readOnlyHint and openWorldHint; the description adds the material missing context — x402 payment covering the whole batch, a 10-page minimum quote, dedup and a 50-URL cap, per-page billing where undelivered pages are not billed, and optional credit for unused pages. The one gap is that the 10-page minimum price floor sits oddly against a schema that allows a single URL, leaving the cost of a 1-page request ambiguous.

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?

Dense and mostly front-loaded, but it opens with payment prerequisites rather than the tool's purpose, pushing 'Read a fixed list of public HTML pages' into the middle. The closing '402 without PAYMENT-SIGNATURE' partially restates the opening payment sentence, a minor redundancy in an otherwise information-rich block.

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 paid batch tool the description covers prerequisites, billing model, ordering, per-item and batch-level return fields, and sibling alternatives — an output schema also exists, so field naming assistance is supplementary rather than load-bearing. The only uncertainty left is the practical interaction between the 10-page quote minimum and the schema's minItems of 1.

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 100%, so a 3 is the floor; the description earns above that by explaining batch-level semantics that the schema cannot — URLs are deduped before quoting, the batch has a minimum quoted size, and a shared time budget applies across items. It does not re-explain format/pipeline, which the schema already documents well.

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?

The description states a specific verb and resource — 'Read a fixed list of public HTML pages in one call' — and anchors it to existing semantics ('the same article extraction as POST /v1/text for each URL'). It also explicitly separates itself from readfetch_text (single URL), readfetch_map/readfetch_crawl (discovery and traversal), and readfetch_scrape (JS required).

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?

It gives explicit routing rules: use this for a fixed list, readfetch_text for one URL, map+crawl to discover and walk a site, scrape when JavaScript is required, and pipeline='render' when a probe reported challenge:true. It also states the prerequisite (funded Base USDC wallet plus a signing client or proxy) and the failure mode (402 on direct calls).

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

readfetch_crawlA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Start a bounded async crawl from one seed URL. Returns job_id, status (queued), pages_quoted, and price_usd — then poll readfetch_crawl_status with that id until status is complete or failed. A complete job includes per-page url and Markdown in the status payload. Cap scope with max_pages (default 20, max 100) and max_depth (default 2, max 3); include/exclude filter paths by prefix (* suffix on include). Prefer readfetch_batch for a fixed URL list; readfetch_map to list URLs without fetching bodies; readfetch_text for a single page.

NameRequiredDescriptionDefault
urlYesSeed URL; crawl stays on the same registrable domain.
excludeNoPath prefixes to skip during the crawl.
includeNoPath prefixes to allow; * suffix wildcard.
max_depthNoLink depth from the seed URL (default 2).
max_pagesNoMaximum pages to fetch in this job (quoted up front for payment).

Output Schema

NameRequiredDescription
hintNo
job_idNo
statusNo
price_usdNo
pages_quotedNo

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare readOnlyHint and openWorldHint; the description adds material behavior the annotations cannot express: a funded Base USDC wallet is required, direct calls without a signing client terminate at 402, and the accepted auth paths (readfetch-client, @readfetch/client, @readfetch/mcp-x402-proxy) are named. It further discloses the async lifecycle (job_id, status=queued, pages_quoted, price_usd) and that completed jobs carry per-page url and Markdown in the status payload.

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?

Dense but purposeful, with no filler sentences and a clean progression from prerequisites to action to follow-up to alternatives. The main structural flaw is ordering: the payment preamble occupies the opening position that should belong to the purpose statement, delaying the one-line "what it does" until the second sentence.

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 paid, asynchronous, open-world crawl tool, the description covers the prerequisite (funded wallet), failure mode (402), lifecycle and polling, and sibling routing. Return fields are also summarized even though an output schema exists, so an agent has everything needed to call, pay for, and complete the workflow.

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 100%, so all five parameters are already documented structurally, and the description largely restates what the schema says (max_pages default 20 / max 100, max_depth default 2 / max 3, include/exclude as prefix filters with * wildcard). The one genuinely additive note is that quoted page count drives up-front payment, but that is framed as billing behavior rather than parameter meaning, so the baseline 3 holds.

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?

"Start a bounded async crawl from one seed URL" gives a specific verb (start), resource (crawl), execution model (async) and scope constraint (bounded, one seed). It is immediately distinguishable from readfetch_text (single page), readfetch_map (URL listing only) and readfetch_batch (fixed list), which the description names directly.

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?

Explicit routing rules: prefer readfetch_batch for a fixed URL list, readfetch_map to list URLs without fetching bodies, readfetch_text for a single page. It also gives the follow-up protocol — poll readfetch_crawl_status with the returned job_id until complete or failed — so the agent knows both when to enter and when to exit this workflow.

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

readfetch_crawl_statusA
Read-only

FREE — no payment or wallet: Poll a crawl job started with readfetch_crawl. FREE — no payment or wallet; unauthenticated. Pass id from the crawl response. Returns job_id, status (queued, running, complete, or failed), completed/total counts, and a growing pages list (url plus Markdown) as results land. Stop polling when status is complete or failed. Results are kept for one hour after the job finishes.

NameRequiredDescriptionDefault
idYesJob id from readfetch_crawl (`job_id` in the start response). Required for MCP tools/call; poll until status is complete or failed (results kept ~1 hour).

Output Schema

NameRequiredDescription
pagesNo
totalNo
job_idNo
statusNo
completedNo

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already flag readOnlyHint and openWorldHint, but the description adds genuinely useful facts: no payment or wallet required, it is unauthenticated, pages grow incrementally as results land, and results are retained only one hour after completion. The retention window and the growing-result behavior are exactly the kind of operational 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.

Conciseness3/5

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

The main sentence is front-loaded and well ordered (purpose, auth, input, return, termination, retention), but 'FREE — no payment or wallet' appears twice in near-identical form, wasting space on a repeated claim.

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 simple polling tool with an output schema, annotations, and full schema coverage, the description covers everything an agent needs: when to call it, what to pass, how to interpret status, when to stop, and how long results persist.

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 100% and there is a single required parameter. The description's 'Pass `id` from the crawl response' merely repeats what the schema already says, adding no format or edge-case detail beyond it, so the baseline of 3 applies.

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?

The description states a specific verb and resource — poll a crawl job started with readfetch_crawl — and names the companion tool so an agent can tell it apart from readfetch_crawl (which starts jobs) and the other siblings. It also enumerates what comes back (job_id, status, counts, pages).

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 the selection context (only for jobs already started with readfetch_crawl), tells the agent to pass the id from that response, and specifies the termination condition: stop when status is complete or failed. It does not discuss failure recovery or what to do on repeated failed polls, so it stops short of a 5.

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

readfetch_diffA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Stateless change detection on readable page text (same HTTP-first extraction as readfetch_text): fetch the URL, compare to a hash or prior body you store client-side, return changed/unchanged plus optional line diff. First call with no prior fields returns a baseline hash (see hint). previous_hash alone detects change without a line diff; add previous_content when you need added/removed/diff. A no-change answer is still billable when text was delivered. Prefer readfetch_text when you need the full article once; readfetch_probe (free) for a short preview and content_sha256 before spending on text.

NameRequiredDescriptionDefault
urlYesPublic http(s) page to re-fetch and compare; must match the extraction used when you saved the hash (same `format`).
formatNoExtraction flavour for this fetch and for the hash (default text). Must match how you built `previous_content` if you send it.text
timeout_sNoTotal budget for the whole call in seconds, both fetches included. 60 s is the ceiling on this route.
previous_hashNo`sha256:…` or bare hex from readfetch_diff, readfetch_probe `content_sha256`, or a prior text read. Omit on the first poll to establish a baseline hash in the response.
previous_contentNoFull prior extracted text (what you stored from readfetch_text/readfetch_diff). Required for `added`/`removed`/`diff` output; hash-only compares do not emit a line diff.

Output Schema

NameRequiredDescription
urlNo
diffNo
hashNo
hintNo
addedNo
billedNo
statusNo
changedNo
removedNo
status_codeNo

TDQS

A4.6/5.0
Behavior4/5

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

Annotations only say readOnlyHint and openWorldHint, so the description carries the cost model and does it well: it discloses that calls are paid, that a no-op still bills when text was delivered, that unsigned calls stop at 402, and that state is client-side so nothing is stored server-side. The only gap is that it doesn't say how long a baseline hash stays valid or what errors look like, but with an output schema present that omission is minor.

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?

Dense but each sentence carries load; the billing and client requirement, the statelessness model, the parameter interaction, and the sibling routing are all necessary. Deducting one point because it opens with the payment/signing prerequisite rather than the tool's core purpose, so the key verb+resource is not front-loaded.

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 an output schema present, the description needn't explain return shapes, and it doesn't. What remains — prerequisites, cost behavior, baseline flow, parameter combinations, and alternatives — is fully covered, and all five parameters are documented in the schema, so an agent has everything needed to call this correctly on the first try.

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 100%, so the baseline is 3. The description goes beyond the per-field text by explaining the interaction between parameters: previous_hash alone yields a change boolean without a diff, while adding previous_content is required to get added/removed/diff, and format must match how prior content was built. That cross-parameter semantics is genuine added value.

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: "Stateless change detection on readable page text", and pins down the mechanism (fetch URL, compare to hash or prior content, return changed/unchanged plus optional diff). It explicitly distinguishes itself from readfetch_fetch, readfetch_text, and readfetch_probe, so an agent can route without opening a 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?

Gives explicit when-to-use and when-not-to-use guidance: "Prefer readfetch_text when you need the full article once; readfetch_probe (free) for a short preview and content_sha256 before spending on text." It also prescribes the first-call workflow (omit previous_hash to establish a baseline) and the hash-only vs hash+content choice.

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

readfetch_feedbackA

FREE — report integration, docs or site issues for a prior call. Bind with request_id from X-Request-Id. Paid delivery disputes use /v1/claims, not this tool.

NameRequiredDescriptionDefault
messageYesWhat went wrong and what you expected (max 500 chars).
categoryYesintegration = MCP/402/client; docs = wrong API copy; site = readfetch.com pages; other = everything else. Not for billing — use /v1/claims.
request_idYesX-Request-Id from the call you are reporting.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations only declare readOnlyHint=false and openWorldHint=false; the description adds the non-obvious cost signal (FREE) and the binding requirement to a prior request_id, which affects whether the call can succeed at all. It does not say what happens after submission (confirmation, ticket ID, side effects), so it stops short of full behavioral disclosure.

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 short clauses with no filler; the cost hook and purpose are front-loaded, followed by the binding requirement and then the exclusion. Every sentence earns its place.

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 3-required-param write tool with full schema coverage and no output schema, the description supplies the prerequisite, the free-cost signal, and the boundary against claims. The only gap is post-submission behavior, which is minor given the annotations and complete schema.

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 100%, including the category enum values and the 500-char limit, so the schema already carries parameter meaning. The description only reinforces that request_id comes from the X-Request-Id header and repeats the billing exclusion, adding little beyond the schema baseline.

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: report integration/docs/site issues for a prior call. It also names the thing it is not (paid delivery disputes go to /v1/claims), so an agent can route correctly without opening any schema, and it is unambiguous against the read-only data-retrieval siblings.

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?

Gives the precondition for use (requires a request_id from a prior call's X-Request-Id) and an explicit exclusion with a named alternative ('Paid delivery disputes use /v1/claims, not this tool'). This is exactly the when/when-not/alternative pattern.

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

readfetch_fetchA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Send an HTTP request (GET, POST, PUT, PATCH, DELETE, HEAD) through egress and return status_code, response headers, and body as text or base64 (binary: true). max_bytes caps the stored body; follow_redirects (default true) and timeout_s (95 s ceiling) apply to the full redirect chain. Use json_body for JSON POST/PUT payloads; use body for raw bytes or strings. Prefer readfetch_text for readable HTML articles; readfetch_pdf to extract PDF text (not raw bytes alone). POST/PUT/DELETE can change remote state despite readOnlyHint.

NameRequiredDescriptionDefault
urlYesRequest URL (http or https).
bodyNoRaw request body string for POST/PUT/PATCH (mutually exclusive with json_body).
binaryNoWhen true, return body as base64 instead of UTF-8 text.
methodNoHTTP method (GET default).GET
headersNoOptional request headers, e.g. Authorization or Accept.
json_bodyNoJSON object serialized as the request body (Content-Type application/json).
max_bytesNoStop reading and truncate once the response body exceeds this size (bytes).
timeout_sNoTotal budget for the whole call in seconds, redirect hops included.
follow_redirectsNoFollow 3xx redirects (default true).

Output Schema

NameRequiredDescription
urlNo
sizeNo
textNo
billedNo
statusNo
status_codeNo
content_typeNo

TDQS

A4.2/5.0
Behavior5/5

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

Annotations only supply readOnlyHint=true and openWorldHint=true, and the description adds substantial behavior the agent could not infer: a paid route requiring a funded Base USDC wallet, the 402 stop condition, the required signing client/proxy, redirect-chain timeout semantics, and max_bytes truncation. It also explicitly warns that POST/PUT/DELETE can mutate remote state despite readOnlyHint, which corrects a potentially misleading annotation rather than contradicting it. This is exactly the extra context the behavioral dimension is meant to reward.

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?

Dense and essentially waste-free: every sentence carries either a precondition, a parameter hint, or a sibling routing rule, appropriate for a 9-parameter tool. The weakness is ordering — the core 'send an HTTP request' statement arrives after two sentences of wallet/proxy prerequisites, so the front-loaded element is setup friction rather than the tool's action.

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 general-purpose egress fetch tool with 9 parameters, a full schema, and an output schema, the description covers the critical unknowns: payment/auth prerequisites, the 402 failure mode, mutation risk on non-GET methods, and sibling routing. Return values are briefly summarized even though the output schema carries them. Minor gaps remain around rate limits, header restrictions, and egress/geo behavior, but nothing an agent needs to invoke the 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 100%, so the baseline is 3; the description still earns above baseline by giving selection guidance between the two overlapping body parameters ('use json_body for JSON POST/PUT payloads; use body for raw bytes or strings'). It also frames timeout_s and follow_redirects as applying to the full redirect chain and binary:true as a base64 switch, reinforcing the practical effect of each parameter. It adds meaning but does not fully document headers or the 2083-char URL limit, which the schema already covers.

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 names a specific verb and resource: send an HTTP request across all six methods through egress and return status_code, response headers, and body. It also distinguishes itself from two siblings (readfetch_text for readable HTML articles, readfetch_pdf for PDF text), so an agent can route correctly. The main statement of purpose is buried behind two sentences of payment/setup preamble, which slightly blunts the front-loading.

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 explicit routing advice: prefer readfetch_text for readable HTML articles and readfetch_pdf for PDF extraction rather than raw bytes. It also tells the agent that direct calls without a signing client will stop at 402, which is actionable context for when a call will fail. It stops short of naming when a completely different sibling (e.g. readfetch_scrape or readfetch_crawl) is preferable over a raw fetch.

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

readfetch_mapA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Discover a site's crawlable surface without crawling it: parse robots.txt allow/disallow rules, collect URLs from sitemap.xml and sitemap indexes, find RSS, Atom and JSON feeds, and count internal and external links on the homepage. Use the returned URLs to plan readfetch_scrape, readfetch_batch, or readfetch_crawl — not readfetch_map again on each URL. Prefer readfetch_probe on one URL before paying for bodies.

NameRequiredDescriptionDefault
urlYesPublic http(s) URL of the site to map.
limitNoMaximum number of URLs to return (1-1000).
max_bytesNoAbort if any single document exceeds this many bytes.
timeout_sNoTotal budget for the whole call in seconds; every sitemap fetch and the browser fallback share it. 95 s is the edge ceiling (Cloudflare closes at 100 s).

Output Schema

NameRequiredDescription
urlNo
hostNo
urlsNo
feedsNo
linksNo
billedNo
robotsNo
statusNo
sitemapsNo
url_countNo
status_codeNo
total_foundNo

TDQS

A4.4/5.0
Behavior4/5

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

Goes well beyond the readOnlyHint/openWorldHint annotations by disclosing the monetization model: a funded Base USDC wallet is required on paid routes, a signing client or @readfetch/mcp-x402-proxy is needed, and unsigned direct calls fail at 402. It also notes the 95 s edge ceiling and that the browser fallback shares the timeout budget. It stops short of describing failure modes for unreachable sites or how robots/documents errors surface, so not a 5.

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 purpose sentence is dense but front-loaded with the core capability, and the workflow/alternative instructions follow logically. The opening payment/wallet preamble consumes the highest-attention position before the tool's function is stated, which costs a point.

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 read-only, open-world, four-parameter tool with full schema coverage and a declared output schema, the description supplies everything an agent still needs: payment/auth prerequisites, the 402 failure condition, the timeout ceiling, what is returned, and which sibling to call next. No material gap remains.

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 100%, so all four parameters (url, limit, max_bytes, timeout_s) are already documented with defaults and bounds. The description adds no parameter-level meaning of its own and does not explain how limit interacts with the collected sitemap/feed URL pool, so baseline 3 applies.

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 precise verb and resource: "Discover a site's crawlable surface without crawling it", then enumerates the exact artifacts produced (robots.txt rules, sitemap URLs, RSS/Atom/JSON feeds, link counts). The negation "without crawling it" and the instruction not to re-run readfetch_map on each returned URL cleanly separate it from readfetch_crawl.

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?

Explicit downstream routing: use returned URLs to plan readfetch_scrape, readfetch_batch, or readfetch_crawl. Also gives a pre-condition alternative ("Prefer readfetch_probe on one URL before paying for bodies") and an anti-pattern (do not call readfetch_map per URL), so both when-to-use and when-not-to-use are covered.

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

readfetch_pdfA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Extract text from a PDF (%PDF- magic, not Content-Type). Send exactly one of url (public http(s) link — egress GET, ≤ 20 MB) or content_base64 (bytes you already have — the whole request body is capped at 1 MiB, base64 expansion included; optional filename labels the upload). Returns pages (per-page text), one concatenated markdown body, title, and metadata; $0.005 per document, not per page. max_pages limits extraction (default 50, max 200); documents over 200 pages or above your cap return 413 and are not billed. Scanned/image-only PDFs may return empty text with billed: false and a hint. Prefer readfetch_text or readfetch_scrape for HTML articles; readfetch_fetch for raw PDF bytes without extraction; readfetch_batch for many HTML URLs, not PDFs. Read-only server-side; paid x402 like other routes.

NameRequiredDescriptionDefault
urlNoPublic PDF URL; fetched through egress (≤ 20 MB). Mutually exclusive with content_base64.
filenameNoOptional label when using content_base64 (default upload.pdf); ignored for url-only requests.
max_pagesNoExtract at most this many pages. Default 50; raise up to 200 when the document is longer. Over cap → 413, unbilled.
content_base64NoBase64-encoded PDF bytes. The request body is capped at 1 MiB total — base64 expansion comes out of that, it does not add to it (~0.75 MB of PDF). Mutually exclusive with url; pair with filename when the label matters.

Output Schema

NameRequiredDescription
hintNo
pagesNo
titleNo
billedNo
sourceNo
statusNo
markdownNo
metadataNo
page_countNo
content_sha256No

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=true, and the description confirms 'Read-only server-side'. Beyond that it adds genuinely useful context beyond annotations: the 402-without-signing-client behavior, $0.005 per-document pricing, 413 unbilled over-cap behavior, and empty-text-with-hint for scanned PDFs. Missing detail on return shape and pagination limits it to a 3 rather than higher.

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?

Information-dense and front-loaded with the payment prerequisite and the pair-selection rule, then the billing and limit caveats. Well organized, but the single dense paragraph packs unrelated concerns (auth, limits, billing, sibling routing) together without clear separation, slightly hurting scannability.

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?

Complete for a paid extraction endpoint: it covers input alternatives with size limits, output fields (pages, markdown, title, metadata), billing semantics, edge cases (scanned PDFs, over-cap 413), and sibling routing. An agent has everything needed to call it correctly and interpret the response.

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 100%, so all four parameters are documented in the schema itself, making the baseline 3. The description mostly restates the schema's size caps (20 MB egress, 1 MiB body with base64 expansion) and max_pages defaults, adding little new meaning beyond what structured fields already say.

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 ('Extract text from a PDF') and adds a concrete acceptance rule ('%PDF- magic, not Content-Type') that distinguishes it from generic fetch/scrape. The sibling comparison in the final sentences makes it unambiguous which tool handles PDF extraction vs HTML.

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?

Explicit routing guidance: 'Prefer readfetch_text or readfetch_scrape for HTML articles; readfetch_fetch for raw PDF bytes without extraction; readfetch_batch for many HTML URLs, not PDFs.' It also states the input-selection rule ('Send exactly one of url or content_base64') and the payment prerequisite for calls.

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

readfetch_probeA
Read-only

FREE — no payment or wallet: Free preflight on a URL before any paid readfetch_* call: HTTP status, content type, byte size, title, language, and whether a bot wall is waiting (challenge). When the response is HTML and not a challenge page, the JSON includes preview: up to 400 characters of the text readfetch_text would return (same extractor). Use readfetch_probe instead of readfetch_text when choosing a route or estimating size; if challenge: true, use readfetch_scrape (then readfetch_residential if still blocked), not readfetch_text. Plain HTTP only — no browser render.

NameRequiredDescriptionDefault
urlYesPublic http(s) URL to inspect.
timeout_sNoTotal budget for the whole call in seconds (default 10, max 60). Shared across redirects; does not apply to paid readfetch_text timeout_s on a follow-up call.
accept_languageNoAccept-Language header, e.g. 'de-DE,de;q=0.9'. Defaults to en-US.

Output Schema

NameRequiredDescription
urlNo
bytesNo
titleNo
billedNo
statusNo
previewNo
languageNo
challengeNo
redirectedNo
status_codeNo
content_typeNo
requested_urlNo
content_sha256No

TDQS

A4.4/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint; the description adds real substance beyond them — free/no wallet, plain HTTP only with no browser render, a 400-character preview produced by the same extractor as readfetch_text, and a timeout budget shared across redirects. The main omitted behavior is redirect handling details and any rate limiting, which keeps it from a 5.

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?

Front-loaded with the cost model and the core purpose, with the escalation path at the end. Dense and information-rich, though the bold markup and stacked parentheticals make it read more like a sales blurb than a spec — a slightly leaner phrasing would earn a 5.

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?

An output schema exists, yet the description still names the key response fields and the preview semantics, which is what an agent needs to decide whether to follow up with a paid call. Combined with the routing rules and transport limitation, nothing material is missing for a 3-parameter read-only probe.

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 100%, so all three parameters (url, timeout_s, accept_language) are already documented, including the note that timeout_s does not carry over to a follow-up paid call. The description adds no parameter-level meaning beyond the schema, so the baseline 3 applies.

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 ("Free preflight on a URL") and enumerates exactly what it returns: HTTP status, content type, byte size, title, language, bot-wall flag. It is clearly distinguishable from the paid readfetch_* siblings it names.

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?

Explicit routing guidance: use this instead of readfetch_text when choosing a route or estimating size, and on `challenge: true` escalate to readfetch_scrape then readfetch_residential rather than readfetch_text. Both the when and the when-not are spelled out.

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

readfetch_residentialA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Identical request and response to /v1/scrape, but the render leaves through a residential address instead of the datacentre. For targets that block by IP reputation (DataDome, PerimeterX, Cloudflare, AWS WAF). One attempt, no retries: residential bandwidth is the cost, and four times the scrape price is what it takes to cover it honestly. Prefer readfetch_scrape when datacentre egress works; use readfetch_residential only after readfetch_scrape fails or readfetch_probe reports a persistent challenge.

NameRequiredDescriptionDefault
urlYesPublic http(s) URL to load in Chromium.
authNoOptional cookie, bearer, or basic auth for the page load.
modeNoWhole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll).render
formatNoPrimary body field returned: markdown (default), plain text, or raw HTML.markdown
optionsNoDeprecated — use `advanced` instead (same ScrapeOptions shape). Scheduled for removal in a future API semver bump.
advancedNoBrowser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc.

Output Schema

NameRequiredDescription
urlNo
titleNo
billedNo
statusNo
markdownNo
status_codeNo

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the readOnlyHint/openWorldHint annotations: paid routes need a funded Base USDC wallet, unsigned calls fail with 402, there are no retries ('one attempt'), and the price is four times scrape. The target category (DataDome, PerimeterX, Cloudflare, AWS WAF) tells the agent what success looks like.

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?

Front-loads the payment prerequisite and routing guidance, and each sentence carries a distinct fact. The 'cover it honestly' aside is editorial padding that could be trimmed, and the prerequisite/proxy sentence is dense enough to slow scanning.

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?

Output schema and annotations handle return shape and safety, so the description only needs cost, auth, failure modes, and routing; it covers all four. An agent could call this correctly and predict the 402 and no-retry behavior from the text alone.

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 100%, so every parameter and nested option is already documented. The description adds only the framing that request and response are identical to /v1/scrape, which is useful but no substitute for parameter-level detail. Baseline 3 applies.

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 resource and a distinguishing mechanism: 'Identical request and response to /v1/scrape, but the render leaves through a residential address instead of the datacentre.' That single clause separates it from readfetch_scrape without requiring the agent to open 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?

Explicit when-to-use and when-not: 'Prefer readfetch_scrape when datacentre egress works; use readfetch_residential only after readfetch_scrape fails or readfetch_probe reports a persistent challenge.' It names both sibling alternatives and the exact condition that selects this one.

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

readfetch_scrapeA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Load a public URL in headless Chromium and return Markdown, plain text, or HTML (format, plus status_code, title, billed; optional links via advanced.include_links). mode sets latency and depth: fast (15 s, minimal render), render (30 s, default, full JS), full (60 s, scroll the page). Put scroll, wait_for, js_code, headers, cookies, and auth in advanced (options is deprecated, same shape). Prefer readfetch_text when JavaScript is not required; readfetch_fetch for raw HTTP/API bytes; readfetch_residential when the site blocks datacentre IPs; readfetch_screenshot for a PNG/JPEG. Bot-check or empty extractions may return billed: false with a hint.

NameRequiredDescriptionDefault
urlYesPublic http(s) URL to load in Chromium.
authNoOptional cookie, bearer, or basic auth for the page load.
modeNoWhole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll).render
formatNoPrimary body field returned: markdown (default), plain text, or raw HTML.markdown
optionsNoDeprecated — use `advanced` instead (same ScrapeOptions shape). Scheduled for removal in a future API semver bump.
advancedNoBrowser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc.

Output Schema

NameRequiredDescription
urlNo
titleNo
billedNo
statusNo
markdownNo
status_codeNo

TDQS

A4.6/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint, so the payment precondition, the 402 failure mode, and the billing semantics (a 'billed' field, with billed: false on bot checks or empty extractions) are genuine added value that the agent could not infer. It stops short of covering rate limits or retry/backoff behavior, so it is not a full 5.

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?

Dense but nearly every clause carries load, and the sibling routing is compressed into one comparison sentence. The one structural flaw is front-loading the wallet/402 prerequisite ahead of the actual purpose statement, so an agent skimming the first sentence learns the payment gate before what the tool does.

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 an output schema present, the description need not describe return fields, and it still names the key response fields (status_code, title, billed, links). For a 6-parameter, outbound-network tool it covers the payment gate, mode budgets, advanced controls, and alternative tools.

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 100%, so the 3 baseline is already met; the description goes further by grouping the advanced knobs ('scroll, wait_for, js_code, headers, cookies, and auth') and by flagging that `options` is deprecated but shares the `advanced` shape, which prevents a wrong-field call.

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 ('Load a public URL in headless Chromium') plus the exact output shapes ('Markdown, plain text, or HTML'), which is enough for an agent to distinguish it from readfetch_fetch or readfetch_text without opening a 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 routes away from this tool with named alternatives and conditions: readfetch_text when JavaScript is not required, readfetch_fetch for raw HTTP/API bytes, readfetch_residential when datacentre IPs are blocked, readfetch_screenshot for images. It also states the prerequisite (a funded Base USDC wallet plus a signing client) and the failure mode (402) of not meeting it.

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

readfetch_screenshotA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Screenshot a public URL in headless Chromium (page JavaScript runs; no ad blocker) and return PNG or JPEG in JSON — image_base64, mime, width, height, status_code, billed (not a hosted URL). Scope: viewport only (full_page: false), full scrollable page (default), or one element (selector). mode caps total render time: fast (15 s), render (30 s, default), full (60 s, always full-page regardless of full_page). Set width/height before navigation (default 1280×800, max 3840×2160). delay_ms (0–30000) waits after navigation, then captures — raise it or use mode=full for slow SPAs and lazy media. Prefer readfetch_text or readfetch_scrape for extractable text; readfetch_pdf for PDF files; readfetch_fetch for raw HTTP without rendering. Read-only on the origin (GET + render, no form POST). Bot-check or blank frames may still return pixels with billed: false and a hint; paid x402 like other routes.

NameRequiredDescriptionDefault
urlYesPublic http(s) URL to render in headless Chromium.
modeNoWhole-call budget: fast (15 s), render (30 s, default), or full (60 s; always captures the full scrollable page).render
widthNoViewport width in pixels before navigation (default 1280, max 3840).
formatNoImage encoding for `image_base64` (png default, or jpeg).png
heightNoViewport height in pixels before navigation (default 800, max 2160).
delay_msNoMilliseconds to wait after navigation before capture (0–30000); use for SPAs and lazy-loaded content.
selectorNoCSS selector — capture that element's box only. Omit for page/viewport per full_page.
full_pageNotrue (default): entire scrollable document; false: viewport only. Ignored when mode=full.

Output Schema

NameRequiredDescription
urlNo
hintNo
mimeNo
sizeNo
widthNo
billedNo
formatNo
heightNo
statusNo
status_codeNo
image_base64No
content_sha256No

TDQS

A4.7/5.0
Behavior5/5

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

Beyond readOnlyHint/openWorldHint it discloses payment mechanics (funded Base USDC wallet, 402 without a signing client), the fact that page JavaScript runs and there is no ad blocker, that the call is a GET-and-render with no form POST, and that bot-check or blank frames can still bill as false with a hint. This is exactly the kind of operational context annotations cannot express.

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

Conciseness3/5

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

The block is dense but mostly earns its words; however, it opens with billing/auth mechanics rather than the tool's purpose, burying 'Screenshot a public URL' in the middle. It also restates schema defaults (1280x800, 3840x2160) and output fields that the schema and output schema already declare.

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 an 8-parameter, open-world rendering tool, the definition covers cost/auth prerequisites, capture scope semantics, timeout behavior, and failure modes (bot checks, billed:false with hint). With an output schema present, it correctly does not need to explain return structure in depth.

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 100%, so the schema already documents every parameter and the baseline is 3. The description adds real guidance on top: mode is framed as a whole-call time budget, mode=full overrides full_page, and 'raise delay_ms or use mode=full for slow SPAs and lazy media' is operational advice not present in the schema.

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?

The description states a concrete verb and resource: 'Screenshot a public URL in headless Chromium ... return PNG or JPEG in JSON.' It also enumerates the return fields and explicitly names the sibling tools it is not (readfetch_text, readfetch_scrape, readfetch_pdf, readfetch_fetch), so an agent can distinguish it 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 Guidelines5/5

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

It gives explicit routing rules: 'Prefer readfetch_text or readfetch_scrape for extractable text; readfetch_pdf for PDF files; readfetch_fetch for raw HTTP without rendering.' It also states in-scope capture modes (viewport, full page, single selector) and when to raise delay_ms, so both selection and configuration decisions are covered.

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

readfetch_sectionA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Extract one heading or one CSS selector from a public page instead of the whole document. Returns matched Markdown or text, title, chars, content_sha256, and billed. If the heading is missing, returns HTTP 200 with empty text and available_headings so you can retry. mode: fast (plain HTTP) or render (default, Chromium when the page blocks HTTP). max_chars truncates output (default 8000, max 20000). Prefer readfetch_text for full articles; readfetch_scrape when content needs JavaScript.

NameRequiredDescriptionDefault
urlYesPublic page URL to extract from.
modeNofast = HTTP-first; render = one browser pass when plain HTTP fails (default).render
formatNoOutput flavour for the matched section (markdown default).markdown
headingNoHeading text to match (case-insensitive, whitespace-normalised). Required unless `selector` is set — send exactly one of `heading` or `selector`, not both.
selectorNoCSS selector; up to 20 matches concatenated. Required unless `heading` is set — use selector when the section has no stable heading text.
max_charsNoTruncate matched text after this many characters.

Output Schema

NameRequiredDescription
urlNo
hintNo
textNo
charsNo
titleNo
billedNo
statusNo
matchedNo
status_codeNo
used_browserNo
content_sha256No
available_headingsNo

TDQS

A4.6/5.0
Behavior4/5

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

The description goes well past the readOnlyHint/openWorldHint annotations: it discloses the paid-route prerequisite (funded Base USDC wallet plus a signing client or proxy), that unsigned calls stop at 402, and the notable edge-case behavior that a missing heading still returns HTTP 200 with empty text plus available_headings. The one thing left implicit is anything about rate limits or billing magnitude beyond the 'billed' field name.

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?

Almost every sentence carries load — the payment precondition, the one-of parameter rule, the empty-result recovery, and the sibling routing are all things an agent needs. The only structural weakness is that it opens with an auth wall rather than the tool's purpose, so the core verb arrives second.

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 read-only extraction tool with a full output schema, six well-documented parameters, and two enums, the description covers purpose, routing, preconditions, failure modes, and truncation. Nothing an agent needs in order to call it correctly or interpret an empty result 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 already 100%, so the baseline is 3, but the description adds decision-level meaning: mode is framed as when Chromium is engaged ('when the page blocks HTTP') and max_chars as a truncation ceiling with a usable default. Those are marginal restatements of schema text rather than new syntax, keeping it below a 5.

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?

The description names a specific verb and resource ('Extract one heading or one CSS selector from a public page instead of the whole document') and scopes it tightly against grabbing a whole document. It also names the sibling tools it is not, so an agent can separate it from readfetch_text and readfetch_scrape without opening a 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?

It gives explicit routing: 'Prefer readfetch_text for full articles; readfetch_scrape when content needs JavaScript,' plus a rule for choosing between the two required-one-of parameters ('use selector when the section has no stable heading text'). There is even a recovery path when the heading is absent — retry using the returned available_headings.

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

readfetch_textA
Read-only

Paid routes require a funded Base USDC wallet. Use readfetch-client / @readfetch/client or the MCP signing proxy (@readfetch/mcp-x402-proxy). Direct calls without a signing client will stop at 402. Fetch a public URL and return its main readable content as Markdown or plain text, plus title, author, published date and site name. Strips navigation, ads and boilerplate. No JavaScript rendering by default (cheaper than readfetch_scrape); one Chromium fallback when plain HTTP is blocked. Prefer readfetch_fetch when you need raw status, headers, or non-HTML bytes; readfetch_scrape when the article only appears after JavaScript runs.

NameRequiredDescriptionDefault
urlYesPublic http(s) URL to read.
formatNoOutput flavour: Markdown keeps headings, lists and tables.markdown
max_bytesNoAbort if the response body exceeds this many bytes.
timeout_sNoTotal budget for the whole call in seconds: DNS, redirects, the render fallback and any retry share it.
accept_languageNoAccept-Language header, e.g. 'de-DE,de;q=0.9'. Defaults to en-US.

Output Schema

NameRequiredDescription
urlNo
sizeNo
textNo
titleNo
billedNo
formatNo
statusNo
metadataNo
redirectedNo
status_codeNo
requested_urlNo

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare readOnlyHint and openWorldHint; the description adds the billing/auth precondition (funded USDC wallet, signing client or proxy, 402 on direct calls), the no-JS-by-default behavior with a single Chromium fallback, and the relative cost versus readfetch_scrape. Those are material facts an agent cannot derive from the structured fields.

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?

Dense and free of filler, but the first two sentences are payment preamble placed ahead of what the tool actually does, delaying the purpose statement. The routing guidance at the end is well placed; only the ordering keeps it from a 5.

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?

Output schema exists, so return values need no explanation, and all five parameters are fully described in the schema. The description fills the remaining gaps an agent needs: auth/payment requirement, cost relative to siblings, retry-capable fallback behavior, and when to choose each alternative tool.

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 100%, so url, format, max_bytes, timeout_s and accept_language are already documented with defaults and bounds. The description only echoes the format choice ('Markdown or plain text') and adds no syntax, units or interaction detail beyond the schema, so baseline 3 applies.

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 a public URL and return its main readable content as Markdown or plain text'), plus the returned metadata (title, author, published date, site name) and boilerplate stripping. It explicitly separates itself from readfetch_fetch (raw bytes/headers) and readfetch_scrape (JS-dependent articles), so an agent can pick the right sibling 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 Guidelines5/5

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

Gives explicit routing rules: prefer readfetch_fetch for raw status, headers or non-HTML bytes; use readfetch_scrape when the article only appears after JavaScript runs. It also flags the prerequisite that paid routes need a funded Base USDC wallet and a signing client, and that unsigned direct calls terminate at 402.

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. 15 tool updatesv0.1.14
    • Changedreadfetch_batch3 fields changed
      • removedInput schema / properties / fresh
        Removed value: -{
        -  "default": false,
        -  "description": "When true, bypass cached responses for each item (default false).",
        -  "type": "boolean"
        -}
      • changedInput schema / properties / pipeline / description
        Previous value: -"text = HTTP-first; render needs the browser tier."New value: +"text (default) = HTTP-first per URL, same as readfetch_text; use render when probe reported challenge:true or items need JavaScript — bills like scrape per undelivered page, not like plain text."
      • changedOutput schema / properties / results / items / properties / hint / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_crawl1 field changed
      • changedOutput schema / properties / price_usd / type
        Previous value: -"number"New value: +"string"
    • Changedreadfetch_crawl_status2 fields changed
      • changedInput schema / properties / id / description
        Previous value: -"Job id returned by POST /v1/crawl."New value: +"Job id from readfetch_crawl (`job_id` in the start response). Required for MCP tools/call; poll until status is complete or failed (results kept ~1 hour)."
      • changedInput schema / required
        Previous value: -[]New value: +[
        +  "id"
        +]
    • Changedreadfetch_diff5 fields changed
      • addedInput schema / properties / format / description
        Added value: +"Extraction flavour for this fetch and for the hash (default text). Must match how you built `previous_content` if you send it."
      • changedInput schema / properties / previous_content / description
        Previous value: -"Previous text, for an added/removed diff."New value: +"Full prior extracted text (what you stored from readfetch_text/readfetch_diff). Required for `added`/`removed`/`diff` output; hash-only compares do not emit a line diff."
      • changedInput schema / properties / previous_hash / description
        Previous value: -"sha256:... from a previous call."New value: +"`sha256:…` or bare hex from readfetch_diff, readfetch_probe `content_sha256`, or a prior text read. Omit on the first poll to establish a baseline hash in the response."
      • addedInput schema / properties / url / description
        Added value: +"Public http(s) page to re-fetch and compare; must match the extraction used when you saved the hash (same `format`)."
      • changedOutput schema / properties / hint / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_feedback2 fields changed
      • addedInput schema / properties / category / description
        Added value: +"integration = MCP/402/client; docs = wrong API copy; site = readfetch.com pages; other = everything else. Not for billing — use /v1/claims."
      • addedInput schema / properties / message / description
        Added value: +"What went wrong and what you expected (max 500 chars)."
    • Changedreadfetch_fetch1 field changed
      • addedOutput schema / properties / billed
        Added value: +{
        +  "type": "boolean"
        +}
    • Changedreadfetch_map2 fields changed
      • addedOutput schema / properties / billed
        Added value: +{
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / robots / properties / crawl_delay / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_pdf2 fields changed
      • changedInput schema / properties / content_base64 / description
        Previous value: -"Base64-encoded PDF bytes (≤ 20 MB). Mutually exclusive with url; pair with filename when the label matters."New value: +"Base64-encoded PDF bytes. The request body is capped at 1 MiB total — base64 expansion comes out of that, it does not add to it (~0.75 MB of PDF). Mutually exclusive with url; pair with filename when the label matters."
      • changedOutput schema / properties / hint / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_probe2 fields changed
      • changedInput schema / properties / timeout_s / description
        Previous value: -"Total budget for the whole call in seconds."New value: +"Total budget for the whole call in seconds (default 10, max 60). Shared across redirects; does not apply to paid readfetch_text timeout_s on a follow-up call."
      • changedOutput schema / properties / language / type
        Previous value: -"string"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_residential23 fields changed
      • addedInput schema / $defs / Auth / properties / cookies / description
        Added value: +"Cookie jar when `type` is cookie; ignored for bearer/basic."
      • addedInput schema / $defs / Auth / properties / password / description
        Added value: +"Basic-auth password when `type` is basic."
      • addedInput schema / $defs / Auth / properties / token / description
        Added value: +"Bearer token when `type` is bearer (Authorization: Bearer …)."
      • addedInput schema / $defs / Auth / properties / type / description
        Added value: +"Authentication mode: `cookie` (set `cookies`), `bearer` (set `token`), or `basic` (set `username` and `password`)."
      • addedInput schema / $defs / Auth / properties / username / description
        Added value: +"Basic-auth username when `type` is basic."
      • addedInput schema / $defs / Cookie / properties / domain / description
        Added value: +"Optional domain scope, e.g. `.example.com`."
      • addedInput schema / $defs / Cookie / properties / name / description
        Added value: +"Cookie name."
      • addedInput schema / $defs / Cookie / properties / path / description
        Added value: +"Path scope within the domain (default `/`)."
      • addedInput schema / $defs / Cookie / properties / url / description
        Added value: +"Optional full URL scope for the cookie; alternative to `domain`/`path`."
      • addedInput schema / $defs / Cookie / properties / value / description
        Added value: +"Cookie value."
      • addedInput schema / $defs / ScrapeOptions / properties / cookies / description
        Added value: +"Inject cookies without `auth`; same shape as auth cookies."
      • addedInput schema / $defs / ScrapeOptions / properties / delay_before_return_ms / description
        Added value: +"Pause after navigation before snapshot (0–60000, default 0); use for short post-load animations."
      • addedInput schema / $defs / ScrapeOptions / properties / headers / description
        Added value: +"Extra HTTP request headers for the navigation (merged with defaults)."
      • addedInput schema / $defs / ScrapeOptions / properties / include_html / description
        Added value: +"When true, include raw HTML in the response in addition to the primary `format` field."
      • addedInput schema / $defs / ScrapeOptions / properties / include_links / description
        Added value: +"When true, add a `links` array (href/text) alongside the main body."
      • addedInput schema / $defs / ScrapeOptions / properties / js_code / description
        Added value: +"JavaScript executed in the page before extraction; one string or an array run in order. Disables shared-browser cache for this call."
      • addedInput schema / $defs / ScrapeOptions / properties / max_scroll_steps / description
        Added value: +"Cap scroll iterations when `scan_full_page` is true (1–200); omit for engine default."
      • addedInput schema / $defs / ScrapeOptions / properties / scan_full_page / description
        Added value: +"Scroll the page to trigger lazy-loaded content; combine with `mode=full` or `max_scroll_steps`."
      • addedInput schema / $defs / ScrapeOptions / properties / user_agent / description
        Added value: +"Override the default browser User-Agent for this render only."
      • addedInput schema / $defs / ScrapeOptions / properties / wait_for / description
        Added value: +"CSS selector that must appear before capture; pairs with `wait_for_timeout_ms`."
      • addedInput schema / $defs / ScrapeOptions / properties / wait_for_timeout_ms / description
        Added value: +"Max milliseconds to wait for `wait_for` (0–120000, default 10000)."
      • removedInput schema / properties / fresh
        Removed value: -{
        -  "default": false,
        -  "description": "When true, bypass cached scrape results (default false).",
        -  "title": "Fresh",
        -  "type": "boolean"
        -}
      • removedOutput schema / properties / cache_status
        Removed value: -{
        -  "type": "string"
        -}
    • Changedreadfetch_scrape23 fields changed
      • addedInput schema / $defs / Auth / properties / cookies / description
        Added value: +"Cookie jar when `type` is cookie; ignored for bearer/basic."
      • addedInput schema / $defs / Auth / properties / password / description
        Added value: +"Basic-auth password when `type` is basic."
      • addedInput schema / $defs / Auth / properties / token / description
        Added value: +"Bearer token when `type` is bearer (Authorization: Bearer …)."
      • addedInput schema / $defs / Auth / properties / type / description
        Added value: +"Authentication mode: `cookie` (set `cookies`), `bearer` (set `token`), or `basic` (set `username` and `password`)."
      • addedInput schema / $defs / Auth / properties / username / description
        Added value: +"Basic-auth username when `type` is basic."
      • addedInput schema / $defs / Cookie / properties / domain / description
        Added value: +"Optional domain scope, e.g. `.example.com`."
      • addedInput schema / $defs / Cookie / properties / name / description
        Added value: +"Cookie name."
      • addedInput schema / $defs / Cookie / properties / path / description
        Added value: +"Path scope within the domain (default `/`)."
      • addedInput schema / $defs / Cookie / properties / url / description
        Added value: +"Optional full URL scope for the cookie; alternative to `domain`/`path`."
      • addedInput schema / $defs / Cookie / properties / value / description
        Added value: +"Cookie value."
      • addedInput schema / $defs / ScrapeOptions / properties / cookies / description
        Added value: +"Inject cookies without `auth`; same shape as auth cookies."
      • addedInput schema / $defs / ScrapeOptions / properties / delay_before_return_ms / description
        Added value: +"Pause after navigation before snapshot (0–60000, default 0); use for short post-load animations."
      • addedInput schema / $defs / ScrapeOptions / properties / headers / description
        Added value: +"Extra HTTP request headers for the navigation (merged with defaults)."
      • addedInput schema / $defs / ScrapeOptions / properties / include_html / description
        Added value: +"When true, include raw HTML in the response in addition to the primary `format` field."
      • addedInput schema / $defs / ScrapeOptions / properties / include_links / description
        Added value: +"When true, add a `links` array (href/text) alongside the main body."
      • addedInput schema / $defs / ScrapeOptions / properties / js_code / description
        Added value: +"JavaScript executed in the page before extraction; one string or an array run in order. Disables shared-browser cache for this call."
      • addedInput schema / $defs / ScrapeOptions / properties / max_scroll_steps / description
        Added value: +"Cap scroll iterations when `scan_full_page` is true (1–200); omit for engine default."
      • addedInput schema / $defs / ScrapeOptions / properties / scan_full_page / description
        Added value: +"Scroll the page to trigger lazy-loaded content; combine with `mode=full` or `max_scroll_steps`."
      • addedInput schema / $defs / ScrapeOptions / properties / user_agent / description
        Added value: +"Override the default browser User-Agent for this render only."
      • addedInput schema / $defs / ScrapeOptions / properties / wait_for / description
        Added value: +"CSS selector that must appear before capture; pairs with `wait_for_timeout_ms`."
      • addedInput schema / $defs / ScrapeOptions / properties / wait_for_timeout_ms / description
        Added value: +"Max milliseconds to wait for `wait_for` (0–120000, default 10000)."
      • removedInput schema / properties / fresh
        Removed value: -{
        -  "default": false,
        -  "description": "When true, bypass cached scrape results (default false).",
        -  "title": "Fresh",
        -  "type": "boolean"
        -}
      • removedOutput schema / properties / cache_status
        Removed value: -{
        -  "type": "string"
        -}
    • Changedreadfetch_screenshot1 field changed
      • changedOutput schema / properties / hint / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_search1 field changed
      • changedOutput schema / properties / hint / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_section3 fields changed
      • changedInput schema / properties / heading / description
        Previous value: -"Case-insensitive, whitespace-normalised."New value: +"Heading text to match (case-insensitive, whitespace-normalised). Required unless `selector` is set — send exactly one of `heading` or `selector`, not both."
      • changedInput schema / properties / selector / description
        Previous value: -"CSS selector; up to 20 matches concatenated."New value: +"CSS selector; up to 20 matches concatenated. Required unless `heading` is set — use selector when the section has no stable heading text."
      • changedOutput schema / properties / hint / type
        Previous value: -"null"New value: +[
        +  "string",
        +  "null"
        +]
    • Changedreadfetch_text3 fields changed
      • addedOutput schema / properties / billed
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / redirected
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / requested_url
        Added value: +{
        +  "format": "uri",
        +  "type": "string"
        +}
  2. 14 tool updatesv0.1.13
    • Changedreadfetch_batch4 fields changed
      • addedInput schema / properties / accept_language / description
        Added value: +"Accept-Language header for every item, e.g. 'de-DE,de;q=0.9'. Defaults to en-US when omitted."
      • addedInput schema / properties / format / description
        Added value: +"Per-item output flavour, same as /v1/text: markdown (default) or plain text."
      • addedInput schema / properties / fresh / description
        Added value: +"When true, bypass cached responses for each item (default false)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed_pages": {
        +      "type": "integer"
        +    },
        +    "credit": {
        +      "type": "string"
        +    },
        +    "delivered": {
        +      "type": "integer"
        +    },
        +    "failed": {
        +      "type": "integer"
        +    },
        +    "results": {
        +      "items": {
        +        "properties": {
        +          "billed": {
        +            "type": "boolean"
        +          },
        +          "content_sha256": {
        +            "type": "string"
        +          },
        +          "hint": {
        +            "type": "null"
        +          },
        +          "requested_url": {
        +            "format": "uri",
        +            "type": "string"
        +          },
        +          "status_code": {
        +            "type": "integer"
        +          },
        +          "text": {
        +            "type": "string"
        +          },
        +          "title": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "format": "uri",
        +            "type": "string"
        +          },
        +          "used_browser": {
        +            "type": "boolean"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_crawl6 fields changed
      • addedInput schema / properties / exclude / description
        Added value: +"Path prefixes to skip during the crawl."
      • changedInput schema / properties / include / description
        Previous value: -"Path prefixes; * suffix wildcard."New value: +"Path prefixes to allow; * suffix wildcard."
      • addedInput schema / properties / max_depth / description
        Added value: +"Link depth from the seed URL (default 2)."
      • addedInput schema / properties / max_pages / description
        Added value: +"Maximum pages to fetch in this job (quoted up front for payment)."
      • addedInput schema / properties / url / description
        Added value: +"Seed URL; crawl stays on the same registrable domain."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "hint": {
        +      "type": "string"
        +    },
        +    "job_id": {
        +      "type": "string"
        +    },
        +    "pages_quoted": {
        +      "type": "integer"
        +    },
        +    "price_usd": {
        +      "type": "number"
        +    },
        +    "status": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_crawl_status1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "completed": {
        +      "type": "integer"
        +    },
        +    "job_id": {
        +      "type": "string"
        +    },
        +    "pages": {
        +      "items": {},
        +      "type": "array"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "total": {
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_diff1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "added": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "changed": {
        +      "type": "boolean"
        +    },
        +    "diff": {
        +      "type": "string"
        +    },
        +    "hash": {
        +      "type": "string"
        +    },
        +    "hint": {
        +      "type": "null"
        +    },
        +    "removed": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_fetch9 fields changed
      • addedInput schema / properties / binary / description
        Added value: +"When true, return body as base64 instead of UTF-8 text."
      • addedInput schema / properties / body / description
        Added value: +"Raw request body string for POST/PUT/PATCH (mutually exclusive with json_body)."
      • addedInput schema / properties / follow_redirects / description
        Added value: +"Follow 3xx redirects (default true)."
      • addedInput schema / properties / headers / description
        Added value: +"Optional request headers, e.g. Authorization or Accept."
      • addedInput schema / properties / json_body / description
        Added value: +"JSON object serialized as the request body (Content-Type application/json)."
      • addedInput schema / properties / max_bytes / description
        Added value: +"Stop reading and truncate once the response body exceeds this size (bytes)."
      • addedInput schema / properties / method / description
        Added value: +"HTTP method (GET default)."
      • addedInput schema / properties / url / description
        Added value: +"Request URL (http or https)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "content_type": {
        +      "type": "string"
        +    },
        +    "size": {
        +      "type": "integer"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "text": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_map1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "feeds": {
        +      "items": {
        +        "format": "uri",
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "host": {
        +      "type": "string"
        +    },
        +    "links": {
        +      "properties": {
        +        "external": {
        +          "type": "integer"
        +        },
        +        "internal": {
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "robots": {
        +      "properties": {
        +        "allow": {
        +          "items": {},
        +          "type": "array"
        +        },
        +        "crawl_delay": {
        +          "type": "null"
        +        },
        +        "disallow": {
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "sitemaps": {
        +          "items": {
        +            "format": "uri",
        +            "type": "string"
        +          },
        +          "type": "array"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "sitemaps": {
        +      "items": {
        +        "format": "uri",
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "total_found": {
        +      "type": "integer"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    },
        +    "url_count": {
        +      "type": "integer"
        +    },
        +    "urls": {
        +      "items": {
        +        "format": "uri",
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_pdf5 fields changed
      • changedInput schema / properties / content_base64 / description
        Previous value: -"Inline PDF, up to 20 MB."New value: +"Base64-encoded PDF bytes (≤ 20 MB). Mutually exclusive with url; pair with filename when the label matters."
      • addedInput schema / properties / filename / description
        Added value: +"Optional label when using content_base64 (default upload.pdf); ignored for url-only requests."
      • addedInput schema / properties / max_pages / description
        Added value: +"Extract at most this many pages. Default 50; raise up to 200 when the document is longer. Over cap → 413, unbilled."
      • changedInput schema / properties / url / description
        Previous value: -"PDF URL, fetched through egress."New value: +"Public PDF URL; fetched through egress (≤ 20 MB). Mutually exclusive with content_base64."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "content_sha256": {
        +      "type": "string"
        +    },
        +    "hint": {
        +      "type": "null"
        +    },
        +    "markdown": {
        +      "type": "string"
        +    },
        +    "metadata": {
        +      "properties": {
        +        "author": {
        +          "type": "string"
        +        },
        +        "created": {
        +          "type": "string"
        +        },
        +        "producer": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "page_count": {
        +      "type": "integer"
        +    },
        +    "pages": {
        +      "items": {
        +        "properties": {
        +          "page": {
        +            "type": "integer"
        +          },
        +          "text": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "source": {
        +      "format": "uri",
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "title": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_probe1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "bytes": {
        +      "type": "integer"
        +    },
        +    "challenge": {
        +      "type": "boolean"
        +    },
        +    "content_sha256": {
        +      "type": "string"
        +    },
        +    "content_type": {
        +      "type": "string"
        +    },
        +    "language": {
        +      "type": "string"
        +    },
        +    "preview": {
        +      "type": "string"
        +    },
        +    "redirected": {
        +      "type": "boolean"
        +    },
        +    "requested_url": {
        +      "format": "uri",
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_residential7 fields changed
      • addedInput schema / properties / advanced / description
        Added value: +"Browser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc."
      • addedInput schema / properties / auth / description
        Added value: +"Optional cookie, bearer, or basic auth for the page load."
      • addedInput schema / properties / format / description
        Added value: +"Primary body field returned: markdown (default), plain text, or raw HTML."
      • addedInput schema / properties / fresh / description
        Added value: +"When true, bypass cached scrape results (default false)."
      • addedInput schema / properties / mode / description
        Added value: +"Whole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll)."
      • addedInput schema / properties / url / description
        Added value: +"Public http(s) URL to load in Chromium."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "cache_status": {
        +      "type": "string"
        +    },
        +    "markdown": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_scrape7 fields changed
      • addedInput schema / properties / advanced / description
        Added value: +"Browser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc."
      • addedInput schema / properties / auth / description
        Added value: +"Optional cookie, bearer, or basic auth for the page load."
      • addedInput schema / properties / format / description
        Added value: +"Primary body field returned: markdown (default), plain text, or raw HTML."
      • addedInput schema / properties / fresh / description
        Added value: +"When true, bypass cached scrape results (default false)."
      • addedInput schema / properties / mode / description
        Added value: +"Whole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll)."
      • addedInput schema / properties / url / description
        Added value: +"Public http(s) URL to load in Chromium."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "cache_status": {
        +      "type": "string"
        +    },
        +    "markdown": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_screenshot9 fields changed
      • addedInput schema / properties / delay_ms / description
        Added value: +"Milliseconds to wait after navigation before capture (0–30000); use for SPAs and lazy-loaded content."
      • addedInput schema / properties / format / description
        Added value: +"Image encoding for `image_base64` (png default, or jpeg)."
      • addedInput schema / properties / full_page / description
        Added value: +"true (default): entire scrollable document; false: viewport only. Ignored when mode=full."
      • addedInput schema / properties / height / description
        Added value: +"Viewport height in pixels before navigation (default 800, max 2160)."
      • addedInput schema / properties / mode / description
        Added value: +"Whole-call budget: fast (15 s), render (30 s, default), or full (60 s; always captures the full scrollable page)."
      • changedInput schema / properties / selector / description
        Previous value: -"Capture one element."New value: +"CSS selector — capture that element's box only. Omit for page/viewport per full_page."
      • addedInput schema / properties / url / description
        Added value: +"Public http(s) URL to render in headless Chromium."
      • addedInput schema / properties / width / description
        Added value: +"Viewport width in pixels before navigation (default 1280, max 3840)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "content_sha256": {
        +      "type": "string"
        +    },
        +    "format": {
        +      "type": "string"
        +    },
        +    "height": {
        +      "type": "integer"
        +    },
        +    "hint": {
        +      "type": "null"
        +    },
        +    "image_base64": {
        +      "type": "string"
        +    },
        +    "mime": {
        +      "type": "string"
        +    },
        +    "size": {
        +      "type": "integer"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    },
        +    "width": {
        +      "type": "integer"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_search5 fields changed
      • changedInput schema / properties / lang / description
        Previous value: -"e.g. en, de-DE"New value: +"Optional language/locale hint, e.g. en or de-DE."
      • addedInput schema / properties / limit / description
        Added value: +"Maximum number of results to return (default 5)."
      • addedInput schema / properties / query / description
        Added value: +"Search query string."
      • changedInput schema / properties / tbs / description
        Previous value: -"Time range."New value: +"Optional recency filter: h=hour, d=day, w=week, m=month, y=year."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "hint": {
        +      "type": "null"
        +    },
        +    "query": {
        +      "type": "string"
        +    },
        +    "results": {
        +      "items": {
        +        "properties": {
        +          "position": {
        +            "type": "integer"
        +          },
        +          "snippet": {
        +            "type": "string"
        +          },
        +          "title": {
        +            "type": "string"
        +          },
        +          "url": {
        +            "format": "uri",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "status": {
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_section5 fields changed
      • addedInput schema / properties / format / description
        Added value: +"Output flavour for the matched section (markdown default)."
      • addedInput schema / properties / max_chars / description
        Added value: +"Truncate matched text after this many characters."
      • addedInput schema / properties / mode / description
        Added value: +"fast = HTTP-first; render = one browser pass when plain HTTP fails (default)."
      • addedInput schema / properties / url / description
        Added value: +"Public page URL to extract from."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "available_headings": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "billed": {
        +      "type": "boolean"
        +    },
        +    "chars": {
        +      "type": "integer"
        +    },
        +    "content_sha256": {
        +      "type": "string"
        +    },
        +    "hint": {
        +      "type": "null"
        +    },
        +    "matched": {
        +      "properties": {
        +        "kind": {
        +          "type": "string"
        +        },
        +        "label": {
        +          "type": "string"
        +        },
        +        "level": {
        +          "type": "integer"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "text": {
        +      "type": "string"
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    },
        +    "used_browser": {
        +      "type": "boolean"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedreadfetch_text1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "properties": {
        +    "format": {
        +      "type": "string"
        +    },
        +    "metadata": {
        +      "properties": {
        +        "author": {
        +          "type": "string"
        +        },
        +        "date": {
        +          "type": "string"
        +        },
        +        "sitename": {
        +          "type": "string"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "size": {
        +      "type": "integer"
        +    },
        +    "status": {
        +      "type": "string"
        +    },
        +    "status_code": {
        +      "type": "integer"
        +    },
        +    "text": {
        +      "type": "string"
        +    },
        +    "title": {
        +      "type": "string"
        +    },
        +    "url": {
        +      "format": "uri",
        +      "type": "string"
        +    }
        +  },
        +  "type": "object"
        +}
  3. 1 tool updatev0.1.12
    • Changedreadfetch_diff3 fields changed
      • addedInput schema / properties / timeout_s / default
        Added value: +30
      • addedInput schema / properties / timeout_s / description
        Added value: +"Total budget for the whole call in seconds, both fetches included. 60 s is the ceiling on this route."
      • changedInput schema / properties / timeout_s / maximum
        Previous value: -120New value: +60
  4. 15 tool updatesv0.1.0
    • First observedreadfetch_batch
    • First observedreadfetch_crawl
    • First observedreadfetch_crawl_status
    • First observedreadfetch_diff
    • First observedreadfetch_feedback
    • First observedreadfetch_fetch
    • First observedreadfetch_map
    • First observedreadfetch_pdf
    • First observedreadfetch_probe
    • First observedreadfetch_residential
    • First observedreadfetch_scrape
    • First observedreadfetch_screenshot
    • First observedreadfetch_search
    • First observedreadfetch_section
    • First observedreadfetch_text

TDQS

A4.2/5.0

Scored across 15 tools

Disambiguation4/5

The core reads — text, scrape, residential, section, diff, fetch, pdf — all retrieve content from a URL and could tempt misselection, but each description states an explicit 'prefer X when...' boundary (plain HTTP, JS render, residential egress, selector subset, change detection, raw bytes, PDF parsing). Probe, map, crawl, and batch are cleanly separated as free preflight, URL discovery, async site walk, and fixed-list reads respectively. Only the text/scrape/residential/section cluster still requires careful reading to choose correctly.

Naming Consistency4/5

Every tool uses the same lowercase snake_case `readfetch_` prefix with a single terse token (or a clear noun_qualifier like readfetch_crawl_status), so the set is highly predictable and greppable. Minor deviation: some tokens are verbs (scrape, fetch, crawl, map, probe, search) while others are nouns (text, pdf, batch, section, diff, screenshot, residential), so the suffix doesn't reliably indicate an action.

Tool Count4/5

At 15 tools this sits at the top of the comfortable range but each entry maps to a genuinely distinct capability of a web-reading API (extraction, rendering, raw HTTP, PDF, screenshot, discovery, batch, crawl, search, feedback). A few variants (residential, section, diff) could plausibly be parameters of scrape/text rather than standalone tools, which would trim the surface. It is well within scope, not bloated.

Completeness4/5

The domain — paid web reading via x402 — is covered end to end: free preflight (probe), discovery (map, search), single-URL reads across formats (text, scrape, fetch, pdf, section, screenshot, diff), bulk (batch, crawl, crawl_status), and a feedback channel. Gaps are minor: no crawl cancel/abort or job listing, and no wallet/balance or pricing-discovery tool, even though every paid call warns about a required funded USDC wallet and 402 behaviour.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    F
    maintenance
    A Model Context Protocol server that provides browser automation capabilities using Playwright. This server enables LLMs to interact with web pages, take screenshots, and execute JavaScript in a real browser environment.
    32
    13,447 npm
    5,674
    MIT
  • A
    license
    A
    quality
    F
    maintenance
    Enables MCP clients to access all endpoints of an x402 gateway by paying real-time microtransactions (USDC on Base) per API call, with automatic tool discovery and spend guardrails.
    23
    52 npm
    MIT