Zero-Cost Guide to Deploying MCP Servers on Cloudflare Workers

Move MCP servers to remote on Cloudflare Workers for a shared URL and centralized keys.
The article tackles three pain points of local MCP servers in team settings—inconsistent environments, scattered keys, and cloud agents that can't call in—by hosting a remote MCP server on Cloudflare Workers. Using a notes service example, it covers project setup, wrangler config, tools with Zod validation, bearer auth, MCP Inspector testing, curl smoke checks, and client integration, while flagging pitfalls like new_sqlite_classes, the dual Accept header, and KV read quotas.
Locally-run MCP servers are becoming a bottleneck for team collaboration: every machine needs Node installed, environment variables configured, API keys scattered across each person's config files, and cloud-based agents simply can't call processes running on your laptop. Moving MCP servers to Cloudflare Workers and exposing them via the Streamable HTTP protocol with a unified URL may be the most hassle-free solution available today.
Why Move MCP Servers to Remote
Most MCP tutorials teach the local mode: clients like Claude Desktop, Cursor, and VS Code spawn a process and communicate over stdin/stdout. That's fine for one person, but the moment you share across a team, three pain points emerge.
- Inconsistent environments: different Node versions, missing env variables, a unique setup for every person.
- Scattered keys: database or third-party API keys get copied into everyone's local config files.
- Cloud clients can't call in: agents running in the cloud simply can't spawn processes on your machine.
Remote MCP uses Streamable HTTP transport (introduced in the MCP spec version 2025-03-26, replacing the old HTTP+SSE approach). Clients only need a URL and a token; keys stay on the server side. To update, you redeploy once and the whole team automatically uses the new version.
Cloudflare Workers fits this scenario for straightforward reasons: the free tier offers 100,000 requests per day, cold starts are near zero, and SQLite-backed Durable Objects are now part of the free plan. Each MCP session's state lives in its own dedicated Durable Object.
MCP (Model Context Protocol) is a standard protocol proposed and open-sourced by Anthropic, designed to let AI applications (clients like Claude Desktop, Cursor, and VS Code) connect to external tools and data sources in a unified way. Its core value lies in abstracting "what the model can call" out of each vendor's proprietary plugin mechanism, forming an ecosystem where clients and servers are decoupled: a server only needs to declare which tools, resources, and prompts it provides, and any MCP-compatible client can connect. In local mode, MCP servers run as child processes that exchange JSON-RPC messages over stdin/stdout; in remote mode, the transport layer is swapped for HTTP, allowing the server to be deployed in the cloud and shared by multiple parties. Understanding this client/server separation is the premise for understanding why this article "moves house."
Streamable HTTP is the transport method introduced in the MCP spec version 2025-03-26 to replace the earlier HTTP+SSE approach. The old scheme required clients to first establish a long-lived SSE channel to receive server pushes, then use a separate POST endpoint to send requests, with session correlation maintained across two channels—prone to disconnections in serverless environments and behind intermediary proxies. Streamable HTTP merges both into a single endpoint: the client POSTs JSON-RPC messages to the same URL, and the server can return JSON directly or switch the response body to an SSE stream when streaming push is needed. This "upgrade to stream on demand" model is friendlier to stateless edge runtimes like Cloudflare Workers, and simplifies client configuration to a single URL plus an auth header.
Setting Up the Project Skeleton in Five Minutes
The author uses wrangler 4.x, Cloudflare's agents package, and the official @modelcontextprotocol/sdk, requiring Node 20 or above.
npm create cloudflare@latest mcp-notes -- --type=hello-world --lang=ts
cd mcp-notes
npm install agents @modelcontextprotocol/sdk zod
npx wrangler kv namespace create NOTES
npx wrangler secret put MCP_TOKEN
Next, declare the Durable Object and KV bindings in wrangler.jsonc. Here's a high-frequency pitfall: the free plan must use new_sqlite_classes—if you write the old-style new_classes, deployment will fail outright.
Implementing Tools, Input Validation, and Authentication
The server does just two things: save_note writes a note to KV, and search_notes retrieves notes by keyword. The core class extends McpAgent and registers tools in init().
A few key points learned from real-world practice:
- Constrain all inputs with Zod (e.g.,
max(5000),min(2)). LLMs occasionally stuff in tens of KB of text; with a schema you can block it at the entrance and avoid polluting KV. - Tool descriptions are prompts. The model relies on the description to decide whether to call—writing clearly what it does matters more than writing at length.
- Limit the number of returned items (10 in the example). Returning too much text eats the context window, and you're the one paying the token bill.
- A static bearer token is sufficient for internal tools. If you need to expose it publicly, switch to
@cloudflare/workers-oauth-providerfor OAuth.
Authentication logic goes in the Worker's fetch entry: compare the Authorization header against env.MCP_TOKEN, and on success hand the /mcp path to NotesMCP.serve("/mcp"), returning 404 for everything else.
Durable Objects are the stateful compute primitive on the Cloudflare Workers platform: each object instance has a unique ID and private persistent storage, and the platform guarantees that requests for the same ID are always routed to the same instance, providing strongly consistent session state. This is crucial for MCP—remote servers need to remember context like capability negotiation and subscription relationships from when a session was initialized, whereas ordinary Workers are stateless and run across multiple nodes worldwide. Early Durable Objects only supported key-value storage and required payment; later, built-in SQLite storage was added (the type declared by new_sqlite_classes), allowing SQL queries directly via this.sql, and it was included in the free plan. This article leverages exactly that, switching keyword search from reading KV entries one by one to a SQL LIKE query.
Testing, Deployment, and Client Integration
First run npx wrangler dev locally (defaults to http://localhost:8787), then open another terminal and start npx @modelcontextprotocol/inspector. Select Streamable HTTP as the transport, enter http://localhost:8787/mcp as the URL, add the Authorization header, and test each tool one by one. Once confirmed, run wrangler deploy, then send an initialize via curl as a smoke test.
The curl step has a detail that can trip you up for half a day: the Accept header must include both application/json and text/event-stream. Omit the latter and the server returns 406, without the error message telling you that's the reason.
If a client only supports stdio (such as some older versions of Claude Desktop), you can bridge with mcp-remote:
npx mcp-remote https://.../mcp --header "Authorization: Bearer ${TOKEN}"
The Real Boundaries of Cost and Quotas
The author's team of 6 handles a few thousand requests per day and is still within the free tier. What really needs watching is KV read counts—the free plan allows 100,000 reads per day. The loop in search_notes above that calls get for each entry is quite read-intensive; when notes grew to several thousand, the author switched to SQLite inside the Durable Object (this.sql), replacing iteration with a LIKE query.
mcp-remote is a community-maintained bridging tool whose purpose is to translate protocols between MCP clients that only support stdio transport and remote Streamable HTTP servers: it's spawned by the client as a local child process, appearing to the client as a standard stdio server, while internally making HTTP requests to the remote URL and forwarding messages. The --header parameter attaches auth headers so the remote server can verify the bearer token. This path lets older clients that don't yet support remote transport connect to remote servers, at the cost of an extra local process and some startup latency. Once a client natively supports Streamable HTTP, you can drop this bridge and just enter the URL.
A Few Practices Worth Copying
- Start with 1–2 genuinely useful tools (internal queries, reading logs)—don't wrap an entire API right out of the gate.
- Always use
new_sqlite_classesin migrations, or the free plan won't run. - Validate inputs with Zod and limit output size—you're saving your own tokens.
- Add auth from day one: store the bearer token with
wrangler secret, upgrade to OAuth if you need to go public. - Test with MCP Inspector before connecting real clients—and don't forget that dual-value
Acceptheader. - Watch KV/DO quotas in the dashboard; if reads climb fast, migrate search to SQLite.
By the author's estimate, building the first version takes just an afternoon. For developers who want to turn AI tools from personal toys into team infrastructure, the barrier on this path is now low enough to be worth trying right away.
One-line Summary
Move MCP servers to remote on Cloudflare Workers, letting teams share a unified URL and centralized keys.
Paragraph Summary
The article addresses the three major pain points local MCP servers expose in team collaboration—inconsistent environments, scattered keys, and cloud agents being unable to call in—by proposing a solution that hosts remote MCP servers on Cloudflare Workers. Using a notes service as an example, it walks through the entire process: project initialization, wrangler configuration, tool implementation with Zod input validation, bearer token authentication, MCP Inspector testing, curl smoke verification, and client integration. It highlights several common pitfalls: the free plan must use new_sqlite_classes, curl's Accept header must include both JSON and SSE, and per-entry KV reads will hit quota limits. The author estimates the first version can be completed in an afternoon and offers six practices you can adopt directly.
Related articles

Chain of Thought Isn't Just for AI: How Humans Can Use CoT to Improve Thinking Quality
Chain of Thought isn't just a prompt trick for large models. Starting from a Hacker News discussion, this article analyzes why CoT works for human thinking too, breaks down actionable ways to transfer it, and highlights the key differences between human CoT and machine CoT.
Cloudflare Teams Up with OpenAI: Closi…
Cloudflare Teams Up with OpenAI: Closing the Loop from Vulnerability Discovery to Defense with AI
Cloudflare uses OpenAI Daybreak to investigate security vulnerabilities and generate reviewable remediation plans, while developers use Codex to boost coding efficiency and quality.

Orca Multi-Agent Orchestration in Practice: A Guide to Parallel Collaboration with Claude and Codex
Orca is Stable AI's free open-source agent workbench supporting 34 agents like Claude Code and Codex in parallel. Learn its Git worktree isolation, multi-model orchestration, and mobile management.