mcpField
C
CleanPage

CleanPage

リモート
github.com/IO31-WEBブラウザ自動化06 週間前に更新
リポジトリ

CleanPage について

CleanPage は、URL から読みやすい構造化コンテンツを抽出する、エージェント向けの有料 MCP サービスです。Markdown、テキスト、メタデータ、リンク、画像を返し、任意で LLM による事実抽出も行えます。

主な機能

  1. 01整形済み Markdown とテキストの抽出
  2. 02メタデータ、リンク、画像の返却
  3. 03構造化された事実の任意抽出
  4. 04ヘルス、機能、料金の無料ツール
  5. 05抽出成功後のみ課金

活用シーン

  1. 01エージェントによる記事処理の準備
  2. 02ページ本文とリンクの構造化取得
  3. 03URL から事実を任意抽出

MCP 対応

Streamable HTTP の MCP エンドポイントで、無料の検出ツールと有料の `clean_page` ツールを提供します。成功した呼び出しは Base 上の x402 により 0.02 USDC で課金され、抽出失敗時は決済されません。

設定

リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。

エンドポイントhttps://cleanpage-mcp.cleanpage-mcp.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 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。

ツール

4
パラメーター型必須説明
urlstringはい抽出対象ページの絶対URL(http/httpsのみ)。
optionsobjectいいえ
options.languagestringいいえISO言語ヒント。例:'en'。
options.max_lengthintegerいいえclean_markdown/plain_textを指定した文字数に切り詰めます。
options.timeout_msintegerいいえ取得のタイムアウト(ミリ秒、最大20000)。デフォルトは10000です。
options.extract_factsbooleanいいえ構造化された事実/主張の抽出を実行します。遅延が増加しますが、追加料金はかかりません。
options.include_imagesbooleanいいえ抽出した画像 URL を含めます。デフォルトは true です。

詳細

CleanPage

あらゆる URL を、エージェントに最適化された、整理済みのクリーンなコンテンツに変換する有料 MCP ツールです。エージェントは x402 を介して Base 上で、成功した呼び出し 1 回につき $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 ウォレットアドレス以外に、有料のインフラは必要ありません。


エージェントによる利用方法

  1. 無料でサービスを確認します。以下はいずれも支払い不要です。

    • GET /.well-known/agent.json — 機能を機械可読形式で記述したカード
    • GET /.well-known/mcp.json — MCP 接続と料金のマニフェスト
    • GET /llms.txt — LLM クローラー向けのプレーンテキストの概要
    • MCP ツール health、list_capabilities、pricing(すべて無料)
  2. Streamable HTTP を使用して、MCP クライアントを https://<your-domain>/mcp に接続します。

    {
      "mcpServers": {
        "cleanpage": { "url": "https://<your-domain>/mcp", "transport": "streamable-http" }
      }
    }
    
  3. 最初は支払いを添付せずに 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 配列が含まれます。

  4. 署名して再試行します。 要求された金額の USDC transferWithAuthorization(EIP-3009)支払いペイロードを作成し、Base64 でエンコードして、X-PAYMENT ヘッダーを付けて同じリクエストを再試行します。多くの x402 クライアントライブラリ(例:x402-fetch、x402-axios)では、手順 3~4 が自動的に実行されます。

  5. 結果を取得します。 成功すると、応答には完全な JSON 結果と、決済トランザクションのハッシュを含む X-PAYMENT-RESPONSE ヘッダーが含まれます。抽出に失敗した場合(ペイウォール、ボットによるブロック、空のページ)は、料金が請求されることはありません。決済は抽出の成功後にのみ行われます。

プロトコルの詳細については、デプロイ後に /llms.txt と /.well-known/mcp.json を参照するか、ランディングページの「エージェント向け」セクションを参照してください。


プロジェクト構成

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 トランスポートは、公式 SDK の Node 向け HTTP トランスポートクラスを介さず、src/mcp/server.ts でステートレスな JSON-RPC 2.0 ディスパッチャー(initialize、tools/list、tools/call、ping)として直接実装されています。これは Cloudflare Workers 上で正しく動作させるための意図的な選択です。SDK のトランスポートは Node の http.IncomingMessage/ServerResponse を対象としていますが、Workers にはこれらがありません。このディスパッチャーは同じワイヤープロトコル(単一の POST エンドポイント上の JSON-RPC、リクエストごとにサーバー単位のセッションを 1 つ使用)に従うため、標準的な MCP クライアントであれば接続できます。後で Node ベースのホスト上で実行する場合は、@modelcontextprotocol/sdk の StreamableHTTPServerTransport に直接置き換えられます。

決済ゲーティング。 POST /mcp は解析済みの JSON-RPC ボディを確認し、clean_page を指定した tools/call リクエストのみを決済ゲーティングの対象にします(src/index.ts)。health、list_capabilities、pricing、およびツール呼び出し以外のすべてのメソッド(initialize、tools/list など)は、そのまま処理されます。レート制限は適用されますが、料金はかかりません。これにより、エージェントが利用できる検出機能はすべて開放し、有料機能のうち 1 つだけをゲーティングできます。

決済確定のタイミング。 決済は抽出の実行前に検証されますが、オンチェーンでの確定(ブロードキャスト)は抽出が成功した後にのみ行われます。抽出に失敗した場合、エージェントの決済承認は破棄され、請求は発生しません。

秘密鍵は不要です。 Base 上の USDC は EIP-3009 メタトランザクションに対応しているため、リソースサーバーが秘密鍵を保持することはありません。PAYMENT_ADDRESS は公開ウォレットアドレスです。ファシリテーターが署名済みの承認をオンチェーンで送信し、ガス代を負担します。

