Deploy your FastMCP server to Cloudflare Workers for ultra-low latency worldwide. The edge runtime allows your MCP server to run close to your users with automatic global distribution.
EdgeFastMCP vs FastMCP
Cloudflare Workers requires the edge-compatible EdgeFastMCP class:
Feature FastMCP EdgeFastMCP Runtime Node.js Edge (V8 isolates) Start method server.start({ port })export default serverTransport stdio, httpStream, SSE HTTP Streamable only Sessions Stateful or stateless Stateless only File system Yes No OAuth/Authentication Built-in authenticate option Use Hono middleware (built-in planned) Custom routes server.getApp()server.getApp()
EdgeFastMCP is optimized for stateless edge environments with no filesystem access . Use fetch APIs for external data.
Step-by-Step Deployment
Install Dependencies
Install FastMCP and Zod in your Cloudflare Workers project:
Create Your MCP Server
Create src/index.ts with the EdgeFastMCP import: import { EdgeFastMCP } from "fastmcp/edge" ;
import { z } from "zod" ;
const server = new EdgeFastMCP ({
name: "My Edge Server" ,
version: "1.0.0" ,
description: "MCP server running on Cloudflare Workers" ,
});
// Add tools, resources, prompts as usual
server . addTool ({
name: "greet" ,
description: "Greet someone" ,
parameters: z . object ({
name: z . string (),
}),
execute : async ({ name }) => {
return `Hello, ${ name } ! Served from the edge.` ;
},
});
// Export the server as default (required for Cloudflare Workers)
export default server ;
The export default server statement is required for Cloudflare Workers to recognize your handler.
Configure wrangler.toml
Create a wrangler.toml configuration file: name = "my-mcp-server"
main = "src/index.ts"
compatibility_date = "2024-01-01"
Basic Configuration
With Environment Variables
With Custom Domain
name = "my-mcp-server"
main = "src/index.ts"
compatibility_date = "2024-01-01"
Deploy to Cloudflare
Deploy your MCP server with a single command: Your server will be available at:
MCP endpoint: https://my-mcp-server.workers.dev/mcp
Health check: https://my-mcp-server.workers.dev/health
Complete Example
Here’s a full example based on src/examples/edge-cloudflare-worker.ts:
import { EdgeFastMCP } from "fastmcp/edge" ;
import { z } from "zod" ;
const server = new EdgeFastMCP ({
description: "An MCP server running on Cloudflare Workers" ,
name: "CloudflareWorkerMCP" ,
version: "1.0.0" ,
});
// Simple tool
server . addTool ({
name: "greet" ,
description: "Greet someone by name" ,
parameters: z . object ({
name: z . string (). describe ( "The name to greet" ),
}),
execute : async ({ name }) => {
return `Hello, ${ name } ! This response is from a Cloudflare Worker.` ;
},
});
// Tool with structured content
server . addTool ({
name: "get_weather" ,
description: "Get weather information for a location" ,
parameters: z . object ({
location: z . string (). describe ( "The city or location" ),
}),
execute : async ({ location }) => {
// Call external API using fetch
return {
content: [
{
type: "text" ,
text: `Weather for ${ location } : \n - Temperature: 72°F \n - Conditions: Sunny \n - Humidity: 45%` ,
},
],
};
},
});
// Static resource
server . addResource ({
uri: "info://server" ,
name: "Server Info" ,
description: "Information about this MCP server" ,
mimeType: "text/plain" ,
load : async () => {
return "This is a FastMCP server running on Cloudflare Workers edge runtime." ;
},
});
// Prompt template
server . addPrompt ({
name: "analyze_code" ,
description: "Generate a prompt to analyze code" ,
arguments: [
{ name: "language" , description: "Programming language" , required: true },
{ name: "focus" , description: "What to focus on (optional)" , required: false },
],
load : async ( args ) => {
const focus = args . focus ? ` focusing on ${ args . focus } ` : "" ;
return {
messages: [
{
role: "user" ,
content: {
type: "text" ,
text: `Please analyze the following ${ args . language } code ${ focus } :` ,
},
},
],
};
},
});
export default server ;
Adding Custom Routes
Access the underlying Hono app to add custom HTTP endpoints:
const app = server . getApp ();
// Add a landing page
app . get ( "/" , ( c ) => c . html ( "<h1>Welcome to my MCP server</h1>" ));
// Add REST API endpoints
app . get ( "/api/status" , ( c ) => c . json ({ status: "ok" , edge: true }));
// Handle POST requests
app . post ( "/api/data" , async ( c ) => {
const body = await c . req . json ();
return c . json ({ received: body });
});
export default server ;
Environment Variables and Secrets
Add Environment Variables
Define variables in wrangler.toml: [ vars ]
API_ENDPOINT = "https://api.example.com"
CACHE_TTL = "3600"
Add Secrets
Use wrangler CLI for sensitive data: npx wrangler secret put API_KEY
npx wrangler secret put DATABASE_URL
Access in Code
TypeScript doesn’t have direct access to env in EdgeFastMCP. Use Hono middleware: const app = server . getApp ();
app . use ( "*" , async ( c , next ) => {
// Access environment variables
const apiKey = c . env . API_KEY ;
await next ();
});
Never commit secrets to wrangler.toml. Always use wrangler secret put for sensitive values.
Edge Runtime Limitations
When running on Cloudflare Workers, be aware of these constraints:
No filesystem access : Use KV, R2, or fetch APIs instead
Stateless by default : Each request is handled independently
V8 isolates : Limited to JavaScript/TypeScript runtime
CPU time limits : Maximum 50ms CPU time on free tier, 30s on paid
Memory limits : 128MB per request
No long-running connections : Use Durable Objects for websockets
Testing Locally
Test your worker locally before deploying:
# Start local development server
npx wrangler dev
# Test the MCP endpoint
curl -X POST http://localhost:8787/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}'
# Test health check
curl http://localhost:8787/health
Monitoring and Logs
View logs and analytics in the Cloudflare dashboard:
# Stream logs in real-time
npx wrangler tail
# View metrics
npx wrangler metrics
Next Steps