Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
作者提供的说明(英文原文)
Turn any URL into clean, structured, agent-ready content. $0.02/call via x402 on Base.
这三项永远不会合并成一个分数:意见、测量和人气是不同的东西。
我们还没有为它写通俗的介绍。下面是我们从注册中心读取到的事实。
选择你使用的 AI 应用,然后复制设置。
你需要
你用的是哪个应用?
在上方选择你的应用。我们会记住它,下次按钮会显示“安装到 …”。
适用于网页版、桌面版和手机版 Claude:
https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp在终端中运行这条命令
claude mcp add --transport http cleanpage https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp粘贴到项目中的 .cursor/mcp.json,或 ~/.cursor/mcp.json
{
"mcpServers": {
"cleanpage": {
"url": "https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
粘贴到项目中的 .vscode/mcp.json
{
"servers": {
"cleanpage": {
"type": "http",
"url": "https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp"
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
ChatGPT 只能连接互联网上的服务器:
https://cleanpage-mcp.cleanpage-mcp.workers.dev/mcp菜单名称可能因套餐和版本不同而略有差异。
你的选择通过 Cookie 保存在这台设备上,无需账户。
这些设置是根据作者在注册中心的条目生成的。如果 README 的写法不同,请以 README 为准。
我们还没有读取这个服务器的工具列表;我们会轮流检查各个端点。
我们检查的是任何人都能看到的信息;我们没有阅读代码。不适用的检查项不计入总数。 · 检查于 2026年11月7日
注册名称已通过 GitHub 账户 IO31-WEB 验证,该账户拥有此仓库
我们还没有从 GitHub 读取这个仓库
我们还没有从 GitHub 读取这个仓库
尚未检查;我们会轮流检查各个端点
尚未检查;我们会轮流检查各个端点
尚未检查;我们会在检查端点时读取工具列表
与注册中心里这个分类中所有活跃的服务器比较。只有当发布者拥有该仓库时,星标数才计入。
它在 1 项适用的基础检查中通过了 1 项。我们没有阅读代码。在添加密钥或令牌之前,请先看看这个服务器要求哪些权限,并使用只具备所需权限的密钥。
注册中心没有列出必需的密钥,不过有些服务器会在首次使用时要求你登录。
它在作者的云端运行。通过互联网连接,无需安装,但你发送的内容会经过作者的服务器。
GitHub 仓库最后更新于–,最新版本(1.0.0)于2个月前进入注册中心。
支持 MCP 的应用,例如 Claude Desktop、Claude Code、Cursor 和 VS Code。它通过 URL 连接,所以接受远程 MCP 服务器的应用也可以使用,例如开启开发者模式的 ChatGPT。
同一分类中有:Spec Driven Development, Remote Desktop Commander, Detailing Manager
同一分类中其他作者的服务器,按星标数排序。
如何看卡片:★ GitHub 星标i三大支柱:评价 · 检查 · 使用情况i更新 = 最新版本发布到注册中心的时间i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Connect your auto detailing studio's tasks, cars, clients and revenue to Claude or ChatGPT.
按原文从作者的仓库复制。PopNx MCP 没有审查或背书其内容。HTML、图片和脚本已被移除。链接会离开本站。
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.
GET /.well-known/agent.json — machine-readable capability cardGET /.well-known/mcp.json — MCP connection + pricing manifestGET /llms.txt — plain-text summary for LLM crawlershealth, list_capabilities, pricing (all free)https:// /mcp over Streamable HTTP: {
"mcpServers": { "cleanpage": { "url": "https:// /mcp", "transport": "streamable-http" } } }
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).
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.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.
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 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.
| Component | What you need | Where to get it |
|---|---|---|
| Hosting | Cloudflare Workers (with Static Assets) | dash.cloudflare.com — free tier works to start |
| Domain + DNS | A domain proxied through Cloudflare | Any registrar; add to Cloudflare, point at the Worker |
| Wallet | A Base wallet address (public address only) | Any EVM wallet — Coinbase Wallet, MetaMask, etc. |
| x402 facilitator | Verifies/settles payments | https://x402.org/facilitator (testnet-friendly default); Coinbase-operated or self-hosted facilitators for mainnet production volume |
| KV namespace | Rate limiting + analytics storage | wrangler kv namespace create CLEANPAGE_KV |
| LLM (optional) | Structured fact extraction | Anthropic API key, only if ENABLE_LLM_ENRICHMENT=true |
No database, no queue, no separate backend — everything runs in the one Worker.
# 1. Install dependencies
npm install
npx wrangler kv namespace create CLEANPAGE_KV npx wrangler kv namespace create CLEANPAGE_KV --preview
npx wrangler secret put ANTHROPIC_API_KEY
npm run typecheck
npm run deploy
npm run dev
X402_NETWORK from base-sepolia to base in wrangler.toml.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).See .env.example for the full annotated list. Summary:
| Variable | Required | Default | Purpose |
|---|---|---|---|
PAYMENT_ADDRESS | yes | — | Base wallet address receiving USDC |
X402_NETWORK | yes | base-sepolia | base or base-sepolia |
X402_FACILITATOR_URL | yes | https://x402.org/facilitator | Facilitator used for verify/settle |
CLEAN_PAGE_PRICE_USD | yes | 0.02 | Price per successful clean_page call |
PUBLIC_BASE_URL | yes | — | Your deployed URL, used in discovery files |
FREE_RATE_LIMIT_PER_MIN | no | 30 | Free-tier calls per IP per minute |
ENABLE_LLM_ENRICHMENT | no | true | Enables structured_facts extraction |
LLM_MODEL | no | claude-haiku-4-5-20251001 | Model used for enrichment |
ANTHROPIC_API_KEY | only if enrichment enabled | — | Secret; set via wrangler secret put |
{
"mcpServers": { "cleanpage": { "url": "https://cleanpage.yourdomain.com/mcp", "transport": "streamable-http" } } }
Request:
{
"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:
{
"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 | Meaning | Retryable |
|---|---|---|
INVALID_URL | Malformed, non-http(s), or a blocked internal address | no |
FETCH_FAILED | Non-2xx response, non-HTML content, or oversized page | sometimes |
TIMEOUT | Page didn't respond within the timeout | yes |
PAYWALL_DETECTED | Subscription/metered paywall detected | no |
BLOCKED_BY_SITE | Bot-check/CAPTCHA or JS-only empty shell | no |
EMPTY_CONTENT | No substantial article content found |
只显示了开头部分;其余内容请在仓库中阅读