mcpField
A
AgentRead

AgentRead

远程服务
agentread.omar-cv.workers.dev浏览器自动化04 天前更新

关于 AgentRead

AgentRead 是一个 Cloudflare Worker,可将公开网页转换为供大模型和 Agent 使用的结构化 Markdown 与元数据。它提供免费的 URL 检查,并按成功请求收费;通过 Base 上的 USDC 和 x402 支付,无需账户或 API 密钥。

主要功能

  1. 01免费检查 URL 可访问性
  2. 02网页 Markdown 提取
  3. 03结构化提取元数据和链接
  4. 04HTTP API 与远程 MCP 访问
  5. 05x402 按请求支付
  6. 06URL 与目标地址验证

适用场景

  1. 01提取前检查网页是否可访问
  2. 02为 Agent 提供网页的简洁 Markdown
  3. 03提取页面元数据、标题和链接
  4. 04通过 MCP 客户端调用网页提取

MCP 相关

通过无状态的 Streamable HTTP MCP 端点提供 `inspect_url`、`extract_url` 和 `extract_url_structured`。付费工具遵循 x402 MCP 约定:客户端提交支付元数据,随后收到结算凭据。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://agentread.omar-cv.workers.dev/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

AgentRead

为 AI Agent 清理网页内容,按请求付费。

AgentRead 是一个 Cloudflare Worker,可将公开网页转换为适合大模型和自主 Agent 使用的简洁、结构化 Markdown。它同时作为 HTTP API 和远程 MCP 服务提供。付费操作按成功请求收费,使用 x402 微支付(Base 上的 USDC)。无需账户、API 密钥或订阅。

操作HTTPMCP 工具价格(默认)
检查 URLPOST /v1/inspectinspect_url免费
提取简洁 MarkdownPOST /v1/extractextract_url$0.003
结构化提取POST /v1/extract/structuredextract_url_structured$0.005

价格通过配置设置,而非写死在代码中(参见配置)。

立即使用

服务: https://agentread.omar-cv.workers.dev · MCP: https://agentread.omar-cv.workers.dev/mcp · 已列入官方 MCP 注册表,名称为 io.github.omarhassanatef/agentread,也已列入 x402scan

试用免费检查:

curl -s -X POST https://agentread.omar-cv.workers.dev/v1/inspect \
  -H 'content-type: application/json' -d '{"url":"https://example.com/"}'

将其添加到 MCP 客户端(任何客户端都能使用 inspect_url;付费工具需要支持 x402 的客户端,例如 @x402/mcp):

claude mcp add --transport http agentread https://agentread.omar-cv.workers.dev/mcp
{ "mcpServers": { "agentread": { "url": "https://agentread.omar-cv.workers.dev/mcp" } } }

使用 x402 客户端通过代码按次付费:参见使用 x402 客户端付款和 MCP。面向 Agent 的文档:/llms.txt、/openapi.json、/.well-known/x402。

状态:MVP,已上线。

  • 生产环境(Base 主网,真实 USDC): https://agentread.omar-cv.workers.dev。付款通过 CDP facilitator 结算至 0xb866dD8C8401438Efb29b538ec4df11b6b407Ce6。
  • 测试网: 未托管测试网。npm run dev 会在本地运行,使用 Base Sepolia 和免费的 x402.org facilitator。

已验证的内容:

  • 自动化测试: 全部通过(237 项测试,在 Workers 运行时中执行)。
  • 目录检查: 两个付费端点均通过 CDP Bazaar 验证器(所有预检检查)和 AgentCash/x402scan 发现审核,并已登记在 x402scan。
  • 本地冒烟测试(9/9): 使用线上 x402.org facilitator,通过 wrangler dev 执行。来自未注资钱包的真实签名付款通过了签名和要求检查,并因 insufficient_balance 被拒绝,因此已验证线上支付链路,直至实际转账环节。
  • 生产环境部署: 通过 GitHub Actions 中的所有冒烟检查(gh workflow run CI)。线上 CDP facilitator 会验证 AgentRead 的身份并校验签名付款。由于开发网络会阻止 workers.dev IP 范围,因此 CI 从该网络执行。
  • 可在 Workers Free 计划上运行。 在 Cloudflare 边缘(Free 账户)的约 180 次基准测试请求中,已部署的 lite 引擎没有因 CPU 限制而被终止;readability 引擎在最多 84% 的请求中被终止。参见提取引擎。
  • 尚未在已部署的边缘环境中实际测试: 通过产品 Worker 进行的付费提取。同一提取代码已在边缘环境中进行基准测试,但尚未有注资付款成功完成。

