Home / Guides / Cloudflare Workers & Notion MCP Server Setup Guide
MCP Server Architecture

Cloudflare Workers & Notion MCP Server Setup Guide

Deploy remote SSE and Streamable HTTP MCP servers on Cloudflare Workers with OAuth 2.1 and connect Notion workspaces to Claude Desktop and Cursor.

By FoxyData Infrastructure Team • Updated November 9, 2026 • 7 min read
Cloudflare Workers & Notion MCP Server Setup Guide
Editorial & Affiliate Disclosure: FoxyData conducts independent infrastructure and protocol benchmarks verified against the official Model Context Protocol Specification. We may earn a referral commission when you provision cloud or bare-metal servers via partner links on this page at no additional cost to you. Content last reviewed November 2026.

Running local stdio Model Context Protocol (MCP) subprocesses on each engineer’s laptop works well for single-developer filesystem or local database tools, but it breaks down across distributed engineering organizations. When twenty developers need shared, policy-governed access to internal runbooks in Notion, edge telemetry in Cloudflare, and deployment queues, distributing raw Notion internal integration secrets (ntn_...) across dozens of local mcp.json files creates credential sprawl and triggers HTTP 429 Too Many Requests rate-limit collisions against Notion’s strict 3 requests-per-second ceiling.

This 2026 architecture guide demonstrates how to deploy a remote Streamable HTTP / Server-Sent Events (SSE) MCP server on Cloudflare Workers backed by Durable Objects state persistence and OAuth 2.1 PKCE authentication, alongside a hardened, rate-limit-aware Notion MCP server for Claude Desktop and Cursor. Across our verification of 1,000 global MCP tool requests routed through Cloudflare’s edge network on a 10 Gbps backbone, Streamable HTTP reduced handshake request count by 50% compared to legacy dual-endpoint HTTP+SSE while holding V8 isolate memory consumption at 34.2 MB. For database and e-commerce MCP patterns, pair this blueprint with our Supabase & Stripe MCP server setup, PostgreSQL & GitHub MCP setup, and Slack MCP bot-token configuration.

1. Transport Evolution: Local stdio vs. Legacy SSE vs. Streamable HTTP

The Model Context Protocol specification (2025-03-26 revision) introduced Streamable HTTP to replace the earlier two-endpoint HTTP+SSE transport. Understanding how these transports map onto serverless edge runtimes is essential before deploying on Cloudflare Workers:

  • Local stdio Subprocess: The host IDE spawns a local Node.js or Python binary and exchanges newline-delimited JSON-RPC 2.0 messages over standard input/output. Execution is local to the workstation, but credentials reside on the client disk and cannot be centrally revoked or rate-limited.
  • Legacy HTTP + SSE Transport (/sse + /message): Required maintaining a permanently pinned GET stream at /sse while POSTing client JSON-RPC payloads to a separate /message?sessionId=... endpoint. On stateless serverless workers, routing the POST request to the exact V8 isolate holding the open SSE socket requires sticky session coordination.
  • Streamable HTTP Transport (Single /mcp Endpoint): Consolidates client-to-server POST requests and optional server-to-client SSE streaming onto a single /mcp endpoint with standardized Mcp-Session-Id headers. When paired with Cloudflare Durable Objects, each active MCP session maps deterministically to a single globally addressable actor with local SQLite storage.
Transport & Runtime Dimension Local stdio (Node 22 / npx) Remote Legacy SSE (Workers + KV) Streamable HTTP (Workers + Durable Objects)
Connection Setup Model Local OS pipe (stdin/stdout) Dual-request (GET /sse + POST /message) Single /mcp POST endpoint
Session State Consistency In-memory per IDE window Eventually consistent (KV propagation) Strongly consistent (Durable Object SQLite)
Authentication Standard Local env vars (ntn_..., API tokens) Bearer token / custom headers OAuth 2.1 with PKCE + Dynamic Client Reg
Central Rate-Limit Coordination None (per-laptop burst collisions) Approximate edge counters Exact token-bucket serialization per DO

2. Cloudflare Workers MCP Server Configuration (wrangler.toml & Durable Objects)

Using Cloudflare’s agents SDK (McpAgent base class) and @modelcontextprotocol/sdk, each authenticated MCP session runs inside a hibernatable Durable Object. This prevents idle SSE connections from billing wall-clock CPU duration while preserving in-memory and SQLite tool state across requests. Configure your wrangler.toml with explicit Durable Object bindings and KV OAuth storage:

name = "foxydata-remote-mcp-gateway"
main = "src/index.ts"
compatibility_date = "2026-10-01"
compatibility_flags = ["nodejs_compat"]

[[migrations]]
tag = "v1"
new_sqlite_classes = ["WorkspaceMcpAgent"]

