Scaffold a new MCP server on Cloudflare Workers with TypeScript, OAuth support, and Durable Objects.
Scaffolds a new MCP server on Cloudflare Workers with TypeScript, OAuth, and Durable Objects.
/plugin marketplace add jezweb/claude-skills/plugin install jezweb-cloudflare-mcp-server-skills-cloudflare-mcp-server@jezweb/claude-skillsScaffold a new MCP server on Cloudflare Workers with TypeScript, OAuth support, and Durable Objects.
Follow these steps to create a new MCP server project.
Ask the user for:
Defaults if not specified:
npm create cloudflare@latest <project-name> -- --type hello-world --ts --git --deploy false
cd <project-name>
npm install @modelcontextprotocol/sdk hono zod
npm install -D @cloudflare/workers-types wrangler typescript
If OAuth selected:
npm install @cloudflare/workers-oauth-provider
src/
├── index.ts # Main worker entry
├── mcp/
│ ├── server.ts # MCP server setup
│ └── tools/
│ └── index.ts # Tool definitions
├── auth/ # If OAuth
│ └── oauth.ts
└── types.ts # TypeScript types
Create src/mcp/server.ts:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { registerTools } from './tools';
export function createMcpServer() {
const server = new McpServer({
name: '<project-name>',
version: '1.0.0',
});
registerTools(server);
return server;
}
Create src/mcp/tools/index.ts:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
export function registerTools(server: McpServer) {
server.registerTool(
'hello',
{
description: 'Say hello to someone',
inputSchema: z.object({
name: z.string().describe('Name to greet'),
}),
},
async ({ name }) => ({
content: [{ type: 'text', text: `Hello, ${name}!` }],
})
);
// Add more tools here
}
Create src/index.ts:
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { createMcpServer } from './mcp/server';
type Bindings = {
// Add your bindings here
};
const app = new Hono<{ Bindings: Bindings }>();
app.use('/mcp/*', cors());
app.post('/mcp', async (c) => {
const server = createMcpServer();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true,
});
await server.connect(transport);
return transport.handleRequest(c.req.raw);
});
app.get('/', (c) => c.json({
name: '<project-name>',
endpoints: { mcp: '/mcp' }
}));
export default app;
{
"name": "<project-name>",
"main": "src/index.ts",
"compatibility_date": "2025-11-11",
"compatibility_flags": ["nodejs_compat"]
}
If OAuth selected, add Durable Objects:
{
"durable_objects": {
"bindings": [
{ "name": "OAUTH_PROVIDER", "class_name": "OAuthProvider" }
]
},
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["OAuthProvider"] }
]
}
Ensure tsconfig.json has:
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"strict": true,
"types": ["@cloudflare/workers-types"]
}
}
✅ MCP Server "<project-name>" created!
📁 Structure:
- src/index.ts (Worker entry)
- src/mcp/server.ts (MCP server setup)
- src/mcp/tools/index.ts (Tool definitions)
🚀 Next steps:
1. cd <project-name>
2. Add your tools in src/mcp/tools/index.ts
3. npm run dev (Start local dev)
4. npx wrangler deploy (Deploy to Cloudflare)
🔗 Connect to Claude.ai:
Settings → MCP Servers → Add → https://<worker>.workers.dev/mcp
📚 Skill loaded: cloudflare-mcp-server
- 22 common issues auto-prevented
- OAuth ready for Claude.ai integration