尚未进行过注资付款(参见测试网付款演示)。依赖此服务前,请阅读限制。


为什么 Agent 愿意为此付费

原始 HTML 大多是噪声:导航、Cookie 横幅、广告、脚本、样式。Agent 自己抓取页面会浪费令牌,还必须维护 HTML 清理、SSRF 防护、编码检测、重定向处理和大小限制。AgentRead 一次性完成这些工作,并返回格式稳定、带版本号的 JSON。

x402 允许 Agent 使用自己的钱包,每次调用支付几分之一美分。无需注册,也不会存储凭据。提取失败不会收费。

这是一个有待验证的假设,而非已经证实的市场。服务会记录用于验证这一假设的数据(参见可观测性)。

架构

AI agent ──HTTP (x402 headers)──┐          ┌── POST /v1/inspect ──────────────┐
                                ▼          │                                  │
                      Cloudflare Worker (Hono)                                ▼
AI agent ──MCP Streamable HTTP──► /mcp ────┤   validate input + URL policy + DNS guard
          (x402 in _meta)                  │   (rejects bad input BEFORE any 402)
                                           │                                  │
                                           ├── POST /v1/extract[/structured]  │
                                           │      └─ @x402/hono paymentMiddleware ──► facilitator /verify
                                           │                                  │
                                           └── MCP paid tools                 ▼
                                                  └─ @x402/mcp wrapper    shared operations
                                                                          (inspectUrl / extractUrl /
                                                                           extractUrlStructured)
                                                                              │
                                                       bounded fetch (manual redirects, re-validated
                                                       each hop, timeout, byte cap) → linkedom →
                                                       boilerplate removal → Readability → Turndown
                                                                              │
                                     handler OK (2xx) → facilitator /settle → result + PAYMENT-RESPONSE
                                     handler failed   → settlement cancelled → error (not charged)
  • 单个 Worker,无数据库、队列或容器。
  • HTTP API 和 MCP 工具调用相同的操作函数,并使用相同的 zod 架构进行验证。
  • 支付使用官方 x402 v2 SDK:HTTP 使用 @x402/hono,MCP 使用 @x402/mcp,exact EVM 方案使用 @x402/evm。这里不会重新实现任何 x402 协议逻辑。

更多详情:docs/architecture.md · docs/payments.md · docs/security.md · docs/demo.md

API

机器可读文档:GET /(发现:操作、价格、限制)和 GET /openapi.json(OpenAPI 3.1,根据服务用于验证的 zod 架构生成)。

所有错误都采用相同格式:

{ "error": { "code": "blocked_destination", "message": "Internal, reserved, or loopback hostnames are not allowed.", "details": {} } }
GET /health
curl -s http://localhost:8787/health
# {"status":"ok","service":"agentread","version":"0.1.0","environment":"development",
#  "payments":{"enabled":true,"network":"eip155:84532","networkName":"Base Sepolia"}}
POST /v1/inspect:免费

在付费前检查 URL 是否可访问并可提取内容。最多下载 64 KB,且不会构建 DOM。上游问题(超时、404、非 HTML)会在 200 响应正文中以 reachable: false 或 limitation 的形式报告。只有无效或被拦截的 URL 会返回 4xx。

curl -s -X POST http://localhost:8787/v1/inspect \
  -H 'content-type: application/json' \
  -d '{"url":"https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402"}'
{
  "schemaVersion": "1.0", "operation": "inspect_url",
  "requestedUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402",
  "normalizedUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402",
  "hostname": "developer.mozilla.org", "reachable": true, "statusCode": 200,
  "finalUrl": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/402", "redirects": 1,
  "contentType": "text/html", "contentLength": 209180, "isHtml": true,
  "title": "402 Payment Required - HTTP | MDN", "mayRequireJavaScript": false,
  "extractionSupported": true, "limitation": null
}
POST /v1/extract:付费

请求正文(JSON,最大 8 KB;不接受未知字段):

