cloudflare-dns-mcp-server
A best-of-breed MCP server for Cloudflare DNS management. Designed for extreme token efficiency, full CRUD coverage, and easy deployment as both a local MCP server and a Cloudflare Worker.
Features
- 10 DNS tools covering zones, records, bulk operations, and BIND export
- Token-efficient by default — concise output strips 60-80% of Cloudflare API bloat
- Summary mode — get record counts + type distribution without fetching individual records
- Random sampling — audit large zones without loading everything
- Safety gates — deletes require explicit
confirm: true - Dual transport — stdio for Claude Desktop, Streamable HTTP for remote access
- Worker-ready — deploy to Cloudflare Workers with
npm run deploy
Quick Start
1. Create a Cloudflare API Token
Go to Cloudflare API Tokens and create a token with:
- Zone → Zone → Read
- Zone → DNS → Edit
- Scope: All zones (or specific zones you want to manage)
2. Install
git clone https://github.com/piersdd/cloudflare-platform-mcp.git
cd cloudflare-platform-mcp
npm install
npm run build
3. Configure Claude Desktop
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"cloudflare-dns": {
"command": "node",
"args": ["/path/to/cloudflare-platform-mcp/dist/index.js"],
"env": {
"CLOUDFLARE_API_TOKEN": "your-api-token-here"
}
}
}
}
Restart Claude Desktop. The server validates your token on startup.
Tools
Read Tools
| Tool | Description |
|---|---|
cf_dns_list_zones | List zones with optional name/status/account filters |
cf_dns_get_zone | Get zone by ID or domain name |
cf_dns_list_records | List records with filters, pagination, summary mode, random sampling |
cf_dns_get_record | Get a single record by ID |
cf_dns_export_records | Export zone as BIND zonefile |
Write Tools
| Tool | Description |
|---|---|
cf_dns_create_record | Create any DNS record type (A, AAAA, CNAME, MX, TXT, SRV, CAA, etc.) |
cf_dns_update_record | Partial update (PATCH) — only changed fields |
cf_dns_delete_record | Delete with mandatory confirm: true safety gate |
cf_dns_bulk_create | Create up to 100 records in one call |
cf_dns_bulk_update | Update up to 100 records in one call |
Token Efficiency
Every tool defaults to concise output. Here's what that means:
Concise (default) — only the fields an LLM needs:
{ "id": "abc123", "type": "A", "name": "www.example.com", "content": "203.0.113.10", "proxied": true, "ttl": "auto" }
Full Cloudflare response (with include_details=true) — includes zone_id, zone_name, meta, settings, proxiable, locked, etc. ~5x more tokens.
Efficiency Modes for cf_dns_list_records
| Mode | Tokens | Use Case |
|---|---|---|
summary_only=true | ~50 | "How many records? What types?" |
random_sample=true | ~200 | "Show me a few records to check" |
| Filtered + concise | ~500 | "Show me all CNAME records" |
| Full details | ~2500 | "I need all metadata for debugging" |
Example Prompts
"List all my Cloudflare zones"
"Show me the DNS records for example.com"
"How many DNS records does example.com have, broken down by type?"
"Create an A record for app.example.com pointing to 203.0.113.10 with proxy enabled"
"Set up email DNS for example.com with Google Workspace MX records"
"Switch the A record for api.example.com from 10.0.0.1 to 10.0.0.2"
"Delete the old staging CNAME record"
"Export all DNS records for example.com as a BIND file"
"Audit example.com for unproxied A records that might expose our origin IP"
HTTP Transport (Remote Access)
Run as an HTTP server instead of stdio:
TRANSPORT=http CLOUDFLARE_API_TOKEN=your-token node dist/index.js
The server starts on port 8787 (configurable via PORT env var). An API key is auto-generated and printed to stderr on first run. Set CLOUDFLARE_DNS_MCP_API_KEY to persist it.
Endpoints:
POST /mcp— MCP Streamable HTTP (requiresX-API-Keyheader)GET /health— Health check
Remote MCP Client Config
{
"mcpServers": {
"cloudflare-dns": {
"url": "http://localhost:8787/mcp",
"headers": {
"X-API-Key": "your-mcp-api-key"
}
}
}
}
Deploy as a Cloudflare Worker
The same codebase deploys to Cloudflare Workers for always-on remote access:
# Set secrets
npx wrangler secret put CLOUDFLARE_API_TOKEN
npx wrangler secret put CLOUDFLARE_DNS_MCP_API_KEY
# Deploy
npm run deploy
Your MCP server is now at https://cloudflare-dns-mcp.your-subdomain.workers.dev/mcp.
Public Exposure with Custom Domain
For production use behind a custom domain:
- Add a custom domain in the Cloudflare dashboard for your Worker
- TLS is automatic via Cloudflare's edge certificates
- Optionally put it behind Cloudflare Access for SSO authentication
Via Cloudflare Tunnel
For exposing a local instance:
cloudflared tunnel --url http://localhost:8787
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
CLOUDFLARE_API_TOKEN | Yes | — | Cloudflare API token with Zone:Read + DNS:Edit |
TRANSPORT | No | stdio | stdio or http |
PORT | No | 8787 | HTTP server port (http transport only) |
CLOUDFLARE_DNS_MCP_API_KEY | No | auto-generated | API key for HTTP transport authentication |
Development
npm run dev # stdio mode with auto-reload
npm run dev:http # HTTP mode with auto-reload
npm run build # Compile TypeScript
npm run typecheck # Type-check without emitting
npm run deploy # Build + deploy to Workers
License
MIT