@readfetch/mcp-x402-proxy
Use this stdio MCP server as a readfetch bridge that lists tools and automatically signs x402 USDC payments on Base for paid web-data calls.
Free preflight: inspect a URL for status, content type, title, preview, language, and bot-wall challenge; poll crawl jobs; submit integration feedback.
Paid article reading: fetch a public URL and return readable Markdown/text plus title, author, date, and site metadata.
Site mapping: discover crawlable URLs via robots.txt, sitemaps, feeds, and homepage link counts.
Headless scraping: render JavaScript pages in Chromium, with residential egress for IP-blocked targets.
Raw HTTP fetch: send GET/POST/PUT/PATCH/DELETE/HEAD requests with headers/body and return status, headers, text, or base64 bytes.
Batch reading: extract the same article text from up to 50 URLs in one paid call.
PDF extraction: extract per-page text and metadata from PDFs by URL or base64 upload.
Section extraction: pull one heading or CSS selector match instead of the full page.
Change detection: compare page text against a stored hash or prior content and return diffs.
Screenshots: capture full-page, viewport, or element PNG/JPEG images from rendered pages.
Web search: return titles, URLs, and snippets; follow up with readfetch URL tools.
Async crawling: start a bounded crawl and poll its status for per-page Markdown results.
Payment handling: automatically signs 402 retries, loads the private key only on first paid call, and caps each x402 authorization.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@readfetch/mcp-x402-proxyfetch the text content of https://example.com/blog/article"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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/listdoes not load your key; the firsttools/calldoes.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 cinpm 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 USDCFrom 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 packageWrong: 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
readfetch_probewith{ "url": "…" }(free; may includepreview~400 chars when HTML, not a bot wall)readfetch_textwith the sameurlIf probe reports
challenge: true, usereadfetch_scrape(thenreadfetch_scrape_residentialif 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/fetchin your appDirect 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 toolsreadfetch_batchARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| urls | Yes | URLs to read, deduped before quoting. | |
| format | No | Per-item output flavour, same as /v1/text: markdown (default) or plain text. | markdown |
| pipeline | No | 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. | text |
| timeout_s | No | Total budget for the whole batch in seconds; every item shares it and no item restarts it. | |
| accept_language | No | Accept-Language header for every item, e.g. 'de-DE,de;q=0.9'. Defaults to en-US when omitted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| credit | No | |
| failed | No | |
| status | No | |
| results | No | |
| delivered | No | |
| billed_pages | No |
TDQS
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.
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.
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.
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.
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.
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_crawlARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Seed URL; crawl stays on the same registrable domain. | |
| exclude | No | Path prefixes to skip during the crawl. | |
| include | No | Path prefixes to allow; * suffix wildcard. | |
| max_depth | No | Link depth from the seed URL (default 2). | |
| max_pages | No | Maximum pages to fetch in this job (quoted up front for payment). |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| job_id | No | |
| status | No | |
| price_usd | No | |
| pages_quoted | No |
TDQS
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.
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.
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.
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.
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.
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_statusARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | 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). |
Output Schema
| Name | Required | Description |
|---|---|---|
| pages | No | |
| total | No | |
| job_id | No | |
| status | No | |
| completed | No |
TDQS
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.
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.
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.
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.
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.
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_diffARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) page to re-fetch and compare; must match the extraction used when you saved the hash (same `format`). | |
| format | No | Extraction flavour for this fetch and for the hash (default text). Must match how you built `previous_content` if you send it. | text |
| timeout_s | No | Total budget for the whole call in seconds, both fetches included. 60 s is the ceiling on this route. | |
| previous_hash | No | `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_content | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| diff | No | |
| hash | No | |
| hint | No | |
| added | No | |
| billed | No | |
| status | No | |
| changed | No | |
| removed | No | |
| status_code | No |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| message | Yes | What went wrong and what you expected (max 500 chars). | |
| category | Yes | integration = MCP/402/client; docs = wrong API copy; site = readfetch.com pages; other = everything else. Not for billing — use /v1/claims. | |
| request_id | Yes | X-Request-Id from the call you are reporting. |
TDQS
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.
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.
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.
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.
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.
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_fetchARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Request URL (http or https). | |
| body | No | Raw request body string for POST/PUT/PATCH (mutually exclusive with json_body). | |
| binary | No | When true, return body as base64 instead of UTF-8 text. | |
| method | No | HTTP method (GET default). | GET |
| headers | No | Optional request headers, e.g. Authorization or Accept. | |
| json_body | No | JSON object serialized as the request body (Content-Type application/json). | |
| max_bytes | No | Stop reading and truncate once the response body exceeds this size (bytes). | |
| timeout_s | No | Total budget for the whole call in seconds, redirect hops included. | |
| follow_redirects | No | Follow 3xx redirects (default true). |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| size | No | |
| text | No | |
| billed | No | |
| status | No | |
| status_code | No | |
| content_type | No |
TDQS
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.
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.
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.
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.
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.
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_mapARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL of the site to map. | |
| limit | No | Maximum number of URLs to return (1-1000). | |
| max_bytes | No | Abort if any single document exceeds this many bytes. | |
| timeout_s | No | Total 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
| Name | Required | Description |
|---|---|---|
| url | No | |
| host | No | |
| urls | No | |
| feeds | No | |
| links | No | |
| billed | No | |
| robots | No | |
| status | No | |
| sitemaps | No | |
| url_count | No | |
| status_code | No | |
| total_found | No |
TDQS
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.
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.
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.
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.
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.
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_pdfARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Public PDF URL; fetched through egress (≤ 20 MB). Mutually exclusive with content_base64. | |
| filename | No | Optional label when using content_base64 (default upload.pdf); ignored for url-only requests. | |
| max_pages | No | Extract at most this many pages. Default 50; raise up to 200 when the document is longer. Over cap → 413, unbilled. | |
| content_base64 | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| pages | No | |
| title | No | |
| billed | No | |
| source | No | |
| status | No | |
| markdown | No | |
| metadata | No | |
| page_count | No | |
| content_sha256 | No |
TDQS
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.
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.
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.
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.
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.
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_probeARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL to inspect. | |
| timeout_s | No | 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. | |
| accept_language | No | Accept-Language header, e.g. 'de-DE,de;q=0.9'. Defaults to en-US. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| bytes | No | |
| title | No | |
| billed | No | |
| status | No | |
| preview | No | |
| language | No | |
| challenge | No | |
| redirected | No | |
| status_code | No | |
| content_type | No | |
| requested_url | No | |
| content_sha256 | No |
TDQS
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.
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.
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.
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.
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.
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_residentialARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL to load in Chromium. | |
| auth | No | Optional cookie, bearer, or basic auth for the page load. | |
| mode | No | Whole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll). | render |
| format | No | Primary body field returned: markdown (default), plain text, or raw HTML. | markdown |
| options | No | Deprecated — use `advanced` instead (same ScrapeOptions shape). Scheduled for removal in a future API semver bump. | |
| advanced | No | Browser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| title | No | |
| billed | No | |
| status | No | |
| markdown | No | |
| status_code | No |
TDQS
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.
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.
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.
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.
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.
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_scrapeARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL to load in Chromium. | |
| auth | No | Optional cookie, bearer, or basic auth for the page load. | |
| mode | No | Whole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll). | render |
| format | No | Primary body field returned: markdown (default), plain text, or raw HTML. | markdown |
| options | No | Deprecated — use `advanced` instead (same ScrapeOptions shape). Scheduled for removal in a future API semver bump. | |
| advanced | No | Browser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| title | No | |
| billed | No | |
| status | No | |
| markdown | No | |
| status_code | No |
TDQS
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.
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.
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.
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.
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.
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_screenshotARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL to render in headless Chromium. | |
| mode | No | Whole-call budget: fast (15 s), render (30 s, default), or full (60 s; always captures the full scrollable page). | render |
| width | No | Viewport width in pixels before navigation (default 1280, max 3840). | |
| format | No | Image encoding for `image_base64` (png default, or jpeg). | png |
| height | No | Viewport height in pixels before navigation (default 800, max 2160). | |
| delay_ms | No | Milliseconds to wait after navigation before capture (0–30000); use for SPAs and lazy-loaded content. | |
| selector | No | CSS selector — capture that element's box only. Omit for page/viewport per full_page. | |
| full_page | No | true (default): entire scrollable document; false: viewport only. Ignored when mode=full. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| hint | No | |
| mime | No | |
| size | No | |
| width | No | |
| billed | No | |
| format | No | |
| height | No | |
| status | No | |
| status_code | No | |
| image_base64 | No | |
| content_sha256 | No |
TDQS
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.
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.
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.
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.
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.
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_searchARead-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. Run a web search without a separate search API subscription. Returns titles, URLs, and snippets only — not full page text; follow with readfetch_text, readfetch_probe, or readfetch_scrape on a chosen result URL. limit is 1–20 (default 5). Optional lang biases locale (e.g. en, de-DE). Optional tbs filters recency: h= past hour, d= day, w= week, m= month, y= year. Use readfetch_map/readfetch_crawl when you already know the site; readfetch_* URL tools when you have the link.
| Name | Required | Description | Default |
|---|---|---|---|
| tbs | No | Optional recency filter: h=hour, d=day, w=week, m=month, y=year. | |
| lang | No | Optional language/locale hint, e.g. en or de-DE. | |
| limit | No | Maximum number of results to return (default 5). | |
| query | Yes | Search query string. |
Output Schema
| Name | Required | Description |
|---|---|---|
| hint | No | |
| query | No | |
| billed | No | |
| status | No | |
| results | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the supplied readOnlyHint/openWorldHint annotations: it discloses the paid-route prerequisite (funded Base USDC wallet), the required signing client/proxy, and the concrete failure mode (calls stop at 402 without one). It also caps expectations on the payload (snippets only, not page text), which shapes downstream planning.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The content is dense and each clause is relevant, but front-loading is inverted: the first two sentences are payment/proxy logistics rather than the tool's action, and the final paragraph compresses parameter details, alternatives, and multi-tool routing into one long run-on block. It could be restructured to lead with what the tool does and push payment prerequisites later.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the return shape need not be spelled out, and the description still usefully summarizes it. Auth/payment requirements, failure mode, and successor-tool routing are all covered; only cost/latency or rate-limit expectations are left unstated for a paid, open-world call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents query, limit, lang and tbs. The description restates the same facts (limit 1–20 default 5, tbs h/d/w/m/y, lang locale examples) without adding format rules, interaction notes, or edge cases beyond what the structured fields carry.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Run a web search") and immediately bounds the output scope ("titles, URLs, and snippets only — not full page text"), which is exactly what separates it from the readfetch_scrape/text siblings. An agent can identify this as the discovery step 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: follow with readfetch_text/probe/scrape on a chosen URL, use readfetch_map/crawl when the site is already known, and use readfetch_* URL tools when a link exists. It names both the successor tools and the conditions that select them, so no inference is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
readfetch_sectionARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public page URL to extract from. | |
| mode | No | fast = HTTP-first; render = one browser pass when plain HTTP fails (default). | render |
| format | No | Output flavour for the matched section (markdown default). | markdown |
| heading | No | Heading text to match (case-insensitive, whitespace-normalised). Required unless `selector` is set — send exactly one of `heading` or `selector`, not both. | |
| selector | No | CSS selector; up to 20 matches concatenated. Required unless `heading` is set — use selector when the section has no stable heading text. | |
| max_chars | No | Truncate matched text after this many characters. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| hint | No | |
| text | No | |
| chars | No | |
| title | No | |
| billed | No | |
| status | No | |
| matched | No | |
| status_code | No | |
| used_browser | No | |
| content_sha256 | No | |
| available_headings | No |
TDQS
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.
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.
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.
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.
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.
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_textARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Public http(s) URL to read. | |
| format | No | Output flavour: Markdown keeps headings, lists and tables. | markdown |
| max_bytes | No | Abort if the response body exceeds this many bytes. | |
| timeout_s | No | Total budget for the whole call in seconds: DNS, redirects, the render fallback and any retry share it. | |
| accept_language | No | Accept-Language header, e.g. 'de-DE,de;q=0.9'. Defaults to en-US. |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | |
| size | No | |
| text | No | |
| title | No | |
| billed | No | |
| format | No | |
| status | No | |
| metadata | No | |
| redirected | No | |
| status_code | No | |
| requested_url | No |
TDQS
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.
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.
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.
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.
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.
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.
15 tool updates
v0.1.14- Changed
readfetch_batch3 fields changed- removed
Input schema / properties / freshRemoved value: -{ - "default": false, - "description": "When true, bypass cached responses for each item (default false).", - "type": "boolean" -} - changed
Input schema / properties / pipeline / descriptionPrevious 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." - changed
Output schema / properties / results / items / properties / hint / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_crawl1 field changed- changed
Output schema / properties / price_usd / typePrevious value: -"number"New value: +"string"
- Changed
readfetch_crawl_status2 fields changed- changed
Input schema / properties / id / descriptionPrevious 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)." - changed
Input schema / requiredPrevious value: -[]New value: +[ + "id" +]
- Changed
readfetch_diff5 fields changed- added
Input schema / properties / format / descriptionAdded value: +"Extraction flavour for this fetch and for the hash (default text). Must match how you built `previous_content` if you send it." - changed
Input schema / properties / previous_content / descriptionPrevious 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." - changed
Input schema / properties / previous_hash / descriptionPrevious 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." - added
Input schema / properties / url / descriptionAdded value: +"Public http(s) page to re-fetch and compare; must match the extraction used when you saved the hash (same `format`)." - changed
Output schema / properties / hint / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_feedback2 fields changed- added
Input schema / properties / category / descriptionAdded value: +"integration = MCP/402/client; docs = wrong API copy; site = readfetch.com pages; other = everything else. Not for billing — use /v1/claims." - added
Input schema / properties / message / descriptionAdded value: +"What went wrong and what you expected (max 500 chars)."
- Changed
readfetch_fetch1 field changed- added
Output schema / properties / billedAdded value: +{ + "type": "boolean" +}
- Changed
readfetch_map2 fields changed- added
Output schema / properties / billedAdded value: +{ + "type": "boolean" +} - changed
Output schema / properties / robots / properties / crawl_delay / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_pdf2 fields changed- changed
Input schema / properties / content_base64 / descriptionPrevious 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." - changed
Output schema / properties / hint / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_probe2 fields changed- changed
Input schema / properties / timeout_s / descriptionPrevious 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." - changed
Output schema / properties / language / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
readfetch_residential23 fields changed- added
Input schema / $defs / Auth / properties / cookies / descriptionAdded value: +"Cookie jar when `type` is cookie; ignored for bearer/basic." - added
Input schema / $defs / Auth / properties / password / descriptionAdded value: +"Basic-auth password when `type` is basic." - added
Input schema / $defs / Auth / properties / token / descriptionAdded value: +"Bearer token when `type` is bearer (Authorization: Bearer …)." - added
Input schema / $defs / Auth / properties / type / descriptionAdded value: +"Authentication mode: `cookie` (set `cookies`), `bearer` (set `token`), or `basic` (set `username` and `password`)." - added
Input schema / $defs / Auth / properties / username / descriptionAdded value: +"Basic-auth username when `type` is basic." - added
Input schema / $defs / Cookie / properties / domain / descriptionAdded value: +"Optional domain scope, e.g. `.example.com`." - added
Input schema / $defs / Cookie / properties / name / descriptionAdded value: +"Cookie name." - added
Input schema / $defs / Cookie / properties / path / descriptionAdded value: +"Path scope within the domain (default `/`)." - added
Input schema / $defs / Cookie / properties / url / descriptionAdded value: +"Optional full URL scope for the cookie; alternative to `domain`/`path`." - added
Input schema / $defs / Cookie / properties / value / descriptionAdded value: +"Cookie value." - added
Input schema / $defs / ScrapeOptions / properties / cookies / descriptionAdded value: +"Inject cookies without `auth`; same shape as auth cookies." - added
Input schema / $defs / ScrapeOptions / properties / delay_before_return_ms / descriptionAdded value: +"Pause after navigation before snapshot (0–60000, default 0); use for short post-load animations." - added
Input schema / $defs / ScrapeOptions / properties / headers / descriptionAdded value: +"Extra HTTP request headers for the navigation (merged with defaults)." - added
Input schema / $defs / ScrapeOptions / properties / include_html / descriptionAdded value: +"When true, include raw HTML in the response in addition to the primary `format` field." - added
Input schema / $defs / ScrapeOptions / properties / include_links / descriptionAdded value: +"When true, add a `links` array (href/text) alongside the main body." - added
Input schema / $defs / ScrapeOptions / properties / js_code / descriptionAdded value: +"JavaScript executed in the page before extraction; one string or an array run in order. Disables shared-browser cache for this call." - added
Input schema / $defs / ScrapeOptions / properties / max_scroll_steps / descriptionAdded value: +"Cap scroll iterations when `scan_full_page` is true (1–200); omit for engine default." - added
Input schema / $defs / ScrapeOptions / properties / scan_full_page / descriptionAdded value: +"Scroll the page to trigger lazy-loaded content; combine with `mode=full` or `max_scroll_steps`." - added
Input schema / $defs / ScrapeOptions / properties / user_agent / descriptionAdded value: +"Override the default browser User-Agent for this render only." - added
Input schema / $defs / ScrapeOptions / properties / wait_for / descriptionAdded value: +"CSS selector that must appear before capture; pairs with `wait_for_timeout_ms`." - added
Input schema / $defs / ScrapeOptions / properties / wait_for_timeout_ms / descriptionAdded value: +"Max milliseconds to wait for `wait_for` (0–120000, default 10000)." - removed
Input schema / properties / freshRemoved value: -{ - "default": false, - "description": "When true, bypass cached scrape results (default false).", - "title": "Fresh", - "type": "boolean" -} - removed
Output schema / properties / cache_statusRemoved value: -{ - "type": "string" -}
- Changed
readfetch_scrape23 fields changed- added
Input schema / $defs / Auth / properties / cookies / descriptionAdded value: +"Cookie jar when `type` is cookie; ignored for bearer/basic." - added
Input schema / $defs / Auth / properties / password / descriptionAdded value: +"Basic-auth password when `type` is basic." - added
Input schema / $defs / Auth / properties / token / descriptionAdded value: +"Bearer token when `type` is bearer (Authorization: Bearer …)." - added
Input schema / $defs / Auth / properties / type / descriptionAdded value: +"Authentication mode: `cookie` (set `cookies`), `bearer` (set `token`), or `basic` (set `username` and `password`)." - added
Input schema / $defs / Auth / properties / username / descriptionAdded value: +"Basic-auth username when `type` is basic." - added
Input schema / $defs / Cookie / properties / domain / descriptionAdded value: +"Optional domain scope, e.g. `.example.com`." - added
Input schema / $defs / Cookie / properties / name / descriptionAdded value: +"Cookie name." - added
Input schema / $defs / Cookie / properties / path / descriptionAdded value: +"Path scope within the domain (default `/`)." - added
Input schema / $defs / Cookie / properties / url / descriptionAdded value: +"Optional full URL scope for the cookie; alternative to `domain`/`path`." - added
Input schema / $defs / Cookie / properties / value / descriptionAdded value: +"Cookie value." - added
Input schema / $defs / ScrapeOptions / properties / cookies / descriptionAdded value: +"Inject cookies without `auth`; same shape as auth cookies." - added
Input schema / $defs / ScrapeOptions / properties / delay_before_return_ms / descriptionAdded value: +"Pause after navigation before snapshot (0–60000, default 0); use for short post-load animations." - added
Input schema / $defs / ScrapeOptions / properties / headers / descriptionAdded value: +"Extra HTTP request headers for the navigation (merged with defaults)." - added
Input schema / $defs / ScrapeOptions / properties / include_html / descriptionAdded value: +"When true, include raw HTML in the response in addition to the primary `format` field." - added
Input schema / $defs / ScrapeOptions / properties / include_links / descriptionAdded value: +"When true, add a `links` array (href/text) alongside the main body." - added
Input schema / $defs / ScrapeOptions / properties / js_code / descriptionAdded value: +"JavaScript executed in the page before extraction; one string or an array run in order. Disables shared-browser cache for this call." - added
Input schema / $defs / ScrapeOptions / properties / max_scroll_steps / descriptionAdded value: +"Cap scroll iterations when `scan_full_page` is true (1–200); omit for engine default." - added
Input schema / $defs / ScrapeOptions / properties / scan_full_page / descriptionAdded value: +"Scroll the page to trigger lazy-loaded content; combine with `mode=full` or `max_scroll_steps`." - added
Input schema / $defs / ScrapeOptions / properties / user_agent / descriptionAdded value: +"Override the default browser User-Agent for this render only." - added
Input schema / $defs / ScrapeOptions / properties / wait_for / descriptionAdded value: +"CSS selector that must appear before capture; pairs with `wait_for_timeout_ms`." - added
Input schema / $defs / ScrapeOptions / properties / wait_for_timeout_ms / descriptionAdded value: +"Max milliseconds to wait for `wait_for` (0–120000, default 10000)." - removed
Input schema / properties / freshRemoved value: -{ - "default": false, - "description": "When true, bypass cached scrape results (default false).", - "title": "Fresh", - "type": "boolean" -} - removed
Output schema / properties / cache_statusRemoved value: -{ - "type": "string" -}
- Changed
readfetch_screenshot1 field changed- changed
Output schema / properties / hint / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_search1 field changed- changed
Output schema / properties / hint / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_section3 fields changed- changed
Input schema / properties / heading / descriptionPrevious 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." - changed
Input schema / properties / selector / descriptionPrevious 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." - changed
Output schema / properties / hint / typePrevious value: -"null"New value: +[ + "string", + "null" +]
- Changed
readfetch_text3 fields changed- added
Output schema / properties / billedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / redirectedAdded value: +{ + "type": "boolean" +} - added
Output schema / properties / requested_urlAdded value: +{ + "format": "uri", + "type": "string" +}
14 tool updates
v0.1.13- Changed
readfetch_batch4 fields changed- added
Input schema / properties / accept_language / descriptionAdded value: +"Accept-Language header for every item, e.g. 'de-DE,de;q=0.9'. Defaults to en-US when omitted." - added
Input schema / properties / format / descriptionAdded value: +"Per-item output flavour, same as /v1/text: markdown (default) or plain text." - added
Input schema / properties / fresh / descriptionAdded value: +"When true, bypass cached responses for each item (default false)." - changed
Output 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" +}
- Changed
readfetch_crawl6 fields changed- added
Input schema / properties / exclude / descriptionAdded value: +"Path prefixes to skip during the crawl." - changed
Input schema / properties / include / descriptionPrevious value: -"Path prefixes; * suffix wildcard."New value: +"Path prefixes to allow; * suffix wildcard." - added
Input schema / properties / max_depth / descriptionAdded value: +"Link depth from the seed URL (default 2)." - added
Input schema / properties / max_pages / descriptionAdded value: +"Maximum pages to fetch in this job (quoted up front for payment)." - added
Input schema / properties / url / descriptionAdded value: +"Seed URL; crawl stays on the same registrable domain." - changed
Output 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" +}
- Changed
readfetch_crawl_status1 field changed- changed
Output 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" +}
- Changed
readfetch_diff1 field changed- changed
Output 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" +}
- Changed
readfetch_fetch9 fields changed- added
Input schema / properties / binary / descriptionAdded value: +"When true, return body as base64 instead of UTF-8 text." - added
Input schema / properties / body / descriptionAdded value: +"Raw request body string for POST/PUT/PATCH (mutually exclusive with json_body)." - added
Input schema / properties / follow_redirects / descriptionAdded value: +"Follow 3xx redirects (default true)." - added
Input schema / properties / headers / descriptionAdded value: +"Optional request headers, e.g. Authorization or Accept." - added
Input schema / properties / json_body / descriptionAdded value: +"JSON object serialized as the request body (Content-Type application/json)." - added
Input schema / properties / max_bytes / descriptionAdded value: +"Stop reading and truncate once the response body exceeds this size (bytes)." - added
Input schema / properties / method / descriptionAdded value: +"HTTP method (GET default)." - added
Input schema / properties / url / descriptionAdded value: +"Request URL (http or https)." - changed
Output 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" +}
- Changed
readfetch_map1 field changed- changed
Output 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" +}
- Changed
readfetch_pdf5 fields changed- changed
Input schema / properties / content_base64 / descriptionPrevious 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." - added
Input schema / properties / filename / descriptionAdded value: +"Optional label when using content_base64 (default upload.pdf); ignored for url-only requests." - added
Input schema / properties / max_pages / descriptionAdded value: +"Extract at most this many pages. Default 50; raise up to 200 when the document is longer. Over cap → 413, unbilled." - changed
Input schema / properties / url / descriptionPrevious value: -"PDF URL, fetched through egress."New value: +"Public PDF URL; fetched through egress (≤ 20 MB). Mutually exclusive with content_base64." - changed
Output 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" +}
- Changed
readfetch_probe1 field changed- changed
Output 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" +}
- Changed
readfetch_residential7 fields changed- added
Input schema / properties / advanced / descriptionAdded value: +"Browser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc." - added
Input schema / properties / auth / descriptionAdded value: +"Optional cookie, bearer, or basic auth for the page load." - added
Input schema / properties / format / descriptionAdded value: +"Primary body field returned: markdown (default), plain text, or raw HTML." - added
Input schema / properties / fresh / descriptionAdded value: +"When true, bypass cached scrape results (default false)." - added
Input schema / properties / mode / descriptionAdded value: +"Whole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll)." - added
Input schema / properties / url / descriptionAdded value: +"Public http(s) URL to load in Chromium." - changed
Output 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" +}
- Changed
readfetch_scrape7 fields changed- added
Input schema / properties / advanced / descriptionAdded value: +"Browser interactions: scroll, wait_for selector, js_code, headers, cookies, locale, include_links, etc." - added
Input schema / properties / auth / descriptionAdded value: +"Optional cookie, bearer, or basic auth for the page load." - added
Input schema / properties / format / descriptionAdded value: +"Primary body field returned: markdown (default), plain text, or raw HTML." - added
Input schema / properties / fresh / descriptionAdded value: +"When true, bypass cached scrape results (default false)." - added
Input schema / properties / mode / descriptionAdded value: +"Whole-call budget and render depth: fast (15 s), render (30 s, default), or full (60 s with page scroll)." - added
Input schema / properties / url / descriptionAdded value: +"Public http(s) URL to load in Chromium." - changed
Output 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" +}
- Changed
readfetch_screenshot9 fields changed- added
Input schema / properties / delay_ms / descriptionAdded value: +"Milliseconds to wait after navigation before capture (0–30000); use for SPAs and lazy-loaded content." - added
Input schema / properties / format / descriptionAdded value: +"Image encoding for `image_base64` (png default, or jpeg)." - added
Input schema / properties / full_page / descriptionAdded value: +"true (default): entire scrollable document; false: viewport only. Ignored when mode=full." - added
Input schema / properties / height / descriptionAdded value: +"Viewport height in pixels before navigation (default 800, max 2160)." - added
Input schema / properties / mode / descriptionAdded value: +"Whole-call budget: fast (15 s), render (30 s, default), or full (60 s; always captures the full scrollable page)." - changed
Input schema / properties / selector / descriptionPrevious value: -"Capture one element."New value: +"CSS selector — capture that element's box only. Omit for page/viewport per full_page." - added
Input schema / properties / url / descriptionAdded value: +"Public http(s) URL to render in headless Chromium." - added
Input schema / properties / width / descriptionAdded value: +"Viewport width in pixels before navigation (default 1280, max 3840)." - changed
Output 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" +}
- Changed
readfetch_search5 fields changed- changed
Input schema / properties / lang / descriptionPrevious value: -"e.g. en, de-DE"New value: +"Optional language/locale hint, e.g. en or de-DE." - added
Input schema / properties / limit / descriptionAdded value: +"Maximum number of results to return (default 5)." - added
Input schema / properties / query / descriptionAdded value: +"Search query string." - changed
Input schema / properties / tbs / descriptionPrevious value: -"Time range."New value: +"Optional recency filter: h=hour, d=day, w=week, m=month, y=year." - changed
Output 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" +}
- Changed
readfetch_section5 fields changed- added
Input schema / properties / format / descriptionAdded value: +"Output flavour for the matched section (markdown default)." - added
Input schema / properties / max_chars / descriptionAdded value: +"Truncate matched text after this many characters." - added
Input schema / properties / mode / descriptionAdded value: +"fast = HTTP-first; render = one browser pass when plain HTTP fails (default)." - added
Input schema / properties / url / descriptionAdded value: +"Public page URL to extract from." - changed
Output 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" +}
- Changed
readfetch_text1 field changed- changed
Output 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" +}
1 tool update
v0.1.12- Changed
readfetch_diff3 fields changed- added
Input schema / properties / timeout_s / defaultAdded value: +30 - added
Input schema / properties / timeout_s / descriptionAdded value: +"Total budget for the whole call in seconds, both fetches included. 60 s is the ceiling on this route." - changed
Input schema / properties / timeout_s / maximumPrevious value: -120New value: +60
15 tool updates
v0.1.0- First observed
readfetch_batch - First observed
readfetch_crawl - First observed
readfetch_crawl_status - First observed
readfetch_diff - First observed
readfetch_feedback - First observed
readfetch_fetch - First observed
readfetch_map - First observed
readfetch_pdf - First observed
readfetch_probe - First observed
readfetch_residential - First observed
readfetch_scrape - First observed
readfetch_screenshot - First observed
readfetch_search - First observed
readfetch_section - First observed
readfetch_text
TDQS
Scored across 15 tools
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.
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.
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.
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
Related MCP Connectors
Pay-per-use tool marketplace for AI agents. Search, price-check, and call APIs via MCP.
Paid MCP tools behind one endpoint. Agents pay per call in USDC on Base via x402.
Pay-per-action access to APIs and MCP tools over Lightning L402 and Base USDC x402.
8 pay-per-call web intel tools over MCP. Free discovery, calls settle in USDC on Base (x402).
Related MCP Servers
- AlicenseBqualityFmaintenanceA 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.3213,447 npm5,674MIT
- AlicenseNot gradedqualityCmaintenanceA local MCP proxy that connects to remote MCP servers and automatically handles x402 payments, signing USDC on-chain when a tool returns HTTP 402.16 npm1MIT
- AlicenseAqualityFmaintenanceEnables 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.2352 npmMIT
- AlicenseNot gradedqualityFmaintenanceMCP server that lets AI agents scrape web pages as clean markdown for a micro-payment in USDC, using the x402 protocol on Base network. No API keys or signup required.MIT