抽出エンジン。 Firefox のリーダーモードの基盤となっている @mozilla/readability が、コンテンツ抽出の中核を担います。抽出は linkedom(Workers で動作する高速かつ依存関係の少ない DOM 実装。jsdom は動作しません)で構築された DOM に対して実行されます。Workers に対応し、かつ DOM ベースでもある既存の Markdown 変換ライブラリがないため、抽出されたフラグメントを Markdown に変換する処理には、小規模な手書きの HTML→Markdown ウォーカーを使用しています。抽出前後のヒューリスティックにより、よくある失敗要因であるペイウォールのマーカー、ボットチェックのページ、JavaScript のみで構成された空のページを検出し、品質の低い出力ではなく型付きエラーを返します。

任意の LLM による拡張。 structured_facts が設定されるのは、呼び出し元が options.extract_facts: true を渡し、かつ ENABLE_LLM_ENRICHMENT=true と ANTHROPIC_API_KEY が設定されている場合のみです。これはクリティカルパスには含まれません。拡張処理の呼び出しが失敗した場合や無効になっている場合でも、clean_page は structured_facts が空の配列である完全な結果を返し、理由を説明する注記を付けます。この機能の使用に追加料金はかかりません。

レート制限と分析。 どちらも 1 つの KV 名前空間で実装されています。無料プランの呼び出しにはクライアント IP ごとの固定 1 分間カウンターを使用し、呼び出し数/成功数/失敗数/収益については累積 JSON カウンターオブジェクトを使用します。これらの情報は GET /analytics で読み取り専用として公開されます。


必要なサービス/インフラストラクチャ

コンポーネント必要なもの入手先
ホスティングCloudflare Workers(Static Assets 対応)dash.cloudflare.com — まずは無料プランで利用できます
ドメイン+DNSCloudflare 経由でプロキシされるドメイン任意のレジストラーで取得し、Cloudflare に追加して Worker に向けます
ウォレットBase ウォレットアドレス(公開アドレスのみ)任意の EVM ウォレット — Coinbase Wallet、MetaMask など
x402 ファシリテーター決済の検証/確定https://x402.org/facilitator(テストネット向けのデフォルト)。メインネットでの本番運用には、Coinbase が運営するファシリテーター、またはセルフホストのファシリテーターを使用します
KV 名前空間レート制限+分析データの保存wrangler kv namespace create CLEANPAGE_KV
LLM(任意)構造化された事実の抽出Anthropic API キー。ENABLE_LLM_ENRICHMENT=true の場合のみ必要

データベースもキューも別のバックエンドも不要です。すべて 1 つの 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"}'
テストネットからメインネットへの移行
  1. wrangler.tomlでX402_NETWORKをbase-sepoliaからbaseに切り替えます。
  2. X402_FACILITATOR_URLをメインネットに対応したファシリテーターに切り替えます(選択したファシリテーターがBaseメインネットでの決済に対応していることを確認してください。このエコシステムはまだ発展途上で、選択肢は変化するため、現在のファシリテーターの選択肢を確認してください)。
  3. 再デプロイします。

環境変数

注釈付きの一覧については.env.exampleを参照してください。概要:

変数必須デフォルト用途
PAYMENT_ADDRESSはい—USDCを受け取るBaseウォレットアドレス
X402_NETWORKはいbase-sepoliabaseまたはbase-sepolia
X402_FACILITATOR_URLはいhttps://x402.org/facilitator検証/決済に使用するファシリテーター
CLEAN_PAGE_PRICE_USDはい0.02clean_page呼び出しが成功した場合の料金
PUBLIC_BASE_URLはい—デプロイ済みのURL。ディスカバリーファイルで使用します
FREE_RATE_LIMIT_PER_MINいいえ30IPごとの無料枠の1分あたりの呼び出し数
ENABLE_LLM_ENRICHMENTいいえtruestructured_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_FAILED2xx以外のレスポンス、HTML以外のコンテンツ、またはサイズ超過のページです場合によります
TIMEOUTタイムアウト時間内にページから応答がありませんでしたはい
PAYWALL_DETECTEDサブスクリプション制または従量制のペイウォールが検出されましたいいえ
BLOCKED_BY_SITEボットチェック/CAPTCHA、またはJavaScriptのみで表示される空のシェルですいいえ
EMPTY_CONTENT実質的な記事コンテンツが見つかりませんでしたいいえ
EXTRACTION_FAILED予期しないパーサーエラーですいいえ

抽出に失敗した場合は、必ず決済処理の前に返されるため、料金が請求されることはありません。


既知の制限事項

  • JavaScriptで描画されるページ:抽出では生のHTMLを取得し、JavaScriptは実行しません。そのため、サーバー側で描画されたコンテンツがない、クライアント側で描画されるSPAは、EMPTY_CONTENTまたはBLOCKED_BY_SITEを返します。トラフィックへの影響がある場合、ヘッドレスブラウザーによる描画のフォールバック(Cloudflare Browser Renderingなど)を追加するのが自然な次のステップです。
  • ファシリテーターへの依存:決済の検証と決済処理は、設定されたx402ファシリテーターの稼働状況に依存します。開発環境ではx402.org/facilitatorが適したデフォルトですが、メインネットの利用量を増やす前に、本番環境向けファシリテーターの信頼性保証を評価してください。
  • レート制限はベストエフォートです:KVベースのカウンターには、同じIPから同時に大量のリクエストが発生した場合に、小さな競合ウィンドウがあります。これは十分な不正利用対策ですが、確実な保証ではありません。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。