CleanPage

io.github.IO31-WEB由 GitHub 帳號 IO31-WEB 發布v1.0.0更新於 Oct 27, 2026

Turn any URL into clean, structured, agent-ready content. $0.02/call via x402 on Base.

發布方自己的服務:Clean

已驗證Streamable HTTP可網頁執行網頁搜尋與抓取金融

概覽

AI 產生的概覽

遠端 MCP 伺服器,抓取網址並回傳乾淨的 Markdown、純文字、中繼資料、連結與品質分數,依次透過 Base 上的 x402 以 USDC 付費。

可以做什麼
  • 抓取網頁並擷取為乾淨的 Markdown、純文字、中繼資料、連結、圖片與品質分數,可選擇產生結構化事實
  • 查詢服務狀態、版本與運作時間
  • 列出可用工具及其價格與輸入結構
  • 讀取目前定價、支援的支付網路與資產以及 x402 支付流程
適用情境
適合需要從任意網址取得可讀正文而非原始 HTML 的情境,且能接受依次支付少量 USDC。免費工具可讓助理在花錢前先確認能力與價格。
執行需求
需要遠端 Streamable HTTP 端點,無需帳號或 API 金鑰。付費的 clean_page 需要支援 x402 的用戶端與 Base 錢包,用來簽署 USDC 的 EIP-3009 授權並送出 X-PAYMENT 標頭;多數 x402 用戶端函式庫會自動處理。
安裝前請注意
clean_page 每次成功呼叫收費 0.02 USDC(Base 網路),接上已儲值錢包的助理可能產生費用;擷取失敗不收費。用戶端需以錢包簽署支付授權。所請求的網址由遠端服務抓取;付費牆、機器人驗證或純 JavaScript 渲染的頁面會失敗。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 CleanPage,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.IO31-WEB%2Fcleanpage/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "cleanpage": {
      "type": "http",
      "url": "https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"
    }
  }
}

README

CleanPage

A paid MCP tool that turns any URL into clean, structured, agent-optimized content. Agents pay $0.02 USDC per successful call via x402 on Base — no accounts, no API keys, no subscriptions.

clean_page(url) → { title, clean_markdown, plain_text, structured_facts,                     metadata, links, images, quality_score, extraction_notes }

Built for Cloudflare Workers. Full TypeScript. No paid infra required beyond a domain and a Base wallet address.


