Deploy MCP Server to Cloudflare Workers: MCP at the Edge
Deploy MCP Server to Cloudflare Workers: stdio to Streamable HTTP conversion, Edge Runtime limits, KV persistence, wrangler config, and a production checklist.
How to
Evaluate stdio vs Streamable HTTP
Local-only → keep stdio; cross-network → switch to Streamable HTTP; deploying to Workers mandates Streamable HTTP.
Adapt the MCP Server entry point
Use @modelcontextprotocol/sdk's StreamableHTTPServerTransport instead of StdioServerTransport; entry point goes from process.stdin to a fetch handler.
Adapt to Edge Runtime
Code uses only fetch / crypto / streams / KV bindings; drop fs / child_process usage; long tasks via ctx.waitUntil.
Configure wrangler.jsonc
Set name / main / compatibility_date / compatibility_flags; configure kv_namespaces (D1 / R2 bindings); secrets via wrangler secret (separate).
Local wrangler dev
wrangler dev; MCP Host points to http://localhost:8787/sse; test tool list and invocations; hot-reload on code changes.
Deploy + monitor
wrangler deploy; Cloudflare dashboard for request logs + CPU usage; set alerts.
Cloudflare Workers is the ideal edge platform to deploy MCP Server on - low latency, pay-per-request, fast cold start. This article walks the full path.
1. Why Workers
Common options for deploying MCP Server:
| Platform | Latency | Cold start | Fit |
|---|---|---|---|
| Cloudflare Workers | Very low (200+ PoP) | < 50ms | Edge MCP, IO-bound |
| Vercel Functions | Medium (CDN) | Medium | Next.js stack |
| AWS Lambda | Medium | Medium | Complex backend |
| Self-hosted VPS | Depends | Depends | Full control |
Workers' edge: global latency + pay-per-request + KV/D1/R2 adjacent.
2. stdio vs Streamable HTTP
MCP has two transports:
- stdio: local process (Host spawns the server binary, communicates via stdin/stdout)
- Streamable HTTP: HTTP + SSE (Server exposes HTTP endpoint, Host calls via POST + GET-SSE)
Workers can only run Streamable HTTP - Workers is edge runtime, no stdin/stdout processes.
To convert, use @modelcontextprotocol/sdk's StreamableHTTPServerTransport instead of StdioServerTransport:
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined, // stateless
});
server.connect(transport);
// Workers fetch handler
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
return transport.handleRequest(request);
}
};
3. Edge Runtime limits
Workers Edge Runtime is not Node.js - the following are unavailable:
fs(filesystem)child_process(subprocess)setImmediate/process.nextTick- any Node.js built-in modules (except Web standards: fetch / crypto / streams / URL)
Code must:
- use only Web standard APIs (
fetch,crypto.subtle,TransformStream) - use Workers KV / D1 / R2 instead of local storage
- long-running tasks via
ctx.waitUntil(async) - cannot require Node packages; use esbuild-compatible packages (most modern SDKs work)
4. CPU time limits
| Plan | CPU time / request |
|---|---|
| Free | 5ms (wall time 10s) |
| Bundled | 5-50ms (per plan) |
| Unbound | 30s |
MCP tool calls are usually low CPU intensity (IO-bound) - 5ms suffices in most cases; complex compute (scraping + parsing) goes to Unbound.
5. KV persistence
Workers KV (edge key-value store) fits MCP scenarios:
// Read
const counter = await env.MCP_KV.get("rate_limit:user_123", { type: "json" });
// Write
await env.MCP_KV.put("rate_limit:user_123", JSON.stringify({ count: counter + 1 }));
KV properties:
- Eventual consistency (global convergence < 60s)
- Per-key value ≤ 25MB
- Suits rate limits / caches / prefs
Not for strong consistency (use D1 SQLite for that).
6. wrangler.jsonc config
{
"name": "my-mcp-server",
"main": "src/index.ts",
"compatibility_date": "2026-08-01",
"compatibility_flags": ["nodejs_compat"], // compatibility for some Node.js APIs
"vars": {
"LOG_LEVEL": "info"
},
"kv_namespaces": [
{ "binding": "MCP_KV", "id": "xxx" }
],
"secrets": [
"GITHUB_CLIENT_SECRET", // set via wrangler secret put
"API_KEY"
]
}
secrets don't go into git - use wrangler secret put GITHUB_CLIENT_SECRET to configure.
7. Deploy + monitor
# Local dev
wrangler dev
# Deploy
wrangler deploy
# Tail logs
wrangler tail
# Set secrets
wrangler secret put GITHUB_CLIENT_SECRET
Cloudflare dashboard provides:
- Request / error rate real-time monitoring
- CPU time usage (spot performance issues)
- KV read/write volume
Set alerts: 5xx rate > 5% sustained 5 minutes → trigger.
8. Practical gotchas
nodejs_compatflag: some Node.js packages (especially zod / pnpm packages) need this flag to run- Cold start: first request 50-100ms warm-up; the user's first MCP call is a bit slower
- Worker size limit: 1MB compressed; with SDK it's typically 200-400KB
- CORS: MCP Host (ChatGPT web) calls your Worker from a different origin; configure CORS to allow
*or ChatGPT's domain
9. What's Next
- Build Your Own MCP Server: From Zero to Published - full stdio MCP path
- Model Context Protocol: How MCP Works and How to Build on It - protocol deep dive
- OpenAI API Error Handling and Retry - production stability
Update log
- 2026-08-08: Initial publish
Key points
- Workers is the ideal edge platform for MCP - but only runs Streamable HTTP MCP, stdio needs a local process
- Edge Runtime has no Node.js APIs (fs / child_process unavailable) - use only fetch / crypto / streams
- CPU time is 5ms (free plan) / 30s (unbound plan) - long tasks must stream or offload
- KV for persistence (rate-limit state, user prefs) - eventual consistency but sufficient
- wrangler.jsonc configures secrets (OAuth client secret, API keys) + bindings (KV, D1, R2)
- Local dev with wrangler dev simulates Edge Runtime; deploy with wrangler deploy; CI with wrangler deploy --dry-run
Frequently asked questions
Official references
Related articles
MCP server development: protocol, debugging, security, and production deployment
MCP server production essentials: protocol deep-dive (JSON-RPC 2.0 / lifecycle / capabilities negotiation), Inspector debugging, transport selection (stdio / Streamable HTTP / SSE), security modes (prompt injection / OAuth scope / audit).
Read articleBuild Your Own MCP Server: From Zero to Published
Build and ship an MCP Server with @modelcontextprotocol/sdk: project setup, declaring tools, choosing stdio vs Streamable HTTP, local testing, OAuth, and a launch checklist.
Read articleModel Context Protocol: how MCP works and how to build on it
What MCP is, how it standardizes tool calling for LLMs, and how to build an MCP server that exposes your data or APIs to ChatGPT, Claude, and Cursor.
Read articleSubscribe to GPTMap Weekly
One email every Monday: curated OpenAI updates, deep dives, and best practices. No ads, unsubscribe anytime.