关于 CleanPage
CleanPage 是面向 Agent 的付费 MCP 服务,可将 URL 提取为易读的结构化内容。它返回 Markdown、纯文本、元数据、链接和图片;还可选用 LLM 补充结构化事实。
主要功能
- 01提取整洁的 Markdown 和纯文本
- 02返回元数据、链接和图片
- 03可选提取结构化事实
- 04提供免费的健康、能力和定价工具
- 05仅在提取成功后收费
适用场景
- 01为 Agent 处理网页文章做准备
- 02以结构化形式获取页面文本和链接
- 03从 URL 可选提取事实
MCP 相关
通过 Streamable HTTP MCP 端点提供免费的发现工具和付费 `clean_page` 工具。成功调用通过 Base 上的 x402 收取 0.02 USDC;提取失败不结算。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcpclaude mcp add --transport http io31-web-cleanpage https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp{"mcpServers":{"io31-web-cleanpage":{"type":"http","url":"https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"}}}在 Cursor 中打开{"servers":{"io31-web-cleanpage":{"type":"http","url":"https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"}}}在 VS Code 中打开{"mcpServers":{"io31-web-cleanpage":{"type":"http","url":"https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"}}}{"mcpServers":{"io31-web-cleanpage":{"serverUrl":"https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
4| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | 要提取的页面绝对 URL(仅限 http/https)。 |
| options | object | 否 | |
| options.language | string | 否 | ISO 语言提示,例如 'en'。 |
| options.max_length | integer | 否 | 将 clean_markdown/plain_text 截断至指定字符数。 |
| options.timeout_ms | integer | 否 | 获取超时时间(毫秒,最大 20000)。默认值为 10000。 |
| options.extract_facts | boolean | 否 | 运行结构化事实/声明提取。会增加延迟,不额外收费。 |
| options.include_images | boolean | 否 | 包含提取的图片 URL。默认值为 true。 |
详细介绍
CleanPage
一款付费 MCP 工具,可将任意 URL 转换为干净、结构化且针对 Agent 优化的内容。Agent 每次成功调用需通过 x402 在 Base 上支付 $0.02 USDC——无需账户、API 密钥或订阅。
clean_page(url) → { title, clean_markdown, plain_text, structured_facts,
metadata, links, images, quality_score, extraction_notes }
基于 Cloudflare Workers 构建。完整使用 TypeScript。除域名和 Base 钱包地址外,无需付费基础设施。
Agent 如何使用
-
免费发现此服务——以下操作均无需付费:
GET /.well-known/agent.json— 机器可读的能力卡片GET /.well-known/mcp.json— MCP 连接和定价清单GET /llms.txt— 面向 LLM 爬虫的纯文本摘要- MCP 工具
health、list_capabilities、pricing(全部免费)
-
连接 MCP 客户端,通过 Streamable HTTP 访问
https://<your-domain>/mcp:{ "mcpServers": { "cleanpage": { "url": "https://<your-domain>/mcp", "transport": "streamable-http" } } } -
先不附带付款,调用
clean_page:POST /mcp { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "clean_page", "arguments": { "url": "https://example.com/article" } } }响应为 HTTP 402,其中包含一个
accepts数组,准确说明所需的付款信息(金额、网络、资产、收款地址)。 -
签名并重试。 为请求的金额构造 USDC
transferWithAuthorization(EIP-3009)付款载荷,将其进行 base64 编码,然后在请求中加入X-PAYMENT标头并重试同一请求。大多数 x402 客户端库(例如x402-fetch、x402-axios)会自动为你完成步骤 3–4。 -
获取结果。 成功时,响应会包含完整的 JSON 结果,以及带有结算交易哈希的
X-PAYMENT-RESPONSE标头。提取失败(付费墙、机器人拦截、页面为空)绝不会收费——只有成功提取后才会结算。
完整协议详情:部署后查看 /llms.txt 和 /.well-known/mcp.json,或访问落地页的“For agents”部分。
项目结构
cleanpage/
├── src/
│ ├── index.ts # Hono app: routes, x402 payment gate, static asset fallback
│ ├── types.ts # Shared types (Env, CleanPageResult, etc.)
│ ├── config.ts # Reads env vars into a typed config object
│ ├── mcp/
│ │ ├── server.ts # JSON-RPC 2.0 / MCP method dispatcher (stateless)
│ │ └── tools.ts # Tool schemas + descriptions (clean_page, health, ...)
│ ├── extraction/
│ │ ├── extractor.ts # Core pipeline: fetch → Readability → markdown/links/metadata
│ │ └── enrichment.ts # Optional cheap LLM pass for structured_facts
│ ├── payments/
│ │ └── x402.ts # x402 payment requirements, facilitator verify/settle
│ └── middleware/
│ └── limits.ts # KV-backed rate limiting + call/revenue analytics
├── public/ # Static assets served at the Worker's root
│ ├── index.html # Landing page (live demo, pricing, docs, for-agents)
│ ├── robots.txt # Explicitly welcomes agent/LLM crawlers
│ ├── llms.txt # Plain-text agent-facing summary
│ └── .well-known/
│ ├── agent.json # Agent discovery/capability card
│ └── mcp.json # MCP connection + pricing manifest
├── wrangler.toml # Cloudflare Workers config (bindings, vars)
├── package.json
├── tsconfig.json
└── .env.example # Documents every config value
架构说明
MCP 传输。 MCP Streamable HTTP 传输在 src/mcp/server.ts 中直接实现为无状态的 JSON-RPC 2.0 分发器(initialize、tools/list、tools/call、ping),而不是通过官方 SDK 面向 Node 的 HTTP 传输类实现。这是为了确保在 Cloudflare Workers 上正确运行而做出的有意选择:SDK 的传输面向 Node 的 http.IncomingMessage/ServerResponse,而 Workers 中并不存在这些对象。此处分发器遵循相同的线路协议(通过单个 POST 端点传输 JSON-RPC,每个请求对应一个服务级会话),因此任何标准 MCP 客户端都可以连接。如果以后在基于 Node 的主机上运行,可以直接换用 @modelcontextprotocol/sdk 的 StreamableHTTPServerTransport。
支付门控。 POST /mcp 会检查解析后的 JSON-RPC 请求正文:只有命名为 clean_page 的 tools/call 请求需要通过支付门控(src/index.ts);health、list_capabilities、pricing 以及所有非工具调用方法(initialize、tools/list 等)都会直接通过,但仍受速率限制且免费。这样可让 Agent 完全开放地发现功能,同时只对这一项付费能力进行门控。
结算时机。 提取开始前会验证支付,但只有在提取成功后才会结算(在链上广播)。如果提取失败,Agent 的支付授权会直接作废,不会收取任何费用。
无需私钥。 由于 Base 上的 USDC 支持 EIP-3009 元交易,资源服务不会持有私钥。PAYMENT_ADDRESS 是公开的钱包地址;facilitator 会在链上提交已签名的授权并承担 Gas 费用。
提取引擎。 @mozilla/readability(Firefox 阅读模式背后的引擎)负责核心内容提取,其运行基于由 linkedom 构建的 DOM(这是一种速度快、依赖轻量且可在 Workers 中运行的 DOM 实现,jsdom 则不行)。由于没有现成的 Markdown 转换库能同时兼容 Workers 并基于 DOM,因此使用手写的简易 HTML→Markdown 遍历器将提取出的片段转换为 Markdown。提取前后的启发式检查可捕获常见故障模式:付费墙标记、机器人检查页面和仅含 JS 的空页面都会产生带类型的错误,而不是低质量输出。
可选的 LLM 增强。 只有在调用方传入 options.extract_facts: true,并且设置了 ENABLE_LLM_ENRICHMENT=true 和 ANTHROPIC_API_KEY 时,才会填充 structured_facts。它不属于关键路径:如果增强调用失败或已禁用,clean_page 仍会返回完整结果,其中 structured_facts 数组为空,并附带说明原因的备注。使用此功能不收取额外费用。
速率限制与分析。 两者均通过单个 KV 命名空间实现:免费层调用按客户端 IP 进行固定 1 分钟窗口计数,并使用持续更新的 JSON 计数对象统计调用总数、成功数、失败数和收入,这些数据可通过 GET /analytics 只读访问。
所需服务 / 基础设施
| 组件 | 所需内容 | 获取方式 |
|---|---|---|
| 托管 | Cloudflare Workers(带 Static Assets) | dash.cloudflare.com — 起步时可使用免费层 |
| 域名 + DNS | 通过 Cloudflare 代理的域名 | 任意注册商;将域名添加到 Cloudflare,并指向 Worker |
| 钱包 | Base 钱包地址(仅需公开地址) | 任意 EVM 钱包 — Coinbase Wallet、MetaMask 等 |
| x402 facilitator | 验证 / 结算支付 | https://x402.org/facilitator(适用于测试网的默认选项);主网生产用量可使用 Coinbase 运营或可自托管的 facilitator |
| KV 命名空间 | 速率限制 + 分析数据存储 | wrangler kv namespace create CLEANPAGE_KV |
| LLM(可选) | 结构化事实提取 | 仅在 ENABLE_LLM_ENRICHMENT=true 时需要 Anthropic API 密钥 |
无需数据库、队列或独立后端 — 所有内容都运行在同一个 Worker 中。
部署(分步指南)
# 1. Install dependencies
npm install
# 2. Create the KV namespace used for rate limiting + analytics
npx wrangler kv namespace create CLEANPAGE_KV
npx wrangler kv namespace create CLEANPAGE_KV --preview
# Copy the two returned IDs into wrangler.toml under [[kv_namespaces]]
# 3. Edit wrangler.toml [vars]:
# - PAYMENT_ADDRESS → your Base wallet address
# - PUBLIC_BASE_URL → your real domain, e.g. https://cleanpage.yourdomain.com
# - X402_NETWORK → "base-sepolia" while testing, "base" for mainnet
# Also update the same URLs/addresses in:
# - public/.well-known/agent.json
# - public/.well-known/mcp.json
# - public/llms.txt
# - public/index.html (og:url, structured data, MCP config example)
# 4. (Optional) enable LLM fact extraction
npx wrangler secret put ANTHROPIC_API_KEY
# 5. Type-check
npm run typecheck
# 6. Deploy
npm run deploy
# 7. Point your domain at the Worker (Cloudflare dashboard → Workers →
# your worker → Triggers → Custom Domains), or use the workers.dev
# subdomain Wrangler prints after deploy.
本地开发
npm run dev
# Worker runs at http://localhost:8787
# Try: curl -X POST http://localhost:8787/mcp -H "Content-Type: application/json" \
# -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
从测试网切换到主网
- 在
wrangler.toml中将X402_NETWORK从base-sepolia切换为base。 - 将
X402_FACILITATOR_URL切换为支持主网的 Facilitator(确认所选 Facilitator 支持 Base 主网结算——请核实当前可用的 Facilitator 选项,因为这个生态仍处于早期阶段,选项可能会变化)。 - 重新部署。
环境变量
完整的注释列表请参阅 .env.example。摘要如下:
| 变量 | 必填 | 默认值 | 用途 |
|---|---|---|---|
PAYMENT_ADDRESS | 是 | — | 接收 USDC 的 Base 钱包地址 |
X402_NETWORK | 是 | base-sepolia | base 或 base-sepolia |
X402_FACILITATOR_URL | 是 | https://x402.org/facilitator | 用于验证/结算的 Facilitator |
CLEAN_PAGE_PRICE_USD | 是 | 0.02 | 每次成功调用 clean_page 的价格 |
PUBLIC_BASE_URL | 是 | — | 部署后的 URL,用于发现文件 |
FREE_RATE_LIMIT_PER_MIN | 否 | 30 | 每个 IP 每分钟的免费调用次数 |
ENABLE_LLM_ENRICHMENT | 否 | true | 启用 structured_facts 提取 |
LLM_MODEL | 否 | claude-haiku-4-5-20251001 | 用于增强的模型 |
ANTHROPIC_API_KEY | 仅在启用增强功能时需要 | — | 密钥;通过 wrangler secret put 设置 |
MCP 客户端配置示例
{
"mcpServers": {
"cleanpage": {
"url": "https://cleanpage.yourdomain.com/mcp",
"transport": "streamable-http"
}
}
}
工具调用和响应格式示例
请求:
{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {
"name": "clean_page",
"arguments": { "url": "https://example.com/article", "options": { "extract_facts": true } }
}
}
成功响应(付款后)——result.content[0].text 是一个 JSON 字符串,格式如下:
{
"title": "Article title",
"clean_markdown": "# Article title\n\nBody content as markdown…",
"plain_text": "Body content as plain text…",
"structured_facts": [
{ "claim": "…", "category": "fact", "confidence": 0.82 }
],
"metadata": {
"author": "Jane Doe", "published_date": "2026-08-01T00:00:00Z",
"site_name": "Example", "language": "en",
"word_count": 812, "reading_time_minutes": 4,
"fetched_at": "2026-09-17T12:00:00.000Z",
"final_url": "https://example.com/article", "status_code": 200
},
"links": [{ "url": "https://example.com/other", "text": "related", "type": "internal" }],
"images": ["https://example.com/hero.jpg"],
"quality_score": 85,
"extraction_notes": []
}
错误代码
error_code | 含义 | 是否可重试 |
|---|---|---|
INVALID_URL | 格式错误、非 http(s) 或被屏蔽的内部地址 | 否 |
FETCH_FAILED | 非 2xx 响应、非 HTML 内容或页面过大 | 有时 |
TIMEOUT | 页面未在超时时间内响应 | 是 |
PAYWALL_DETECTED | 检测到订阅/计量付费墙 | 否 |
BLOCKED_BY_SITE | 机器人检查/CAPTCHA 或仅含 JS 的空页面 | 否 |
EMPTY_CONTENT | 未找到实质性文章内容 | 否 |
EXTRACTION_FAILED | 意外的解析器错误 | 否 |
提取失败时总会在结算前返回,因此不会产生费用。
已知限制
- JavaScript 渲染的页面:提取过程会获取原始 HTML,不会执行 JavaScript,因此没有服务端渲染内容的客户端渲染 SPA 会返回
EMPTY_CONTENT或BLOCKED_BY_SITE。如果这对你的流量很重要,下一步自然是添加无头浏览器渲染回退方案(例如通过 Cloudflare Browser Rendering)。 - 对 Facilitator 的依赖:付款验证和结算取决于配置的 x402 Facilitator 是否正常运行。
x402.org/facilitator是开发环境的良好默认选项;在扩大主网流量之前,请评估生产环境 Facilitator 的可靠性保证。 - 速率限制尽力而为:基于 KV 的计数器在同一 IP 并发突发请求时存在一个较小的竞争窗口;它足以防范滥用,但并非严格保证。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。