How agents use this

  1. Discover the service for free — no payment needed for any of this:

    • GET /.well-known/agent.json — machine-readable capability card
    • GET /.well-known/mcp.json — MCP connection + pricing manifest
    • GET /llms.txt — plain-text summary for LLM crawlers
    • MCP tools health, list_capabilities, pricing (all free)
  2. Connect an MCP client to https://<your-domain>/mcp over Streamable HTTP:

    json
    {  "mcpServers": {    "cleanpage": { "url": "https://<your-domain>/mcp", "transport": "streamable-http" }  }}
  3. Call clean_page with no payment attached first:

    POST /mcp{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",  "params": { "name": "clean_page", "arguments": { "url": "https://example.com/article" } } }

    The response is HTTP 402 with an accepts array describing exactly what payment is required (amount, network, asset, payee address).

  4. Sign and retry. Construct a USDC transferWithAuthorization (EIP-3009) payment payload for the requested amount, base64-encode it, and retry the same request with an X-PAYMENT header. Most x402 client libraries (e.g. x402-fetch, x402-axios) do steps 3–4 for you automatically.

  5. Get the result. On success, the response carries the full JSON result plus an X-PAYMENT-RESPONSE header with the settlement transaction hash. Failed extractions (paywalls, bot-blocks, empty pages) are never charged — settlement only happens after a successful extraction.

Full protocol details: see /llms.txt and /.well-known/mcp.json once deployed, or the "For agents" section of the landing page.


Project structure

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

Architecture notes

MCP transport. The MCP Streamable HTTP transport is implemented directly in src/mcp/server.ts as a stateless JSON-RPC 2.0 dispatcher (initialize, tools/list, tools/call, ping), rather than via the official SDK's Node-oriented HTTP transport class. This is a deliberate choice for correctness on Cloudflare Workers: the SDK's transport targets Node's http.IncomingMessage/ServerResponse, which Workers doesn't have. The dispatcher here follows the same wire protocol (JSON-RPC over a single POST endpoint, one server-scoped session per request) so any standard MCP client can connect to it. If you later run this on a Node-based host, you can swap in @modelcontextprotocol/sdk's StreamableHTTPServerTransport directly.

Payment gating. POST /mcp peeks at the parsed JSON-RPC body: only tools/call requests naming clean_page are payment-gated (src/index.ts); health, list_capabilities, pricing, and all non-tool-call methods (initialize, tools/list, etc.) pass straight through, rate-limited but free. This keeps the discovery surface fully open to agents while gating only the one paid capability.

Settlement timing. Payment is verified before extraction runs, but settled (broadcast on-chain) only after extraction succeeds. If extraction fails, the agent's payment authorization is simply discarded — nothing is charged.

No private key required. Because USDC on Base supports EIP-3009 meta-transactions, the resource server never holds a private key. PAYMENT_ADDRESS is a public wallet address; the facilitator submits the signed authorization on-chain and sponsors gas.

Extraction engine. @mozilla/readability (the engine behind Firefox Reader Mode) does the core content extraction, running against a DOM built with linkedom (a fast, dependency-light DOM implementation that works in Workers — jsdom does not). A small hand-written HTML→Markdown walker converts the extracted fragment to markdown, since no existing markdown-conversion library is both Workers-compatible and DOM-based. Heuristics before and after extraction catch common failure modes: paywall markers, bot-check pages, and JS-only empty shells all produce typed errors instead of low-quality output.

Optional LLM enrichment. structured_facts is populated only when the caller passes options.extract_facts: true, and only if ENABLE_LLM_ENRICHMENT=true and ANTHROPIC_API_KEY is set. It's off the critical path — if the enrichment call fails or is disabled, clean_page still returns a complete result with an empty structured_facts array and a note explaining why. There's no additional charge for using it.

Rate limiting & analytics. Both are implemented with a single KV namespace: a fixed 1-minute-window counter per client IP for free-tier calls, and a running JSON counter object for total calls / successes / failures / revenue, exposed read-only at GET /analytics.


Required services / infrastructure

ComponentWhat you needWhere to get it
HostingCloudflare Workers (with Static Assets)dash.cloudflare.com — free tier works to start
Domain + DNSA domain proxied through CloudflareAny registrar; add to Cloudflare, point at the Worker
WalletA Base wallet address (public address only)Any EVM wallet — Coinbase Wallet, MetaMask, etc.
x402 facilitatorVerifies/settles paymentshttps://x402.org/facilitator (testnet-friendly default); Coinbase-operated or self-hosted facilitators for mainnet production volume
KV namespaceRate limiting + analytics storagewrangler kv namespace create CLEANPAGE_KV
LLM (optional)Structured fact extractionAnthropic API key, only if ENABLE_LLM_ENRICHMENT=true

No database, no queue, no separate backend — everything runs in the one Worker.


Deployment (step by step)

bash
# 1. Install dependenciesnpm install
# 2. Create the KV namespace used for rate limiting + analyticsnpx wrangler kv namespace create CLEANPAGE_KVnpx 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 extractionnpx wrangler secret put ANTHROPIC_API_KEY
# 5. Type-checknpm run typecheck
# 6. Deploynpm 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.

Local development

bash
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"}'

Going from testnet to mainnet

  1. Switch X402_NETWORK from base-sepolia to base in wrangler.toml.
  2. Switch X402_FACILITATOR_URL to a mainnet-capable facilitator (confirm your chosen facilitator supports Base mainnet settlement — verify current facilitator options, as this ecosystem is still young and options change).
  3. Re-deploy.

Environment variables

See .env.example for the full annotated list. Summary:

VariableRequiredDefaultPurpose
PAYMENT_ADDRESSyes—Base wallet address receiving USDC
X402_NETWORKyesbase-sepoliabase or base-sepolia
X402_FACILITATOR_URLyeshttps://x402.org/facilitatorFacilitator used for verify/settle
CLEAN_PAGE_PRICE_USDyes0.02Price per successful clean_page call
PUBLIC_BASE_URLyes—Your deployed URL, used in discovery files
FREE_RATE_LIMIT_PER_MINno30Free-tier calls per IP per minute
ENABLE_LLM_ENRICHMENTnotrueEnables structured_facts extraction
LLM_MODELnoclaude-haiku-4-5-20251001Model used for enrichment
ANTHROPIC_API_KEYonly if enrichment enabled—Secret; set via wrangler secret put

Example MCP client configuration

json
{  "mcpServers": {    "cleanpage": {      "url": "https://cleanpage.yourdomain.com/mcp",      "transport": "streamable-http"    }  }}

Example tool call and response shape

Request:

json
{  "jsonrpc": "2.0", "id": 1, "method": "tools/call",  "params": {    "name": "clean_page",    "arguments": { "url": "https://example.com/article", "options": { "extract_facts": true } }  }}

Successful response (after payment) — result.content[0].text is a JSON string shaped like:

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 codes

error_codeMeaningRetryable
INVALID_URLMalformed, non-http(s), or a blocked internal addressno
FETCH_FAILEDNon-2xx response, non-HTML content, or oversized pagesometimes
TIMEOUTPage didn't respond within the timeoutyes
PAYWALL_DETECTEDSubscription/metered paywall detectedno
BLOCKED_BY_SITEBot-check/CAPTCHA or JS-only empty shellno
EMPTY_CONTENTNo substantial article content foundno
EXTRACTION_FAILEDUnexpected parser errorno

Failed extractions always return before payment settlement, so they're never charged.


Known limitations

  • JavaScript-rendered pages: extraction fetches raw HTML and does not execute JavaScript, so client-side-rendered SPAs with no server-rendered content will return EMPTY_CONTENT or BLOCKED_BY_SITE. Adding a headless-browser rendering fallback (e.g. via Cloudflare Browser Rendering) is the natural next step if this matters for your traffic.
  • Facilitator dependency: payment verification and settlement depend on the configured x402 facilitator's uptime. x402.org/facilitator is a good default for development; evaluate production facilitators for reliability guarantees before scaling mainnet volume.
  • Rate limiting is best-effort: the KV-based counter has a small race window under concurrent bursts from the same IP; it's adequate abuse protection, not a hard guarantee.

來源:README.md,提交 0e9d444

工具

4

clean_page

Fetches a URL and returns clean, structured, agent-optimized content: readable markdown, plain text, metadata (author/date/site/word count), extracted links and images, an optional structured facts array, and a 0-100 quality score. Handles common failure modes (paywalls, bot-walls, empty JS shells) with clear typed errors instead of silently returning junk. PAID TOOL: $0.02 USDC per successful call via x402 (USDC on base). Call with no payment first to receive the exact payment requirements (HTTP 402), then retry with an X-PAYMENT header. Failed extractions are not charged.

輸入參數url必填options

health

Free. Returns service status, version, and uptime signal. Use to check the service is reachable before paying for anything.

無需輸入參數。

list_capabilities

Free. Returns the full list of tools this server offers, including which are paid, their prices, and their input schemas — so an agent can decide what to call before spending anything.

無需輸入參數。

pricing

Free. Returns current pricing, accepted payment network/asset, and the x402 payment flow details for paid tools.

無需輸入參數。

版本歷史

1
  1. v1.0.0最新Sep 18, 2026

評分

已滿足適用檢查項的 100%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

其他 Clean 整合