字段类型默认值说明
urlstring必填绝对的公开 http(s) URL,使用默认端口,不含凭据,不得为 IP 字面量,≤ 2048 个字符
maxCharactersinteger20000100 – 100000;Markdown 会在段落边界处截断
includeLinksbooleantruefalse 会保留链接文本,但移除 URL 和图片

未付款时,响应为 HTTP 402。PAYMENT-REQUIRED 标头携带 base64 编码的 x402 PaymentRequired 对象;JSON 正文提供便于人类和 Agent 阅读的摘要:

curl -si -X POST http://localhost:8787/v1/extract \
  -H 'content-type: application/json' -d '{"url":"https://example.com/"}'
# HTTP/1.1 402 Payment Required
# payment-required: eyJ4NDAyVmVyc2lvbiI6Miwi...
# {"error":{"code":"payment_required","message":"This operation costs $0.003 (USDC on Base Sepolia). ...",
#   "details":{"operation":"extract_url","price":"$0.003","network":"eip155:84532","x402Version":2}}}

解码后的 PAYMENT-REQUIRED(accepts[0]):{"scheme":"exact","network":"eip155:84532","amount":"3000","asset":"0x036CbD53842c5426634e7929541eC2318f3dCF7e","payTo":"<your address>","maxTimeoutSeconds":120,...}。3000 相当于 0.003 美元的 6 位小数 USDC。

提供有效的 PAYMENT-SIGNATURE 标头后,响应为 200,并包含带有结算凭据的 PAYMENT-RESPONSE 标头:

https://example.com/ 的实际输出(2026 年 10 月直接运行操作代码时捕获):

{
  "schemaVersion": "1.0", "operation": "extract_url",
  "requestedUrl": "https://example.com/", "finalUrl": "https://example.com/",
  "title": "Example Domain", "description": null,
  "markdown": "This domain is for use in documentation examples without needing permission. This is not a service; avoid relying on it for testing and monitoring purposes.",
  "headings": [], "truncated": false,
  "extraction": { "method": "readability", "statusCode": 200, "contentType": "text/html", "charset": "utf-8",
    "redirects": 0, "bytesFetched": 577, "characters": 156, "totalCharacters": 156, "words": 25,
    "warnings": [], "durationMs": 854 }
}

extraction.method 的值为 readability、main-content-fallback、body-fallback 或 plain-text。

POST /v1/extract/structured:付费

请求正文与 /v1/extract 相同。分别返回元数据、Markdown、标题和链接:

{
  "schemaVersion": "1.0", "operation": "extract_url_structured",
  "requestedUrl": "...", "finalUrl": "...",
  "metadata": { "title": "...", "description": "...", "canonicalUrl": "...", "language": "en-GB",
                "siteName": "...", "byline": "...", "publishedTime": "2026-03-14T09:00:00Z" },
  "markdown": "...",
  "headings": [{ "level": 2, "text": "Zones of the intertidal" }],
  "headingsTruncated": false,
  "links": [{ "text": "official tide tables", "url": "https://example.org/tide-tables" }],
  "linksTruncated": false,
  "truncated": false,
  "extraction": { "...": "same as extract_url" }
}

缺失的元数据为 null;不会进行猜测。includeLinks 只影响 Markdown;始终会返回 links(最多 200 个,去重后仅保留绝对 http(s) URL)。

状态码(付费端点)
状态含义是否收费?
200提取成功且付款已结算是
400输入无效/目标地址被拦截(在任何 402 之前返回)否
402payment_required(未付款)、payment_invalid(已拒绝:details.reason 给出 Facilitator 的原因,例如 invalid_exact_evm_insufficient_balance),或 payment_settlement_failed否
413 / 415请求体过大/不是 JSON否
422unsupported_content_type、content_too_large、empty_content、javascript_required、too_many_redirects、host_not_found否
429请求频率受限否
502 / 504上游页面错误/无法访问、DNS 故障、Facilitator 错误/上游超时否
503此部署未配置付款否

使用 x402 客户端付款(HTTP)

官方 @x402/fetch 封装会处理 402 → 签名 → 重试流程。以下摘自 scripts/testnet-smoke.mjs:

