Skip to main content

building-mcp-server-on-cloudflare

Builds remote MCP (Model Context Protocol) servers on Cloudflare Workers with tools, OAuth authentication, and production deployment.

Source facts

Repository
GrayCodeAI/starling
Last source activity
July 13, 2026 at 09:28
Detected SKILL.md language
English
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
4 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
building-mcp-server-on-cloudflare
description
Builds remote MCP (Model Context Protocol) servers on Cloudflare Workers with tools, OAuth authentication, and production deployment.
license
MIT
tags
["mcp","cloudflare","workers","oauth","model-context-protocol"]
domain
devops
subdomain
cloudflare
version
1
author
CommandCodeAI (ported)
date_added
2026-05-14T00:00:00.000Z
# Building MCP Servers on Cloudflare Creates production-ready Model Context Protocol servers on Cloudflare Workers with tools, authentication, and deployment. ## When to Use - User wants to build a remote MCP server - User needs to expose tools via MCP - User asks about MCP authentication or OAuth - User wants to deploy MCP to Cloudflare Workers ## Prerequisites - Cloudflare account with Workers enabled - Node.js 18+ and npm/pnpm/yarn - Wrangler CLI (`npm install -g wrangler`) ## Quick Start ### Option 1: Public Server (No Auth) ```bash npm create cloudflare@latest -- my-mcp-server \ --template=cloudflare/ai/demos/remote-mcp-authless cd my-mcp-server npm start ``` Server runs at `http://localhost:8788/mcp` ### Option 2: Authenticated Server (OAuth) ```bash npm create cloudflare@latest -- my-mcp-server \ --template=cloudflare/ai/demos/remote-mcp-github-oauth cd my-mcp-server ``` Requires OAuth app setup. See [references/oauth-setup.md](references/oauth-setup.md). ## Core Workflow ### Step 1: Define Tools Tools are functions MCP clients can call. Define them using `server.tool()`: ```typescript import { McpAgent } from "agents/mcp"; import { z } from "zod"; export class MyMCP extends McpAgent { server = new Server({ name: "my-mcp", version: "1.0.0" }); async init() { // Simple tool with parameters this.server.tool( "add", { a: z.number(), b: z.number() }, async ({ a, b }) => ({ content: [{ type: "text", text: String(a + b) }], }) ); // Tool that calls external API this.server.tool( "get_weather", { city: z.string() }, async ({ city }) => { const response = await fetch(`https://api.weather.com/${city}`); const data = await response.json(); return { content: [{ type: "text", text: JSON.stringify(data) }], }; } ); } } ``` ### Step 2: Configure Entry Point **Public server** (`src/index.ts`): ```typescript import { MyMCP } from "./mcp"; export default { fetch(request: Request, env: Env, ctx: ExecutionContext) { const url = new URL(request.url); if (url.pathname === "/mcp") { return MyMCP.serveSSE("/mcp").fetch(request, env, ctx); } return new Response("MCP Server", { status: 200 }); }, }; export { MyMCP }; ``` **Authenticated server** -- See [references/oauth-setup.md](references/oauth-setup.md). ### Step 3: Test Locally ```bash # Start server npm start # In another terminal, test with MCP Inspector npx @modelcontextprotocol/inspector@latest # Open http://localhost:5173, enter http://localhost:8788/mcp ``` ### Step 4: Deploy ```bash npx wrangler deploy ``` Server accessible at `https://[worker-name].[account].workers.dev/mcp` ### Step 5: Connect Clients **Claude Desktop** (`claude_desktop_config.json`): ```json { "mcpServers": { "my-server": { "command": "npx", "args": ["mcp-remote", "https://my-mcp.workers.dev/mcp"] } } } ``` Restart Claude Desktop after updating config. ## Tool Patterns ### Return Types ```typescript // Text response return { content: [{ type: "text", text: "result" }] }; // Multiple content items return { content: [ { type: "text", text: "Here's the data:" }, { type: "text", text: JSON.stringify(data, null, 2) }, ], }; ``` ### Input Validation with Zod ```typescript this.server.tool( "create_user", { email: z.string().email(), name: z.string().min(1).max(100), role: z.enum(["admin", "user", "guest"]), age: z.number().int().min(0).optional(), }, async (params) => { // params are fully typed and validated } ); ``` ### Accessing Environment/Bindings ```typescript export class MyMCP extends McpAgent<Env> { async init() { this.server.tool("query_db", { sql: z.string() }, async ({ sql }) => { // Access D1 binding const result = await this.env.DB.prepare(sql).all(); return { content: [{ type: "text", text: JSON.stringify(result) }] }; }); } } ``` ## Authentication For OAuth-protected servers, see [references/oauth-setup.md](references/oauth-setup.md). Supported providers: - GitHub - Google - Auth0 - Stytch - WorkOS - Any OAuth 2.0 compliant provider ## Wrangler Configuration Minimal `wrangler.toml`: ```toml name = "my-mcp-server" main = "src/index.ts" compatibility_date = "2024-12-01" [durable_objects] bindings = [{ name = "MCP", class_name = "MyMCP" }] [[migrations]] tag = "v1" new_classes = ["MyMCP"] ``` With bindings (D1, KV, etc.): ```toml [[d1_databases]] binding = "DB" database_name = "my-db" database_id = "xxx" [[kv_namespaces]] binding = "KV" id = "xxx" ``` ## Common Issues ### "Tool not found" in Client 1. Verify tool name matches exactly (case-sensitive) 2. Ensure `init()` registers tools before connections 3. Check server logs: `wrangler tail` ### Connection Fails 1. Confirm endpoint path is `/mcp` 2. Check CORS if browser-based client 3. Verify Worker is deployed: `wrangler deployments list` ### OAuth Redirect Errors 1. Callback URL must match OAuth app config exactly 2. Check `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` are set 3. For local dev, use `http://localhost:8788/callback` ## References - [references/examples.md](references/examples.md) -- Official templates and production examples - [references/oauth-setup.md](references/oauth-setup.md) -- OAuth provider configuration - [references/troubleshooting.md](references/troubleshooting.md) -- Error codes and fixes @ref(examples.md) @ref(oauth-setup.md) @ref(troubleshooting.md)
View on GitHub