A token-efficient MCP server for managing Cloudflare DNS zones and records
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
- TL
Tools (10)
cf_dns_list_zonesList zones with optional name, status, or account filters.cf_dns_get_zoneGet zone details by ID or domain name.cf_dns_list_recordsList DNS records with support for filters, pagination, summary mode, and random sampling.cf_dns_get_recordGet a single DNS record by ID.cf_dns_export_recordsExport a zone's DNS records as a BIND zonefile.cf_dns_create_recordCreate a new DNS record.cf_dns_update_recordPerform a partial update (PATCH) on an existing DNS record.cf_dns_delete_recordDelete a DNS record with a mandatory safety confirmation.cf_dns_bulk_createCreate up to 100 DNS records in a single operation.cf_dns_bulk_updateUpdate up to 100 DNS records in a single operation.Environment Variables
CLOUDFLARE_API_TOKENrequiredAPI token with Zone Read and DNS Edit permissionsCLOUDFLARE_DNS_MCP_API_KEYAPI key for remote HTTP transport authenticationPORTPort for HTTP server modeConfiguration
{"mcpServers": {"cloudflare-dns": {"command": "node", "args": ["/path/to/cloudflare-platform-mcp/dist/index.js"], "env": {"CLOUDFLARE_API_TOKEN": "your-api-token-here"}}}}