import { wrapFetchWithPayment, x402Client, x402HTTPClient } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { toClientEvmSigner } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY); // TESTNET-ONLY wallet
const client = new x402Client().register("eip155:84532", new ExactEvmScheme(toClientEvmSigner(account)));
client.registerPolicy((_v, reqs) => reqs.filter((r) => BigInt(r.amount) <= 10_000n)); // never pay > $0.01

const payFetch = wrapFetchWithPayment(fetch, client);
const res = await payFetch("http://localhost:8787/v1/extract", { // `npm run dev` (Base Sepolia)
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ url: "https://example.com/" }),
});
const result = await res.json();
const receipt = new x402HTTPClient(client).getPaymentSettleResponse((n) => res.headers.get(n));
console.log(result.markdown, receipt.transaction);

MCP

端点:POST /mcp,采用 MCP Streamable HTTP,无状态(无会话,使用 JSON 响应)。按照传输规范,未启用服务端主动流的服务可以让 GET/DELETE 返回 405。

MCP 上的付款遵循 @x402/mcp 传输约定,而非 HTTP 标头:

  1. 未付款时调用付费工具,会返回 isError: true 的工具结果。其 structuredContent 是 x402 PaymentRequired 对象,也会以 JSON 编码形式放在 content[0].text 中。
  2. 客户端进行签名,并在 params._meta["x402/payment"] 中附上付款信息后重试。
  3. 服务端验证付款、运行工具,然后结算。收据位于 _meta["x402/payment-response"] 中。

无效输入和被拦截的 URL 会在付款挑战发出之前被拒绝。工具执行失败(isError)的结果不会结算。

兼容性说明:付费工具有意不声明 outputSchema。MCP SDK 客户端即使在错误结果中也会根据 outputSchema 验证 structuredContent。这会导致 x402 付款挑战被拒绝;我们已在官方 TypeScript 客户端中观察到此问题。工具的输出结构会在工具描述和 /openapi.json 中说明。inspect_url 确实声明了 outputSchema。

使用官方客户端连接并付款(scripts/mcp-client-example.mjs):

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { wrapMCPClientWithPayment } from "@x402/mcp";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { toClientEvmSigner } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const payments = new x402Client().register("eip155:84532", new ExactEvmScheme(toClientEvmSigner(account)));
const mcp = wrapMCPClientWithPayment(new Client({ name: "my-agent", version: "1.0.0" }), payments, {
  autoPayment: true,
  onPaymentRequested: async ({ paymentRequired }) => BigInt(paymentRequired.accepts[0].amount) <= 10_000n,
});
await mcp.connect(new StreamableHTTPClientTransport(new URL("http://localhost:8787/mcp")));

console.log((await mcp.listTools()).tools.map((t) => t.name));      // inspect_url, extract_url, extract_url_structured
const r = await mcp.callTool("extract_url", { url: "https://example.com/" });
console.log(r.paymentMade, r.paymentResponse?.transaction, r.content[0].text);

付费 MCP 工具还会在付款挑战中携带 x402 Bazaar 发现元数据(输入和输出架构),因此启用 Bazaar 的 Facilitator 可以将其编入目录。HTTP 路由不提供这些元数据:@x402/hono 2.28 使用 ajv 验证 Bazaar 路由元数据,而 ajv 会在运行时编译代码。Workers 禁止此操作,因此每个请求都会记录错误。HTTP 发现入口为 GET / 和 /openapi.json。

通用 MCP 客户端(IDE、桌面应用)可以连接到 /mcp 并使用 inspect_url。付费工具仅适用于实现了 x402 MCP 付款流程的客户端,例如 @x402/mcp。其他客户端会将付款挑战视为工具错误。不承诺与通用 Agent 框架兼容。

本地开发

要求:Node.js ≥ 20 和 npm。

