cloudflare-dns-mcp-server
Allows management of DNS records (A, AAAA, CNAME, MX, TXT, SRV, CAA, etc.) on Cloudflare zones, including creating, updating, deleting, listing, and exporting DNS records.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cloudflare-dns-mcp-serverList all DNS records for example.com"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cloudflare-dns-mcp-server
A Model Context Protocol (MCP) server for the Cloudflare API. It gives any MCP-compatible LLM client (Claude Code, Claude Desktop, claude.ai custom connectors, ChatGPT connectors, Cursor, and others) eight typed convenience tools for common DNS operations, plus cloudflare_api_request — a guarded passthrough that can reach any Cloudflare v4 API endpoint the token is scoped for. What the server can actually do is set entirely by the API token's scope: a DNS-scoped token keeps it to DNS, while a broader token unlocks more of the v4 surface (reads by default, writes behind an explicit opt-in). It does not add anything outside Cloudflare's own API.
Connect over stdio (for clients that launch a local subprocess) or over streamable HTTP in stateless JSON mode (the current MCP standard for remote servers). See Connecting MCP clients.
Tools
Tool | What it does |
| Confirm the API token is valid and active |
| List domains the token can manage |
| List/filter records in a zone (source of record IDs) |
| Fetch one record by ID |
| Create A/AAAA/CNAME/MX/TXT/SRV/CAA/etc. records |
| Partial update; returns before/after so edits can be reverted |
| Delete (requires |
| Export the zone as a BIND file — take a backup before bulk changes |
| Guarded raw passthrough to any Cloudflare v4 endpoint the token can reach (reads on by default — see Beyond DNS) |
Related MCP server: cloudflare-dns-mcp-server
Setup
Requires Node.js 20+.
1. Create a scoped Cloudflare API token. The token is the real security boundary — what the server can do is exactly what the token is scoped for. For DNS work, in the Cloudflare dashboard go to My Profile → API Tokens → Create Token → use the Edit zone DNS template, and under Zone Resources limit it to the specific zone(s) you want the model to manage. Do not use the Global API Key. Grant only the permissions the task needs: a DNS-scoped token means the worst-case blast radius is DNS on those zones, even though cloudflare_api_request can reach any endpoint the token permits (see Beyond DNS).
2. Install and build:
npm install
npm run build3. Configure and run:
cp .env.example .env # fill in tokens, then either export them or use a loader
export CLOUDFLARE_API_TOKEN="cfat_..."
export MCP_AUTH_TOKEN="$(openssl rand -hex 24)" # protects the MCP endpoint itself
npm startThe MCP endpoint is now at http://127.0.0.1:8787/mcp (health check at /healthz). Environment knobs: HOST (default 127.0.0.1), PORT (default 8787), TRANSPORT (http default, or stdio), ALLOWED_ORIGINS (extra browser origins, comma-separated).
4. Smoke-test it:
MCP_AUTH_TOKEN="<same token>" npm run smokeThis connects with a real MCP client, lists the 9 tools, and calls cloudflare_verify_token. You can also point MCP Inspector at the URL: npx @modelcontextprotocol/inspector.
Connecting MCP clients
The server speaks the two standard MCP transports; pick by how your client connects. A client that launches a local subprocess uses stdio. A client that connects to a URL uses HTTP. The same nine tools are exposed either way.
Local (stdio)
For clients that launch a local subprocess server — Claude Desktop, Cursor, Cline, and similar. The client runs dist/index.js with TRANSPORT=stdio and passes the Cloudflare token in its own env block. There is no network surface, so no MCP_AUTH_TOKEN is needed.
{
"mcpServers": {
"cloudflare": {
"command": "node",
"args": ["/absolute/path/to/cloudflare-dns-mcp-server/dist/index.js"],
"env": {
"CLOUDFLARE_API_TOKEN": "cfat_...",
"TRANSPORT": "stdio",
"CLOUDFLARE_API_PASSTHROUGH": "read"
}
}
}
}The token can live in this env block or in the shell that launches the client. After npm install -g ., the cloudflare-dns-mcp-server bin is on your PATH, so you can set "command": "cloudflare-dns-mcp-server" (dropping args) instead of node plus the absolute path.
Remote (HTTP)
For clients that connect to a URL — ChatGPT custom connectors / MCP, Claude Code, claude.ai custom connectors, and any streamable-HTTP client.
Run the server (
npm start, or Docker) and setMCP_AUTH_TOKENso the/mcpendpoint requires a bearer token.Put it behind HTTPS — a reverse proxy, your platform's TLS, or a Cloudflare Tunnel (
cloudflared tunnel --url http://127.0.0.1:8787). Remote clients can't reachlocalhost.Add it in the client as a custom MCP server / connector pointing at
https://<host>/mcpwith headerAuthorization: Bearer <MCP_AUTH_TOKEN>.
Claude Code:
claude mcp add --transport http cloudflare https://<host>/mcp \
--header "Authorization: Bearer $MCP_AUTH_TOKEN"Generic JSON config (any streamable-HTTP client that supports custom headers):
{
"mcpServers": {
"cloudflare": {
"url": "https://<host>/mcp",
"headers": { "Authorization": "Bearer <MCP_AUTH_TOKEN>" }
}
}
}ChatGPT connects to remote MCP servers by URL — add it under its connectors / MCP settings (typically requires developer mode). It needs a public HTTPS URL. As with the claude.ai connector UI, exact auth-field support (a static bearer header vs OAuth) varies by client version, so check the client's current MCP docs. If the client can't send a static Authorization header, terminate auth upstream instead (e.g. Cloudflare Access) — as described in the next paragraph.
claude.ai / Claude mobile custom connectors need a public HTTPS URL — they can't reach localhost. The quickest path is a Cloudflare Tunnel from the machine running the server:
cloudflared tunnel --url http://127.0.0.1:8787Important caveat: the claude.ai custom-connector UI authenticates via OAuth or not at all — it has no field for a static bearer header. That leaves two options for remote use: put the tunnel behind Cloudflare Access (service auth) and terminate auth there, or run with MCP_AUTH_TOKEN unset and rely on the tunnel URL staying secret — which is meaningfully weaker protection for something that can change your Cloudflare account. With a Cloudflare Tunnel the server still binds 127.0.0.1, so no opt-in is needed; but if you expose the port directly instead of tunnelling, an unauthenticated non-localhost bind requires ALLOW_UNAUTHENTICATED=true. Check the current connector auth options before choosing; this changes over time.
Running with Docker
The image is self-contained and stateless, and no secret is ever built into it — tokens are passed at run time. Because a container must bind 0.0.0.0 to be reachable through a published port, MCP_AUTH_TOKEN is required: the server fails closed without it (unless ALLOW_UNAUTHENTICATED=true, for when auth is terminated upstream). This is the correct behavior for a network-exposed server.
docker build -t cloudflare-mcp .
docker run --rm -p 8787:8787 \
-e CLOUDFLARE_API_TOKEN=cfat_... \
-e MCP_AUTH_TOKEN="$(openssl rand -hex 24)" \
cloudflare-mcp
# add -e CLOUDFLARE_API_PASSTHROUGH=full to also allow passthrough writes (see Beyond DNS)Or with Compose, which reads secrets from a gitignored .env you create (copy .env.example) or from your shell — never from the compose file:
docker compose up --buildEither way the endpoint is at http://<host>:8787/mcp (health check at /healthz). Put HTTPS in front of the published port and add it to a client per Remote (HTTP) above.
Security notes
The server binds to 127.0.0.1 by default and refuses to start without CLOUDFLARE_API_TOKEN. If you bind to any other address without MCP_AUTH_TOKEN set, it refuses to start — anyone who can reach the port can edit your DNS — unless you set ALLOW_UNAUTHENTICATED=true, which is only appropriate when auth is terminated upstream (e.g. Cloudflare Access). Browser-origin requests are rejected unless from localhost or ALLOWED_ORIGINS (DNS-rebinding protection). Tokens are read from the environment, never logged, and never returned by any tool.
On the model-safety side: deletion requires an explicit confirm=true argument, updates return before/after states so any change can be reverted, and cloudflare_export_zone gives a one-call BIND backup — worth asking your model to run before bulk edits. DNS edits propagate to the real internet; a wrong record can take a site or mail offline, so review what the model proposes before letting it loose on production zones.
The ninth tool, cloudflare_api_request, reaches past DNS: by default (read mode) it lets the model GET any endpoint the configured token can reach — not just DNS — while writes require CLOUDFLARE_API_PASSTHROUGH=full plus confirm=true (see Beyond DNS). The Cloudflare token's own scope is the real boundary here, so keep it narrow — or set CLOUDFLARE_API_PASSTHROUGH=off for a strictly DNS-only server.
Beyond DNS: raw API passthrough
The eight typed tools above only touch DNS. cloudflare_api_request is a guarded passthrough that can call any Cloudflare v4 API endpoint the configured token is scoped for — zones, cache, Workers, R2, members, tokens, and so on. It exists so one server can use whatever permissions the token holds — reads are available by default, and writes sit behind an explicit opt-in plus per-call confirmation.
It is controlled entirely by one environment variable, CLOUDFLARE_API_PASSTHROUGH, read fresh on every call:
Value | Behaviour |
unset / |
|
| Reads allowed, and mutating methods allowed only when the call includes |
| Disabled. Every call is refused. Use this for a strictly DNS-only server. |
The tool is compiled in unconditionally and always appears in tools/list. By default it serves reads; set CLOUDFLARE_API_PASSTHROUGH=full to allow writes, or =off to disable it entirely. If you want a strictly DNS-only server, set =off and rely on the typed tools above.
Read this first — and especially before setting full:
The default
readis scoped by the token, not by DNS. The model canGETanything the token can reach —/user(your account email),/accounts/{id}/members, audit logs, Workers script metadata, Access/Zero Trust config, API-token metadata, and more. If you want a strictly DNS-only server, setCLOUDFLARE_API_PASSTHROUGH=off. The token's own scope is the real boundary — keep it as narrow as the work allows.fullgrants whole-account power to every holder ofMCP_AUTH_TOKEN. Authorization on this server is a single shared bearer token for the whole/mcpendpoint, with no per-caller identity or per-tool scoping (and it may sit behind an upstream proxy, or run withALLOW_UNAUTHENTICATED=true).CLOUDFLARE_API_PASSTHROUGHis one process-wide switch, and the per-requestconfirmflag narrows nothing. Sofullmeans anyone who can reach this endpoint gets read/write over the entire Cloudflare account the token permits — including irreversible actions likeDELETE /zones/{id}(deletes a zone with all its records and settings), API token creation/revocation, and member/Access changes. If you need graduated trust, run a separate server instance per trust boundary — its ownMCP_AUTH_TOKEN, its own Cloudflare token, its ownCLOUDFLARE_API_PASSTHROUGH— rather than assumingconfirmprovides caller-level authorization it cannot provide.confirm=trueis set by the model, not by a human. It is the model asserting intent in its own tool-call JSON, exactly likecloudflare_delete_dns_record— but here the blast radius is the whole account, with no snapshot and no undo. Against the realistic threat (a prompt-injected instruction hidden in content the model reads — a DNS TXT record, a fetched web page, an email — telling it to call this tool withconfirm=true), the flag offers essentially no protection oncefullis set; it only guards against the model calling a write by accident. Treat enablingfullas equivalent to granting root Cloudflare account access to anything that can influence the model's context.JSON endpoints only. Non-JSON / binary responses (cert or PEM downloads, raw BIND zone-file exports, Worker script source, other binary assets) are out of scope; use the typed tools or the dashboard for those.
The passthrough never returns or logs the token; host pinning restricts every request to https://api.cloudflare.com/client/v4/… (absolute URLs, other hosts, protocol-relative //host, userinfo, backslashes, and .. traversal are all rejected before any network call).
Development
npm run build # compile TypeScript → dist/
npm start # run HTTP server
npm test # unit tests for the passthrough guards (SSRF path validator + mode resolver)
npm run smoke # end-to-end client test against the running serverSource layout: src/index.ts (transports, auth middleware), src/cloudflare.ts (API client, zone resolution, formatting), src/tools.ts (tool registrations).
License
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-quality-maintenanceA lightweight MCP server for managing DNS records, purging cache, and interacting with the Cloudflare API through natural language commands.24
- Alicense-quality-maintenanceA token-efficient MCP server for managing Cloudflare DNS zones and records with full CRUD support and bulk operations. It can be deployed locally via stdio or as a Cloudflare Worker for remote HTTP access.
- Alicense-qualityCmaintenanceMCP server for managing Cloudflare DNS across multiple zones from a single API token, enabling bulk operations like toggling proxy, listing records, and batch updates.18MIT
- Alicense-qualityBmaintenanceCloudflare DNS MCP server. Manage zones, DNS records, cache, and page rules from Claude, Cursor, Codex, or any MCP-compatible AI assistant.MIT
Related MCP Connectors
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
An MCP server that integrates with Discord to provide AI-powered features.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/SquarePiSigma5/CloudFlareMCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server