If you're building with Claude Code, Cursor, or Windsurf, you've probably heard of MCP — the Model Context Protocol that lets AI assistants use external tools. I went a bit overboard and built 9 production MCP servers with 49 tools, all running on Cloudflare Workers.
Here's what I learned, what went wrong, and what I'd do differently.
What I Built
Each server is a Cloudflare Worker handling JSON-RPC 2.0 requests via the MCP protocol. Zero cold starts, global edge deployment, and a generous free tier.
The 9 servers:
| Server | Tools | What It Does |
|---|---|---|
| JSON Toolkit | 6 | Validate, format, diff, query, transform, schema generation |
| Regex Engine | 5 | Test, explain, build, replace, extract regex patterns |
| Color Palette | 5 | Convert, palette harmonies, WCAG contrast, Tailwind lookup |
| Timestamp | 5 | Unix/ISO convert, timezone, cron parse, duration format |
| Prompt Enhancer | 5 | Optimize, score, rewrite, system prompt generator |
| Intel | 5 | AI market intelligence, GitHub trends, tool comparison |
| Fortune | 3 | Zodiac horoscope, tarot readings (the fun one) |
| MoltBook | 5 | Markdown to HTML, SEO meta, translation, outlines |
| AgentForge | 5 | Side-by-side AI model comparison |
The Architecture
Every server follows the same pattern:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// Landing page at /
if (url.pathname === '/' && request.method === 'GET') {
return new Response(landingHTML(), {
headers: { 'Content-Type': 'text/html' }
});
}
// MCP endpoint at /mcp
if (url.pathname === '/mcp' && request.method === 'POST') {
const body = await request.json();
const { method, id, params } = body;
switch (method) {
case 'initialize':
return mcpResponse(id, {
protocolVersion: '2025-03-26',
capabilities: { tools: {} },
serverInfo: { name: 'my-server', version: '1.0.0' },
});
case 'tools/list':
return mcpResponse(id, { tools: TOOLS });
case 'tools/call':
return handleToolCall(id, params, env);
}
}
}
};
Key design decisions:
- Streamable HTTP transport (not SSE) — simpler, works everywhere
- KV-based rate limiting — 10-20 free calls/day per IP, Pro keys get 1000/day
- In-memory fallback — if KV fails, degrade to 5 req/min instead of unlimited
- Ecosystem hints — every tool response includes links to related tools on other servers
What I'd Do Differently
1. Start with fewer, better tools
I built 49 tools across 9 servers. Honestly, 3 really polished servers would have been more impactful than 9 decent ones. The JSON Toolkit and Regex Engine get the most actual usage.
2. Rate limiting from day one
I initially launched without rate limiting and got hammered by bots within hours. The KV-based rate limiter was a quick fix, but I should have designed it in from the start.
3. Landing pages matter more than you'd think
Each server has a landing page at / with a connect button and tool descriptions. These pages drive more signups than any README or marketplace listing.
The Stack
- Runtime: Cloudflare Workers (V8 isolates, <50ms cold start)
- Storage: D1 (SQLite), KV (key-value), Vectorize (vector search)
- Protocol: MCP 2025-03-26 over JSON-RPC 2.0
-
Auth: API key via
Authorization: Bearerheader -
Deployment:
wrangler deploy— takes about 3 seconds
Total monthly cost for all 9 servers: $0-5 on the Workers paid plan. Cloudflare's free tier covers most of it.
Connect in 10 Seconds
Add any server to your MCP config:
{
"mcpServers": {
"json-toolkit": {
"url": "https://json-toolkit-mcp.yagami8095.workers.dev/mcp"
}
}
}
That's it. Works with Claude Code, Cursor, Windsurf, and Cline.
Try It
All 9 servers are free to use with daily limits. No API key needed for the free tier.
- GitHub — Full source code, MIT license
- All 49 Tools — Try tools in your browser
- Pro Access — $29/mo for 50K calls across all 9 servers
If you're building MCP servers, I wrote a MCP Starter Kit with the complete template I use for every server.
What MCP tools do you wish existed? I'm always looking for ideas for the next server.
Top comments (0)