npm install                    # see Troubleshooting if npm 10 fails with "edgesOut"
cp .dev.vars.example .dev.vars # set X402_PAY_TO to your testnet receiving address
npm run dev                    # wrangler dev on http://localhost:8787 (Base Sepolia, x402.org facilitator)
npm run smoke:local            # health, inspect, 402, SSRF rejection, MCP discovery (no payment)
脚本功能
npm run dev通过 wrangler dev 在本地运行 Worker(真实 workerd、真实出站网络)
npm run typechecktsc --noEmit(严格模式)
npm test通过 @cloudflare/vitest-plugin 在 workerd 中运行完整 Vitest 测试套件
npm run build通过 wrangler deploy --dry-run --outdir dist 生成生产构建包
npm run checktypecheck + test + build
npm run smoke:local针对 AGENTREAD_URL 运行免费冒烟测试,包括零成本实时 Facilitator 检查(必须拒绝来自空钱包的签名付款,原因是余额不足)
npm run smoke:testnet实时付费测试网测试(需要 EVM_PRIVATE_KEY)
npm run smoke:mcpMCP 发现 + 免费工具;如果设置了 EVM_PRIVATE_KEY,则调用付费工具
npm run cf-typegen编辑 wrangler.jsonc 后重新生成 worker-configuration.d.ts

配置

非敏感配置存放在 wrangler.jsonc(vars,按环境配置)。机密信息使用 wrangler secret put(已部署)或 .dev.vars(本地)设置。客户端脚本设置见 .env.example。

变量必填示例 / 默认值说明
ENVIRONMENT是development / testnet / production仅当环境为 production 时才接受主网网络;production 仅接受主网
X402_NETWORK是eip155:84532(Base Sepolia)/ eip155:8453(Base)CAIP-2
X402_PAY_TO是0x…公开收款地址。不接受零地址占位符
X402_FACILITATOR_URL是https://x402.org/facilitator(测试网)/ https://api.cdp.coinbase.com/platform/v2/x402主网不接受 x402.org
CDP_API_KEY_ID、CDP_API_KEY_SECRET机密信息,生产环境使用 CDP facilitator 时必填
PRICE_EXTRACT_USD是0.003美元十进制金额,最多 6 位小数,0 < 价格 ≤ 1
PRICE_EXTRACT_STRUCTURED_USD是0.005
DNS_CHECK否dohdoh = 对每一跳进行 DNS-over-HTTPS 预检查;off = 禁用
EXTRACTION_ENGINE否wrangler.jsonc 中为 lite(代码默认值为 readability)lite = Workers AI toMarkdown(适用于免费计划);readability = linkedom + Readability(质量最佳,需要 Workers Paid)。需要 AI 绑定;如果没有该绑定,服务会回退到 readability,并记录 config.lite_engine_without_ai。GET /health 会报告当前使用的引擎
DOH_URL否https://cloudflare-dns.com/dns-query
FETCH_TIMEOUT_MS否10000总截止时间,包含重定向和响应正文
MAX_RESPONSE_BYTES否3000000内容提取的下载上限
INSPECT_MAX_BYTES否65536检查的下载上限
MAX_REDIRECTS否5
MAX_URL_LENGTH否2048
MAX_REQUEST_BODY_BYTES否8192/mcp 允许的值为此值的 8 倍
DEFAULT_MAX_CHARACTERS / MAX_CHARACTERS_LIMIT否20000 / 100000
MAX_LINKS / MAX_HEADINGS否200 / 100

支付配置无效时会采取默认拒绝策略。付费端点会返回 503,并记录原因(payments.misconfigured);免费端点仍可正常工作。速率限制使用 Workers Rate Limiting 绑定(每个 Cloudflare 位置按客户端 IP 计算:INSPECT_RATE_LIMITER 为 30 次/分钟,PAID_RATE_LIMITER 为 120 次/分钟)。请在 wrangler.jsonc 中调整这些值。

测试

npm test

所有测试都通过 @cloudflare/vitest-plugin 在 workerd(Workers 运行时)中运行,不会访问互联网、区块链或真实的 facilitator。

