Building an MCP Server: Connecting AI to Your Infrastructure
The Model Context Protocol (MCP) lets AI assistants interact with external tools and services. I built a custom MCP server that connects AI to my entire infrastructure — Cloudflare Workers, Vercel deployments, GitHub repos, PostgreSQL databases, and more.
What is MCP?
MCP is a standardized protocol for AI tool use. Think of it as a universal API layer that lets AI models:
- Read data from your services
- Execute operations (deploy, create, update)
- Query databases and analytics
- Manage infrastructure programmatically
Architecture
AI Assistant (Claude, GPT)
↓ MCP Protocol
MCP Server (Node.js)
↓ API Calls
┌──────────────┬──────────────┬──────────────┐
│ Cloudflare │ Vercel │ GitHub │
│ Workers/KV │ Deployments │ Repos │
├──────────────┼──────────────┼──────────────┤
│ PostgreSQL │ Supabase │ Stripe │
│ Database │ Edge Func │ Payments │
└──────────────┴──────────────┴──────────────┘
The MCP server is a single Node.js process that exposes tools via JSON-RPC. Each tool maps to an API call or database query.
Key Tools I Built
1. Cloudflare Management
// Deploy a Worker, manage KV, query analytics
{
name: "worker_deploy",
description: "Deploy or update a Cloudflare Worker",
inputSchema: {
name: z.string(),
script: z.string(),
bindings: z.array(z.object({ name: z.string(), type: z.string() })),
}
}
2. Vercel Deployments
Check deployment status, view logs, manage environment variables, and trigger redeployments — all through natural language.
3. Database Queries
Direct SQL access to PostgreSQL with read-only safety:
{
name: "query",
description: "Execute a read-only SQL query",
input: { sql: z.string() }
}
4. GitHub Operations
Create issues, manage PRs, search code, check CI status — integrated directly into the AI conversation.
Implementation Patterns
Tool Schema Design
Every tool needs a clear name, description, and input schema. The AI uses these to decide when and how to call each tool.
server.tool(
"kv_get",
"Get a value from Cloudflare KV namespace",
{ namespace: z.string(), key: z.string() },
async ({ namespace, key }) => {
const value = await kv.get(namespace, key);
return { content: [{ type: "text", text: value ?? "null" }] };
}
);
Error Handling
Always return structured errors. The AI needs to understand what went wrong to retry or suggest alternatives.
Rate Limiting
Wrap API calls with rate limiting. Cloudflare's API has generous limits, but GitHub and Vercel can throttle aggressive usage.
Security Considerations
- Read-only by default — Write operations require explicit confirmation
- Scoped API tokens — Each integration uses minimal-permission tokens
- Audit logging — Every tool call is logged with timestamp and parameters
- Secrets management — API keys stored in environment variables, never in code
The Workflow
Instead of switching between dashboards, I manage infrastructure through conversation:
"Deploy the latest version of my portfolio to production" "What's the error rate on my Cloudflare Workers this week?" "Create a GitHub issue for the mobile app crash bug" "Query the database for top 10 most visited projects"
Performance
The MCP server adds ~50ms latency per tool call. For complex operations (deployments, database migrations), this is negligible. For rapid iterations, I batch related calls.
What's Next
- Workflow automation — Chain multiple tools for complex operations
- Custom dashboards — Generate real-time monitoring views
- Proactive alerts — AI monitors infrastructure and suggests actions
MCP transforms AI from a chat interface into an operations center. Instead of context-switching between 10 dashboards, everything happens in one conversation.