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/LLMMCP ClientCloudflare 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

  1. User authorizes app
  2. Receive authorization code
  3. Exchange for access token
  4. Store in KV/D1
  5. 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