Building MCP Server on Cloudflare
Build remote Model Context Protocol (MCP) servers on Cloudflare Workers with tools, OAuth authentication, and production deployment.
npx degit LangbaseInc/agent-skills/building-mcp-server-on-cloudflare my-mcp-cloudflare
Deploy MCP servers to Cloudflare's global edge network for low-latency, scalable LLM tool integration.
- Global Edge - Deploy to 300+ locations worldwide
- Zero Cold Starts - Instant execution
- Auto-scaling - Handle any load
- Low Cost - 100k requests/day free
- KV/D1/R2 - Built-in storage options
- OAuth - Easy authentication
Claude/LLM → MCP Client → Cloudflare Worker (MCP Server)
↓
[KV, D1, R2, APIs]
Tools
Expose functions to LLMs:
server.tool({
name: 'get_weather',
description: 'Get weather for a city',
parameters: {
city: { type: 'string' }
},
handler: async ({ city }) => {
const weather = await fetchWeather(city);
return { weather };
}
});
Resources
Provide data access:
server.resource({
uri: 'file://data.json',
handler: async () => {
return await env.KV.get('data');
}
});
OAuth
Secure access:
const oauth = new OAuth({
clientId: env.CLIENT_ID,
clientSecret: env.CLIENT_SECRET,
});
1. Install Wrangler
npm install -g wrangler
2. Create Project
npm create cloudflare@latest my-mcp-server
cd my-mcp-server
3. Install MCP SDK
npm install @modelcontextprotocol/sdk
4. Develop Locally
wrangler dev
import { MCPServer } from '@modelcontextprotocol/sdk';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const server = new MCPServer({
name: 'my-mcp-server',
version: '1.0.0',
});
// Register tools
server.tool({
name: 'example',
description: 'Example tool',
handler: async (args) => {
// Tool logic here
return { result: 'success' };
},
});
return server.handleRequest(request);
},
};
KV (Key-Value)
await env.MY_KV.put('key', 'value');
const value = await env.MY_KV.get('key');
D1 (SQL Database)
const result = await env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(userId).all();
R2 (Object Storage)
await env.MY_BUCKET.put('file.txt', data);
const file = await env.MY_BUCKET.get('file.txt');
OAuth Flow
- User authorizes app
- Receive authorization code
- Exchange for access token
- Store in KV/D1
- Use token for API calls
1. Configure
# wrangler.toml
name = "my-mcp-server"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-id"
2. Deploy
wrangler deploy
3. Set Secrets
wrangler secret put CLIENT_SECRET
- Validate all inputs
- Handle errors gracefully
- Use TypeScript
- Implement rate limiting
- Cache responses
- Monitor usage
- Version your API
- Document tools
- API integration (Stripe, GitHub, etc.)
- Database queries
- File processing
- Data transformation
- External service calls
- Webhook handling
- Real-time data access
- Use KV for caching
- Batch database queries
- Minimize external calls
- Enable compression
- Use Workers Analytics