Cloudflare MCP
Provides a guarded generic Cloudflare REST API request tool and utilities for checking configuration, listing capabilities, and querying endpoint coverage, enabling interaction with Cloudflare services via their official API.
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 MCPlist DNS records for my zone 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.
The contract
MADPANDA3D Cloudflare MCP exposes exactly six protocol-visible tools:
Five agent-ready navigation tools explain configuration, search the catalog, filter endpoint coverage, and return exact descriptors. They are local unless
check_configurationis explicitly asked to verify a token.One advanced legacy dispatcher,
cloudflare_api_request, executes one reviewed Cloudflare REST operation at a time through a fixed provider origin.
The checked-in endpoint inventory accounts for 3,148 operations from a
pinned Cloudflare api-schemas snapshot. Reviewed policy 2026.07.19.3 makes
2,356 callable and leaves 792 catalog-only because their authentication,
required provider headers, media types, request/success contracts, exact policy
overrides, or credential-sensitive schemas fall outside the generic dispatcher
boundary. Catalog-only does not mean hidden: agents can inspect those operations
and the exclusion reason, but the dispatcher rejects execution.
The server is streamable HTTP at /mcp, exposes presence-only health metadata
at /health, stores no Cloudflare credential, and does not turn a deployment
into a public or unauthenticated Cloudflare endpoint.
Related MCP server: Cloudflare MCP Server
Choose an access mode
MCP_MODE is selected at startup. Changing it requires a restart; no tool can
change the running mode.
Mode | Intended use | Service credential | Cloudflare credential |
| Independent self-hosting |
|
|
| Optional MAD MCP Portal routing | Matching | The broker forwards |
There is no unauthenticated MCP mode. The service credential controls access
to this server; the Cloudflare token separately controls provider permissions.
Portal mode also requires the header named by MCP_TENANT_ID_HEADER (default
x-madpanda-user-id) on every MCP request. The broker must remove any
client-supplied value and inject its own authenticated tenant identity. That
identity partitions process-local approval principals; it is not authorization
and never replaces Portal access control or Cloudflare token permissions.
Request-scoped Cloudflare BYOK
Both modes use the same provider headers:
Header | Required | Purpose |
| Provider calls | Least-privilege Cloudflare API token for this request |
| Optional | Account-scope hint used by navigation and token verification |
| Optional | Zone-scope hint used by navigation and workflows |
| Approved mutation retry only | Short-lived one-use proof issued by a trusted operator or broker |
Account and zone headers are hints, not authorization and not automatic path substitution. Provider paths still need the correct explicit resource IDs, and Cloudflare remains the authority for token permissions.
In Portal mode, the broker-controlled tenant header is mandatory service-auth context, not a provider header. Clients must never be allowed to select or forward that value directly.
There is deliberately no Cloudflare token environment fallback. Never place a
provider token in .env, Compose, an image layer, a URL, an issue, a screenshot,
or copied client configuration. Supply it through the MCP client's protected
secret/header facility for the active request.
Five-minute standalone deployment
Prerequisites: Git, Python 3.12 or 3.13, uv, Docker Engine with Compose v2,
and a Cloudflare API token with only the permissions required for your intended
operations.
git clone https://github.com/MADPANDA3D/CF-MCP.git
cd CF-MCP
python3 scripts/init_runtime_env.py --mode standaloneThe initializer creates ignored .env mode 0600, generates independent
service and mutation-approval secrets, never overwrites an existing file, and
never prints a secret. Review only the non-secret routing values:
MCP_MODE=standalone
MCP_ALLOWED_HOSTS=localhost,127.0.0.1
MCP_HOST_PORT=8000Do not put the Cloudflare token in this file. Start the loopback-only profile:
docker compose --env-file .env -f docker-compose.yml config --quiet
docker compose --env-file .env -f docker-compose.yml up -d --build
docker compose --env-file .env -f docker-compose.yml ps
curl --fail http://127.0.0.1:8000/healthExpected safe health fields include:
{
"status": "healthy",
"service": "cloudflare-mcp",
"tool_count": 6,
"configuration": {
"mode": "standalone",
"provider_credentials_mode": "per_request_byok"
}
}/health reports mode, readiness, bounds, and release/catalog identity without
returning a service token, Portal grant, Cloudflare token, account ID, or zone
ID.
Connect an MCP client
Client formats differ, but the logical HTTP configuration is:
{
"mcpServers": {
"cloudflare": {
"type": "http",
"url": "http://127.0.0.1:8000/mcp",
"headers": {
"Authorization": "Bearer ${MCP_ACCESS_TOKEN}",
"x-cloudflare-api-token": "${CLOUDFLARE_API_TOKEN}",
"x-cloudflare-account-id": "${OPTIONAL_CLOUDFLARE_ACCOUNT_ID}",
"x-cloudflare-zone-id": "${OPTIONAL_CLOUDFLARE_ZONE_ID}"
}
}
}
}${...} means “load this value from the client's protected secret or
environment facility.” It is not universal interpolation syntax. Omit optional
headers when they are not needed, and never commit resolved values.
The five navigation tools need only the selected service-auth header. Provider
execution and optional live token verification also need
x-cloudflare-api-token. Mutation-capable clients additionally need a trusted
per-request mechanism to inject a short-lived x-mcp-approval-attestation
after an operator or broker approves the preview. If the client cannot inject a
one-request header, use the server as read-only.
Tools
Tool | Tier | Provider call | Behavior |
|
| Optional | Reports secret-safe readiness; verifies a token only when explicitly requested |
|
| No | Returns compact catalog counts or the complete deterministic ToolManifest |
|
| No | Filters the pinned 3,148-operation inventory; results include coverage, auth, required-header/body, contract, and risk metadata |
|
| No | Resolves one native, canonical, or documented alias to its exact descriptor and usage contract |
|
| No | Searches the local catalog; advanced legacy results are opt-in |
|
| Yes | Previews or executes one pinned method/path JSON operation through the guarded advanced path |
All six tools remain protocol-visible for compatibility. Default task discovery returns the five agent-ready tools; callers must deliberately include the advanced legacy tier to select the dispatcher.
Endpoint coverage
The generated inventory is pinned to Cloudflare's official
api-schemas repository:
Identity | Value |
Upstream commit |
|
Source snapshot SHA-256 |
|
Upstream license | BSD-3-Clause |
Reviewed endpoint-policy version |
|
Total operations | 3,148 |
Read / write / destructive | 1,499 / 1,201 / 448 |
Callable reviewed operations | 2,356 |
Catalog-only operations | 792 |
Unsupported request / success media | 41 / 103 |
Required provider headers / no Bearer API-token proof | 2 / 87 |
No reviewable JSON request schema | 127 |
No explicit 2xx response contract | 49 |
Ambiguous non-204/205 bodyless success | 15 |
No reviewable successful JSON schema | 120 |
Credential-sensitive schema operations | 263 |
Sensitive request / successful-response schemas | 104 / 206 |
Credential-semantic signal operations | 172 |
Reviewed overrides / forced catalog-only overrides | 117 / 114 |
High-risk / reviewed side-effecting GET operations | 469 / 23 |
“Callable” means the method/path exists in the pinned schema, the operation
contract proves compatibility with this server's fixed Bearer API-token client,
it requires no caller-supplied provider headers, and its request and success
contracts fit the reviewed JSON boundary. A JSON request or successful response
must have a reviewable schema; missing, empty, and bare type: object schemas do
not prove which fields or sensitive values may cross the boundary. If OpenAPI
marks a request body required, the runtime rejects an omitted body. This remains
basic contract admission, not complete query/body field validation.
Every operation must declare an explicit 2xx response. Only 204 and 205 are
accepted as implicitly bodyless; every other successful status must declare a
response content contract. That policy leaves 49 operations with no explicit
2xx, 15 with ambiguous non-204/205 bodyless success, and 120 with unreviewable
successful JSON schemas catalog-only. The corresponding request-side rule
excludes 127 operations whose JSON request schema cannot be reviewed. Reason
counts overlap.
Credential signals include unmarked capability and payment values such as license or pairing keys, card/payment fields, invoice documents, and signed upload, download, or debugger URLs. Exact review also forces 87 credential-capable endpoint contexts—including arbitrary outbound header maps and temporary privileged URLs—out of the generic dispatcher. Exact reviewed transport overrides also keep these contracts fail-closed:
GET /accounts/{account_id}/email-security/investigaterequires theLocationheader from its202response to continue polling, but the generic dispatcher intentionally omits provider response headers.POST,PATCH, andDELETE/accounts/{account_id}/teamnet/routes/network/{ip_network_encoded}require an encoded CIDR slash that the path normalizer rejects to prevent ambiguous path traversal.GET /accounts/{account_id}/cni/interconnects/{icon}/loais classified as a write, flagged as a side-effecting GET, and forced catalog-only because it generates a Letter of Authorization document.
Callable status does not mean a caller's token has permission or an operation is free. Every high-risk operation is blocked from generic execution.
The dispatcher does not validate arbitrary query keys or JSON body fields
against Cloudflare's complete parameter and request-body schemas. It enforces a
pinned method/path match, endpoint policy, supported JSON media, and structural
JSON bounds. It also enforces OpenAPI's required-body presence bit, but Cloudflare
remains authoritative for field-level validation. A caller—and, for mutations,
the approval issuer—must review the exact query and body rather than treating
callable as proof that those fields are valid.
The dispatcher rejects operations missing from the snapshot, operations without Bearer API-token compatibility proof, required provider headers it cannot construct, unreviewable request/success contracts, arbitrary provider origins, caller-supplied HTTP headers, non-JSON request bodies, unsupported success media types, redirects, and ambiguous query-in-path URLs. It is not a general-purpose HTTP proxy.
See the endpoint coverage ledger for the generated matrix and provenance for the attribution chain.
Externally approved, one-use mutations
Reviewed reads execute once after authentication, BYOK, pinned method/path, JSON-media, and endpoint-policy checks. Ordinary writes and destructive operations use an approval flow whose signing secret is separate from the agent and MCP client:
Call
cloudflare_api_requestwith the exact method, path, query, JSON body, and content type plus the request-scoped Cloudflare token.The server makes no provider call. It returns
executed=false, an expiringapproval_payload, operation identity, and canonical request digest.A trusted operator or Portal broker creates one exact review JSON document containing only
approval_payload,method,path,query,body, andcontent_type. The issuer independently reviews the full target and effects, including every query/body field, then signs that document with the separately controlledMCP_APPROVAL_SIGNING_KEY. For example:{ "approval_payload": "<EXACT_SERVER_RETURNED_PAYLOAD>", "method": "POST", "path": "/accounts/<ACCOUNT_ID>/<REVIEWED_PATH>", "query": null, "body": {"<REVIEWED_FIELD>": "<REVIEWED_VALUE>"}, "content_type": "application/json" }uv run --env-file .env python scripts/sign_approval.py \ < approval-review.jsonInject the resulting short-lived value as
x-mcp-approval-attestationon one repeat of the unchanged MCP request.
scripts/sign_approval.py recomputes the operation and canonical request
digest from that exact review document before signing. Never pipe or sign an
approval_payload by itself, and never let an agent generate an unreviewed
document for automatic signing.
The attestation is bound to the authenticated service principal (including the broker-derived tenant in Portal mode), request-scoped Cloudflare credential fingerprint, operation, exact request, expiry, and random challenge. It is atomically consumed before the provider attempt, so direct forgery, argument changes, credential swapping, principal swapping, and replay fail closed. A timeout remains outcome-ambiguous; inspect provider state with a safe read before requesting a new approval.
The approval ledger is bounded and process-local. A mutation preview and its
approved retry must reach the same live process within five minutes. Use a
single mutation-admitting replica or explicit same-replica routing; otherwise
operate read-only. Never expose MCP_APPROVAL_SIGNING_KEY to an agent, MCP
client, prompt, ticket, log, or provider request.
All 469 high-risk operations—including detected credential-sensitive,
account-administration, billing/commerce, and reviewed side-effecting GET
classes—are permanently blocked from the generic dispatcher. There is no
startup toggle. All 263 operations with detected sensitive request or successful
response schemas and all 114 force-catalog reviewed overrides are
catalog_only; response redaction remains a defense-in-depth control, not an
admission mechanism.
Provider calls receive one outbound attempt. This server does not automatically retry reads, writes, destructive requests, or billable calls.
Configuration
Start from .env.example. Principal settings are:
Variable | Required | Purpose and reviewed default |
| Yes | Startup mode: |
| Standalone | Bearer token of at least 32 characters |
| Portal | Unique Portal-to-service grant of at least 32 characters |
| Portal | Broker-controlled tenant-partition header name; default |
| Mutations | Separate operator/broker HMAC key; must differ from service and provider credentials; blank makes the deployment read-only |
| Standalone Compose | Loopback host port; default |
| Yes | Explicit Host allowlist; wildcards fail startup validation |
| Optional | Explicit browser origins; empty rejects requests carrying |
| Optional | MCP request limit; default 128 KiB, hard maximum 8 MiB |
| Optional | Complete MCP response limit; default 1 MiB, hard maximum 2 MiB |
| Optional | Streamed provider response limit; default 64 KiB, hard maximum 240 KiB |
| Source builds | Build argument baked into image identity; release Compose does not accept a runtime override |
| Source builds | Source-archive fingerprint baked into image identity; release Compose does not accept a runtime override |
| Source builds |
|
| Immutable release Compose | Only release-identity input: the exact 64-character GHCR digest, in addition to normal service credentials |
The provider origin is fixed to https://api.cloudflare.com/client/v4; there
is no supported environment override. Provider credentials and account/zone
hints are request headers, not environment variables.
Optional Portal deployment
Portal mode uses the same server and provider contract:
MCP_MODE=portal
MCP_PORTAL_GRANT_TOKEN=<UNIQUE_PORTAL_TO_SERVICE_GRANT>
MCP_TENANT_ID_HEADER=x-madpanda-user-id
MCP_APPROVAL_SIGNING_KEY=<SEPARATELY_CONTROLLED_BROKER_SIGNING_KEY>
MCP_PORTAL_NETWORK=<PRIVATE_DOCKER_NETWORK_NAME>
MCP_ALLOWED_HOSTS=cloudflare-mcp,<TRUSTED_PROXY_HOST>The broker sends:
X-MADPANDA-PORTAL-GRANT: <SERVICE_GRANT>
x-madpanda-user-id: <BROKER_DERIVED_TENANT_ID>
x-cloudflare-api-token: <OWNER_CLOUDFLARE_API_TOKEN>
x-cloudflare-account-id: <OPTIONAL_OWNER_ACCOUNT_ID>
x-cloudflare-zone-id: <OPTIONAL_OWNER_ZONE_ID>
x-mcp-approval-attestation: <ONE_USE_BROKER_ATTESTATION_FOR_APPROVED_MUTATION>The broker must strip or overwrite any client-supplied
x-madpanda-user-id value before forwarding. The tenant value partitions
approval principals and same-tenant preview/retry routing; it does not authorize
the request or grant Cloudflare access.
Use deployment-specific placeholders for the internal service name, network, locked MCP URL, health URL, proxy, and secret-store reference. This repository contains no production topology. See the Portal compatibility guide.
Production posture
Keep
/mcpbehind TLS or loopback/private networking.Preserve the selected service-auth context and reviewed BYOK headers at the trusted proxy; in Portal mode, strip/overwrite the tenant header from authenticated broker identity and never log its value.
Block direct container access from untrusted networks.
Keep
.envmode0600, with no Cloudflare provider credential inside.Apply connection, request-size, idle-timeout, and rate limits at the edge.
Preserve Host allowlisting and default browser-Origin rejection.
Verify health, unauthorized rejection, six-tool discovery, local navigation, missing-BYOK rejection, catalog-only rejection, one-use approval binding/replay denial, and permanent high-risk denial before a provider smoke.
Use a least-privilege test token and an explicitly approved read as the first provider call. Do not certify first with a mutation or paid action.
The application stores no database or provider credential. Read traffic can use multiple identical replicas, but the bounded one-use mutation approval ledger is process-local. Keep mutation admission on one replica or use explicit same-replica routing from preview through approved retry.
Immutable containers
The source is prepared as a v1.0.0 release candidate; documentation alone does
not prove that a hosted GitHub Release or public GHCR digest exists. The
exact annotated tag and tagged workflow may start while the clean canonical
source remains private. The workflow first builds only a run-scoped candidate
image with BuildKit SBOM/provenance and scans its exact digest.
The package owner then makes only that GHCR package public so the same candidate
can pass anonymous pull, Compose, and runtime smokes. Only after the image gate
succeeds is the source repository made public for exact-SHA Verify/CodeQL
admission. GitHub-signed package and image attestations are created after that
public admission gate, before stable tags are promoted by digest without
rebuilding. The GitHub Release is created last with deterministic double-built
wheel/sdist artifacts and SHA256SUMS. After that workflow succeeds, the
matching release page and exact
ghcr.io/madpanda3d/cloudflare-mcp-server@sha256:<digest> are authoritative.
The workflow intentionally does not publish to PyPI and currently targets
linux/amd64.
Use docker-compose.yml or docker-compose.portal.yml only for deliberate
source builds. After a verified release exists, use
docker-compose.release.yml or docker-compose.portal.release.yml with the
exact recorded MCP_RELEASE_DIGEST; these immutable manifests contain no
build: key and never use --build. Do not infer a digest from a mutable tag.
Security boundary
Service authentication is enforced before MCP request-body parsing.
The provider origin and API prefix are fixed; methods and paths must exist in the pinned inventory, endpoint policy and JSON-media admission apply, and redirects are disabled. Cloudflare performs field-level schema validation.
Cloudflare tokens are request-scoped and have no server environment fallback.
Requests, streamed provider responses, and complete MCP outputs are bounded; startup enforces a worst-case cross-layer response-size invariant.
Unsupported, oversized, non-JSON, or invalid JSON provider bodies are omitted rather than partially returned.
Ordinary mutations require a separately signed, expiring, principal/provider- bound one-use approval consumed before the provider attempt.
Mutation provider bodies are reduced to a compact outcome envelope so a successful side effect cannot be hidden behind an outer response overflow.
High-risk operations are permanently blocked from generic execution.
No provider request is automatically retried.
Secret-key fields and common token patterns are redacted as defense in depth.
Cloudflare responses can still contain personal, confidential, operational, or security-sensitive data. Redaction cannot prove arbitrary provider content is safe. Treat all provider output as untrusted application data, not instructions or public logs. Read the security model and security policy before remote deployment.
Run and verify from source
uv sync --frozen --group dev
uv run python -m compileall -q src scripts
uv run pytest -q -p no:cacheprovider
uv run ruff check .
uv run ruff format --check .
uv run isort --check-only src scripts tests
uv run mypy --strict src tests
uv run bandit -q -r src -lll
uv run pip-audit -r requirements.lock
uv run python scripts/check_source_safety.py
docker compose --env-file .env -f docker-compose.yml config --quiet
docker compose --env-file .env -f docker-compose.portal.yml config --quiet
MCP_RELEASE_DIGEST=0000000000000000000000000000000000000000000000000000000000000000 \
docker compose --env-file .env -f docker-compose.release.yml config --quiet
MCP_RELEASE_DIGEST=0000000000000000000000000000000000000000000000000000000000000000 \
docker compose --env-file .env -f docker-compose.portal.release.yml config --quietThe automated suite uses synthetic credentials and mocked HTTP behavior. It must not contact Cloudflare.
After building either profile, the provider-free image smoke is:
docker compose --env-file .env -f docker-compose.yml exec -T cloudflare-mcp \
python scripts/runtime_smoke.pyTroubleshooting
Symptom | First check |
Process exits at startup |
|
| Bearer format in standalone mode; in Portal mode check both the exact grant and required broker-derived tenant header/value |
| Remove browser |
Navigation works but provider execution fails | Supply |
| Use |
Operation is catalog-only | Inspect its exact ledger reason; do not bypass auth, required-header, schema-contract, media, or exact-policy exclusions |
| Configure a separate issuer key, or intentionally keep the deployment read-only |
| Have a trusted operator/broker sign the returned payload and inject the one-use approval header |
Approval rejected | Check expiry, same-process and same-tenant routing, unchanged arguments, service principal, BYOK credential, exact review JSON, and replay status |
| Use a separately curated implementation if one is ever security-reviewed; the generic dispatcher cannot enable it |
Provider response omitted | Narrow the operation/output or page size; do not disable limits casually |
Container unhealthy | Check sanitized logs, resource limits, |
Never post tokens, .env, provider IDs, private URLs, or unredacted provider
output in a support report.
Documentation
License and trademarks
The MADPANDA3D-authored code is available under the MIT License. The derived endpoint inventory retains Cloudflare api-schemas BSD-3-Clause attribution in NOTICE.
Cloudflare and related product names are trademarks of Cloudflare, Inc. or their respective owners. This independent project is not an official Cloudflare product, distribution, partnership, sponsorship, or endorsement.
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-qualityDmaintenanceA lightweight MCP server that enables agents to interface with Cloudflare's REST API, allowing management of DNS records and other Cloudflare services.Last updated915GPL 2.0

Cloudflare MCP Serverofficial
Alicense-qualityAmaintenanceA token-efficient MCP server that provides access to the entire Cloudflare API (2500+ endpoints) using a code execution pattern, enabling natural language management of Cloudflare services.Last updated17684Apache 2.0- AlicenseBqualityCmaintenanceRead-only Cloudflare MCP server for SOC investigation, exposing Cloudflare services like WAF, bot management, analytics, and Zero Trust for querying and discovery.Last updated32MIT
- Flicense-qualityBmaintenanceRemote MCP server to manage Cloudflare domains, zones, and DNS records via OAuth authentication.Last updated
Related MCP Connectors
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
MCP server for interacting with the Supabase platform
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/MADPANDA3D/CF-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server