套件覆盖范围
tests/unit/security.test.tsURL 验证/规范化、约 50 种 SSRF 拒绝情形(环回地址、私有地址、链路本地地址、元数据、IPv6、映射 IPv4、十进制/十六进制/八进制 IP、通配符 DNS 主机、端口、凭据、协议)、IP 分类、DoH 防护
tests/unit/fetch.test.ts手动重定向、每一跳都重新验证、每一跳的 DNS 防护、重定向次数限制、超时、Content-Length 和流式大小限制、标头卫生
tests/unit/extraction.test.tsReadability 提取、移除模板内容、Markdown(列表、表格、代码、链接)、元数据、标题/链接、截断、格式错误的 HTML、SPA 检测、字符集、真实场景结构回归
tests/unit/config.test.ts价格/网络/收款方/facilitator 验证、架构、错误规范化
tests/integration/payments.test.ts402 格式(金额、资产、网络、payTo)、402 前验证、伪造/垃圾/篡改/付款不足/收款方错误/重放的支付、完整的 @x402/fetch 流程、提取失败时不结算、结算失败时不提供内容、facilitator 故障
tests/integration/http.test.ts健康检查、发现、OpenAPI、inspect 变体、请求体/内容类型限制、速率限制、所有提取失败模式、截断、重定向、纯文本、旧版字符集
tests/integration/mcp.test.ts初始化、工具发现、免费工具、支付质询、付款前验证、伪造的 _meta、使用 @x402/mcp 自动支付、失败时不结算、结算失败

模拟内容与真实内容。 支付测试使用真实的 x402 SDK 进行端到端测试:

  • 客户端使用 @x402/fetch 和 @x402/mcp,并通过一次性钱包生成真实的 EIP-712 签名。
  • 服务端使用 @x402/hono 和 @x402/mcp。
  • facilitator 使用真实的 x402Facilitator 和 @x402/evm 的 exact 方案,因此签名、金额、收款方、到期时间和 nonce 检查均由 SDK 代码执行。

只有区块链是模拟的(tests/helpers/facilitator.ts),上游网页也一样(tests/helpers/upstream.ts)。npm test 不会覆盖真实网络上的实际结算。 请使用 npm run smoke:testnet 进行测试。

部署到 Cloudflare

先决条件:

  • 一个 Cloudflare 账户。免费套餐即可使用,但需设置 EXTRACTION_ENGINE=lite,这是默认配置。只有在 Workers Paid(每月 $5)上才能切换到 readability;请参阅提取引擎。
  • 账户已启用 Workers AI(默认已启用)。文档说明 HTML→Markdown 转换免费;付费的图像描述功能已明确禁用。
  • npx wrangler login。
生产环境(Base 主网,真实 USDC)
# 1. Create a CDP API key: https://portal.cdp.coinbase.com  (needed for the CDP facilitator)
npx wrangler secret put CDP_API_KEY_ID --env production
npx wrangler secret put CDP_API_KEY_SECRET --env production
# 2. Set your mainnet receiving address in wrangler.jsonc → env.production.vars.X402_PAY_TO
#    (an address you control on Base; consider a dedicated wallet)
# 3. Deploy
npm run deploy:production       # → https://agentread.<your-subdomain>.workers.dev
# 4. Verify health shows {"network":"eip155:8453"} and an unpaid request returns 402 with amount "3000"

日志:运行 npx wrangler tail --env production,或在控制面板中查看 Workers Observability(已在 wrangler.jsonc 中启用)。

自定义域名(稍后配置)

将域名添加到 Cloudflare 账户,然后在 env.production 下添加 "routes": [{ "pattern": "read.example.com", "custom_domain": true }] 并重新部署。支付要求会将请求 URL 用作 x402 resource,因此无需其他更改。

测试网支付演示

测试网可通过 npm run dev 在本地运行(Base Sepolia,x402.org facilitator)。已生成两个测试网钱包:收款方 0xDE20133E787A3cc64565b7AF1cF2bE3bEA3298Ea,以及付款方 0x7816FC23017c86aa917AdbD44367312696421322。两个私钥都保存在 .secrets/testnet-wallets.json 中;该文件已加入 gitignore,且仅文件所有者可访问。仅限测试网使用:切勿向这些地址发送主网资金。

  1. 在 https://faucet.circle.com 为付款方领取 Base Sepolia USDC(选择 Base Sepolia)。无需 ETH。
  2. 在本地运行付费流程:
    echo "X402_PAY_TO=0xDE20133E787A3cc64565b7AF1cF2bE3bEA3298Ea" > .dev.vars
    npm run dev   # in one terminal
    export EVM_PRIVATE_KEY=$(node -p 'require("./.secrets/testnet-wallets.json").payer.privateKey')
    npm run smoke:testnet && npm run smoke:mcp   # in another (AGENTREAD_URL defaults to localhost:8787)
    
  3. 在 https://sepolia.basescan.org/address/0xDE20133E787A3cc64565b7AF1cF2bE3bEA3298Ea 查看转账记录

