NanoParse
Blog

The MCP Server Deep Dive: How One Command Gives Your Agent the Entire Web

· NanoParse team

Yesterday we defined what "agent-native" means. Today we go under the hood of the bridge that makes it real: the NanoParse MCP server.

What Makes MCP Different

MCP — the Model Context Protocol — is not just another API. It's a standard for how AI agents discover and use tools. Think of it as USB-C for agent capabilities: one protocol, one connector, and the agent gains a new sense.

Before MCP, every tool integration was bespoke. You'd write a custom function for web search, another for file access, another for a database query. Each with its own auth, its own error handling, its own shape. MCP standardizes this: every tool advertises itself the same way, every agent discovers tools the same way, and every invocation follows the same JSON-RPC 2.0 contract.

NanoParse plugs into this standard with a single config block:

{
  "mcpServers": {
    "nanoparse": {
      "url": "https://nanoparse.app/mcp"
    }
  }
}

That's it. Your agent can now read any URL on the web. No API key. No signup form.

The Protocol: What Actually Happens

When an MCP client (like Claude Code or Cursor) connects to the NanoParse MCP server, three things happen in sequence:

1. Initialize

The client sends an initialize request. The server responds with its capabilities:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "nanoparse-mcp",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": {}
    }
  }
}

2. Discover Tools

The client calls tools/list. The server advertises exactly one tool:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "nanoparse_fetch",
        "description": "Fetch a URL and return clean markdown...",
        "inputSchema": {
          "type": "object",
          "properties": {
            "url": { "type": "string" },
            "debug": { "type": "boolean" }
          },
          "required": ["url"]
        }
      }
    ]
  }
}

One tool. One purpose. The agent now knows: "I can call nanoparse_fetch with a URL and get back clean markdown."

3. Invoke

The agent calls tools/call:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "nanoparse_fetch",
    "arguments": {
      "url": "https://react.dev/learn"
    }
  }
}

The server validates the URL, sends it to the NanoParse Worker, and the result comes back as clean markdown:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [{
      "type": "text",
      "text": "# React\n\nThe library for web and native..."
    }]
  }
}

The Architecture Under the Hood

The MCP server itself is thin — it's a protocol adapter. The real work happens in the Cloudflare Worker pipeline:

Agent → MCP Client → POST https://nanoparse.app/mcp
                                              ↓
                                       Queue Consumer
                                              ↓
                                  Puppeteer (Browser Rendering)
                                              ↓
                                     Content Extraction
                                              ↓
                                    Markdown → R2 storage
                                              ↓
                                 Poll /status → Return to agent

Why This Architecture?

Browser rendering at the edge. Cloudflare Browser Rendering gives us a real Chromium instance per request. JavaScript executes. React hydrates. SPAs render. What your agent gets is what a human would see — not an empty <div id="root">.

Queue-based isolation. Browser rendering is expensive (500ms–5s per page). The queue consumer pattern decouples request acceptance from content processing. This keeps the MCP endpoint responsive and avoids browser-pool exhaustion.

Content extraction pipeline. Raw HTML is not useful to an agent. Our extraction pipeline:

  1. Strips noise: nav, footer, sidebar, ads, cookie banners, social widgets
  2. Identifies the main content: <article>, <main>, or body heuristics
  3. Converts to GFM-compliant markdown: headings, lists, links, and — critically — tables
  4. Post-processes: drops lines with <40% printable characters, collapses consecutive blank lines

One-hour cache with auto-expiry. Results are stored in R2 with a 1-hour TTL. The /status endpoint deletes on retrieval. If a result is never retrieved, it auto-expires. No permanent storage of fetched content.

x402: How the Agent Pays

This is where the "agent-native" property gets real. The MCP server handles payments without a human in the loop:

  1. Free tier check: First 10 MCP calls are free. After that, the Worker returns HTTP 402 Payment Required.
  2. Agent pays: The MCP client detects the 402, constructs an x402 transaction (EIP-191 signed message for USDC on Base), and resubmits with a Payment-Signature header.
  3. Settlement: The Worker verifies the signature via the x402 facilitator, credits the merchant wallet, and enqueues the job.
  4. Idempotency: Payment signatures include a nonce-based KV lock to prevent double-charge race conditions.

The agent never touches a credit card form. It never sees a CAPTCHA. It signs a cryptographic proof of payment, and the web opens up.

// What the MCP client does under the hood:
const payment = await signPayment({
  to: "0x57a1d06873db575baeae1f6af30862a75c7bd570",
  amount: "0.0174",  // USD, settled in USDC
  network: "base",
});

const response = await fetch("https://nanoparse.app/mcp", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Payment-Signature": payment.signature,
  },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "tools/call",
    params: {
      name: "nanoparse_fetch",
      arguments: { url: "https://example.com" },
    },
  }),
});

Integration: Claude Code, Cursor, and Beyond

Claude Code

Add to your Claude Code MCP config (~/.claude/claude_desktop_config.json or project .mcp.json):

{
  "mcpServers": {
    "nanoparse": {
      "url": "https://nanoparse.app/mcp"
    }
  }
}

Restart Claude Code. Your agent now has a nanoparse_fetch tool.

Cursor

Cursor's MCP support works the same way. Add the server config, and nanoparse_fetch appears in your agent's tool palette.

Any MCP-compatible client

The MCP protocol is open. If your agent framework speaks MCP, it speaks NanoParse. The server runs remotely on Cloudflare's edge at nanoparse.app/mcp — nothing to install, nothing to run. Source: github.com/NanoParse/nanoparse-mcp.

Building Your Own vs. Using NanoParse MCP

Let's be honest about what you'd need to replicate this:

ComponentDIY CostNanoParse MCP
Browser renderingHeadless Chrome: $20-50/month + opsIncluded
Content extractionReadability + Turndown: breaks on SPAsProduction-tested pipeline
GFM table preservationWeeks of debugging edge casesSolved
Anti-bot handlingIP rotation, UA management, evasionCloudflare edge network
Payment integrationStripe, billing UI, invoicesx402 — agent-native, zero setup
Queue managementRedis, workers, retry/backoffCloudflare Queues
SSRF protectionDNS rebinding, encoded-IP detection14 payload classes blocked

You could build all of this. It would take weeks. It would cost more to run than NanoParse costs to use. And when it breaks at 2 AM, you're the ops team.

Or: point your MCP client at nanoparse.app/mcp and your agent can read the web.

What's Next for the MCP Server

Every feature will honor the core principle: agents should be able to discover, pay for, and use web infrastructure without a human ever touching a keyboard.

Try It

{
  "mcpServers": {
    "nanoparse": {
      "url": "https://nanoparse.app/mcp"
    }
  }
}

One config block. Your agent's universe just got a lot bigger.


Tomorrow: "x402: How Software Pays for Software" — the payment protocol that makes agent-native commerce possible.