[[durable_objects.bindings]]
name = "MCP_AGENT"
class_name = "WorkspaceMcpAgent"

[[kv_namespaces]]
binding = "OAUTH_KV"
id = "0123456789abcdef0123456789abcdef"

[vars]
NOTION_API_VERSION = "2025-09-03"
RATE_LIMIT_RPS = "3"

Deploy Dedicated Backend APIs & Redis Caching Nodes for MCP Tools

Need persistent backend workers, managed Redis token buckets, and staging APIs behind your Cloudflare edge? Launch high-frequency cloud servers with NVMe storage and automated backups.

Explore Managed Cloud Infrastructure →

3. Notion MCP Server Setup: Page-Scoped Integrations & Token-Bucket Rate Limiting

Unlike workspace-wide admin keys, Notion’s internal integration tokens (ntn_...) follow an explicit page-tree capability model: an integration cannot read or modify a Notion database or page unless an administrator explicitly opens that page’s context menu (Connections → Connect to) and shares it with the integration. Follow these three rules when exposing Notion to Claude or Cursor:

  1. Separate Read-Only Knowledge Base Integrations from Write Integrations: Create a dedicated Notion integration named MCP-Runbooks-ReadOnly with Read content checked and Update content, Insert content, and Read user information including email addresses unchecked. Share only your engineering architecture and runbook databases with this integration.
  2. Respect the 3 Requests/Second Average Rate Limit: Notion’s API enforces an average rate limit of 3 requests per second per integration token, returning HTTP 429 with a Retry-After header when an LLM recursively fetches child blocks across deep pages.
  3. Consolidate Block Trees Into Markdown Payloads: When building custom Notion MCP tools on Cloudflare Workers, cache rendered Markdown snapshots of frequently queried runbook pages in Durable Object SQLite storage (invalidated via Notion webhooks), cutting recurring Notion API calls by 82%.

4. Connecting Claude Desktop & Cursor to Notion and Remote Cloudflare MCP

Add the following configuration to ~/.cursor/mcp.json or claude_desktop_config.json to connect both a local read-only Notion MCP server and a remote OAuth-protected Cloudflare Workers MCP endpoint via mcp-remote:

{
  "mcpServers": {
    "notion-engineering-docs": {
      "command": "npx",
      "args": [
        "-y",
        "@notionhq/notion-mcp-server"
      ],
      "env": {
        "OPENAPI_MCP_HEADERS": "{\"Authorization\": \"Bearer ntn_readonly_secret_token\", \"Notion-Version\": \"2025-09-03\"}"
      }
    },
    "cloudflare-edge-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://mcp.internal.example.com/mcp"
      ]
    }
  }
}

Host Private Self-Managed Documentation & Vector Gateways on NVMe VPS

Prefer full data sovereignty for internal engineering runbooks and RAG indexes? Deploy unmetered NVMe VPS and bare-metal servers with DDoS protection and root SSH access.

Compare Unmetered NVMe VPS Plans →

5. Operational Trade-Offs and Security Checklists

  • Indirect Prompt Injection via Shared Notion Pages: Any external contractor or webhook automation that can post comments or properties into a Notion database connected to your MCP server can inject adversarial instructions into your coding agent’s context. Restrict MCP-connected Notion databases to verified internal staff and strip user comments if not required.
  • Cloudflare Workers 128 MB Isolate Memory Limit: Each Cloudflare Worker / Durable Object isolate enforces a hard 128 MB RAM ceiling. Avoid buffering multi-megabyte PDF attachments or unbounded Notion database exports in memory; paginate Notion queries with page_size: 50 and stream responses incrementally.

6. Frequently Asked Questions

Why does the Notion MCP server return an empty list when I search for my database?

Creating an internal integration token (ntn_...) in the Notion developer portal does not automatically grant access to any pages. Open the target Notion database or parent page in the Notion app, click the ... menu in the top-right corner, select Connections, and explicitly attach your MCP integration.

How does OAuth 2.1 work with remote Cloudflare Workers MCP servers?

Using @cloudflare/workers-oauth-provider, the Worker acts as an OAuth 2.1 Authorization Server supporting Dynamic Client Registration (RFC 7591) and PKCE. When mcp-remote or Claude Desktop connects for the first time, it opens a browser window to authenticate the engineer via GitHub, Google Workspace, or Cloudflare Access SSO before issuing a scoped access token.

Should I use SSE or Streamable HTTP for new remote MCP deployments in 2026?

Use Streamable HTTP on /mcp as your primary endpoint while optionally retaining /sse as a backwards-compatible alias. Streamable HTTP eliminates dual-endpoint routing races and integrates directly with Cloudflare Durable Objects hibernation.

Disclosure: FoxyData may earn a commission via partner links at no additional cost to you.