可观测性

结构化 JSON 日志(console.log),不包含机密、付款载荷、签名或页面内容:

事件字段
http.requestmethod、route、status、durationMs、paid(已结算)
extract.success / extract.failureop、host(仅主机名)、method 或错误代码、ms、chars
mcp.extract.success / mcp.extract.failuretool、host、method / code
payment.settled / payment.settle_rejectednetwork、amount、公开交易哈希、payer(加盐 SHA-256 前缀,不是地址)
payment.verify_rejected、payment.verify_error、payment.settle_errorreason / error class
payments.misconfigured、config.invalid、http.internal_errorreason

这些日志可用于了解请求量、成功率、失败原因、延迟、不同付款方和重复付款方数量(payer 哈希),以及验证 / 结算失败情况。可在 Workers Observability 中查询。

提取引擎

两种引擎使用相同的 API、架构和付款流程(EXTRACTION_ENGINE):

lite(默认)readability
工作方式通过子字符串检查选取内容根节点(#mw-content-text、.markdown-body、单个 <article>、<main>、[role=main])。将页面交给 Workers AI toMarkdown(转换在我们的 JS 之外运行)。使用少量正则表达式读取 <head> 中的元数据。逐行移除已知噪声linkedom DOM、移除冗余内容、Mozilla Readability、Turndown(GFM 表格)
每个请求的 Edge CPU(实测真实页面)p50 ≈ 10–13 ms,p90 ≈ 35–47 msp50 ≈ 70–80 ms,p75 ≈ 120–285 ms
Workers Free 计划下约 180 个请求中 CPU 限制导致的终止次数为 0(5 次基准测试)33–84% 的请求被终止(错误 1102)
质量适用于文档、文章、Wikipedia 和 GitHub README。对于没有明确内容根节点的页面效果较差;某些 GitHub 代码块会丢失围栏;索引页噪声较多整体效果最佳;内容评分可处理任意布局
额外依赖Workers AI toMarkdown(文档说明 HTML 转换免费)无

这些测量数据来自临时的 src/bench.ts Worker,由 .github/workflows/bench.yml 驱动;CPU 百分位数据来自 Cloudflare 的 GraphQL 分析(2026 年 10 月)。Free 计划的 CPU 限制并非简单地按每个请求 10 ms 截断:lite 的实测 CPU 用量超过 10 ms,但从未被终止。限制机制不透明,且可能发生变化;如果看到 1102 错误,请重新运行基准测试。当收入足以支撑每月 $5 的费用时,切换到 Workers Paid 和 EXTRACTION_ENGINE=readability。

定价和成本说明

默认价格:$0.003(提取)和 $0.005(结构化)。更改价格前,请考虑以下成本(2026 年 10 月价格,请核实当前价格):

  • Cloudflare Workers:
    • 使用 lite 引擎时为 Free:每天 100k 个请求,$0。
    • Paid(每月至少 $5,readability 所需)包含 10M 个请求和 30M CPU-ms;超出后每百万个请求收费 $0.30,每百万 CPU-ms 收费 $0.02。每次 Readability 提取约消耗 80 CPU-ms,因此额度用完后,每个请求的计算成本约为 $0.000002。
  • Workers AI toMarkdown: 文档说明 HTML 转换免费。AgentRead 从不启用图片转换;该功能会使用付费 AI 模型。
  • CDP facilitator(主网): 每月前 1,000 次结算免费,此后每次结算收费 $0.001。按 $0.003 的价格计算,这占收入的 33%;按 $0.005 计算则占 20%。这是主要的边际成本。SDK 支持批量结算,可降低这项成本(见后续步骤)。
  • Gas: 在 exact EIP-3009 流程中,付款方只需签署授权。结算交易由 facilitator 提交,因此付款方不需要 ETH。CDP 声明,Gas 在链上支付,与其费用分开。请查看 facilitator 当前条款,确认是否会将 Gas 成本转嫁给用户。
  • 浏览器渲染(暂缓):会增加按秒计费的浏览器成本;如需添加,应单独定价。

限制

  • Lite 引擎质量(免费计划默认使用)在内容根节点不明确的页面上不如 Readability。部分 GitHub 代码块会丢失围栏。它依赖 Workers AI 的 toMarkdown 对 HTML 免费开放。
  • 不执行 JavaScript。 由客户端渲染的页面会返回 javascript_required(422,不收费)。inspect_url 会通过 mayRequireJavaScript 标记可能需要 JavaScript 的情况。
  • 支持的内容: 仅支持 HTML/XHTML、text/plain 和 text/markdown。PDF、图片和 JSON 会被拒绝,并返回 unsupported_content_type。
  • 会遵守访问控制:绝不会转发 Cookie、身份验证标头或客户端凭据,也不会绕过付费墙和 CAPTCHA。
  • SSRF: 具备强大的应用层控制和 Workers 网络隔离,但无法在应用层彻底消除 DNS 重绑定风险。请参阅 docs/security.md。此项目尚未经过独立安全审查或渗透测试。
  • 支付:
    • 不提供退款;除支付促进方和 EIP-3009 nonce 所提供的保证外,不保证恰好执行一次。
    • 如果提取完成后结算失败,内容将不会提供(402)。
    • 在少数情况下,如果支付促进方在广播后超时,转账仍可能上链,但内容不会送达。此情况已记录在 docs/payments.md 中。
  • 速率限制按 Cloudflare 位置计算,且为近似值(Workers Rate Limiting API)。
  • 仅配置了 Base 和 Base Sepolia,并通过 exact 方案使用 USDC。
  • 尚未完成真实资金支付。 真实支付促进方流程已验证至余额检查。请为生成的付款方钱包充值并运行 npm run smoke:testnet(见上文)。
  • Bazaar 发现仅针对 MCP 工具声明,不适用于 HTTP 路由(SDK 验证使用 Workers 禁止的运行时代码生成)。

故障排除

症状解决方法
npm install 失败,并显示 Cannot read properties of null (reading 'edgesOut')这是 npm 10.9 中与 vitest 对等依赖相关的已知 arborist 错误。请使用 npm 11:npx -y npm@11 install
npm 11 警告 install-scripts … workerdworkerd 二进制通过可选平台包提供,无需运行脚本即可使用。如果 npx wrangler --version 失败,请运行 npx npm@11 install-scripts approve workerd
付费端点返回 503 payments_unavailable支付配置无效。检查日志中的 payments.misconfigured(例如,X402_PAY_TO 为零地址、缺少 CDP 密钥,或生产环境使用了测试网)
npx wrangler deploy 成功,但 workers.dev URL 超时某些网络和 ISP 会屏蔽 Cloudflare 的 workers.dev 地址段(188.114.96.0/20)。请尝试其他网络、使用自定义域名,或运行 CI 冒烟测试任务(gh workflow run CI -f agentread_url=…)
付款后仍返回 402付款方可能未在正确的网络上持有 USDC,授权可能已过期(maxTimeoutSeconds: 120),金额可能对应另一个端点,或者载荷已被重放。payment.verify_rejected 日志会记录原因
javascript_required页面由客户端渲染。AgentRead 不会运行 JavaScript
公共站点返回 blocked_destination该站点解析到非公共 IP,使用了非默认端口,或 URL 使用了 IP 字面量
提取失败并出现 1102 / CPU 限制错误在免费计划上,请确保 EXTRACTION_ENGINE=lite,并且该环境中存在 AI 绑定(GET /health → "extractionEngine":"lite")。Wrangler 不会将绑定继承到 env.* 块中
wrangler dev 报告兼容日期有问题请确保 compatibility_date 不晚于捆绑的 workerd 版本(npx wrangler --version)

项目结构

src/
  index.ts                 Worker entry
  api/                     Hono app, per-request context, discovery, OpenAPI
  mcp/server.ts            Stateless MCP server + x402 payment wrapper
  payments/x402.ts         Facilitator client, resource server, route pricing, logging hooks
  extraction/              Bounded fetch, HTML cleaning, Readability, Markdown, operations
  security/                URL policy, IP classification, DoH guard
  schemas/                 Versioned zod schemas (shared by HTTP, MCP, OpenAPI, tests)
  config/env.ts            Config loading/validation (fails closed)
  utils/                   Errors, structured logging
tests/{unit,integration,helpers,fixtures}
scripts/                   Smoke tests and example clients (Node)
docs/                      Architecture, payments, security, demo script

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。