| name | cloudflare-api |
| description | Connect to Cloudflare API via Cloudflare MCP Code Mode or local scripts for DNS management, R2 bucket management, tunnels, and zone administration. Use when user needs to manage domains, DNS records, R2 buckets, Workers, D1, rulesets, or Cloudflare API operations. |
| read_when | ["User asks about Cloudflare DNS or domains","User wants to create or manage DNS records","User needs to set up Cloudflare tunnels","User wants to list their Cloudflare zones","User asks about R2 buckets or object storage"] |
| metadata | {"clawdbot":{"emoji":"☁️","requires":{"bins":"[Truncated]"}}} |
Cloudflare Skill
Origin: Forked from lucassynnott/cloudflare-api on OpenClaw.
Connect to Cloudflare API for DNS management, tunnels, and zone administration.
Tool Routing
Prefer Cloudflare MCP Code Mode for broad or unknown Cloudflare API work. Use the local scripts for known, deterministic DNS/R2/tunnel workflows that this skill already covers.
| Task | Preferred path |
|---|
| Cloudflare product/API discovery | Native MCP cloudflare_docs then cloudflare_search (fallback: ./scripts/mcp.sh docs / search) |
| Unknown endpoint, Workers, D1, Rulesets, WAF, Pages, AI Gateway, etc. | Native MCP cloudflare_search → cloudflare_execute |
| Exact DNS CRUD from this skill | Local DNS scripts |
| Common R2 bucket workflows, especially jurisdiction-sensitive checks | Local R2 scripts |
| Tunnel CRUD from this skill | Local tunnel scripts |
| Analytics / GraphQL reporting | cloudflare-analytics skill first; MCP fallback |
| MCP unavailable or unauthenticated | Local scripts + Cloudflare llms.txt fallback |
For MCP execute, read-only API calls are okay. MCP OAuth permissions are chosen during the initial OAuth authorization (or re-authorization), not requested per API call; operations outside the granted scopes will fail. Assume MCP access is read-only unless the user explicitly confirms broader scopes. Ask the user before POST, PUT, PATCH, or DELETE, especially for DNS records, R2 buckets, tunnels, rulesets, WAF, Workers, and access/security settings.
Cloudflare MCP (preferred: pi-mcp-adapter)
The server is configured globally in ~/.config/mcp/mcp.json as cloudflare (https://mcp.cloudflare.com/mcp, OAuth handled by the adapter). Call tools through the mcp proxy tool; args is a JSON string:
mcp({ search: "cloudflare" }) # discover tools/schemas
mcp({ tool: "cloudflare_docs", args: "{\"query\":\"R2 bucket jurisdiction API\"}" })
mcp({ tool: "cloudflare_search", args: "{\"code\":\"async () => Object.keys(spec.paths).filter(p => p.includes('/workers/scripts'))\"}" })
mcp({ tool: "cloudflare_execute", args: "{\"code\":\"async () => { const r = await cloudflare.request({ method: 'GET', path: `/accounts/${accountId}/workers/scripts` }); return r.result; }\"}" })
If a call fails with "Re-authentication required", start OAuth and give the user the returned URL:
mcp({ action: "auth-start", server: "cloudflare" })
The browser redirects to a localhost URL that fails to load; the user copies the full URL and you complete with mcp({ action: "auth-complete", server: "cloudflare", args: "{\"redirectUrl\":\"...\"}" }).
Cloudflare MCP via mcporter (fallback)
Use only when the native adapter is unavailable. The helper script wraps npx --yes mcporter@latest so the skill uses the latest MCPorter transport/OAuth support.
./scripts/mcp.sh install
./scripts/mcp.sh auth
./scripts/mcp.sh status
./scripts/mcp.sh list
Useful MCP calls:
./scripts/mcp.sh docs "R2 bucket jurisdiction API"
./scripts/mcp.sh search 'async () => Object.keys(spec.paths).filter(p => p.includes("/workers/scripts"))'
./scripts/mcp.sh execute 'async () => { const r = await cloudflare.request({ method: "GET", path: `/accounts/${accountId}/workers/scripts` }); return r.result; }'
Use CLOUDFLARE_MCP_SERVER when the MCPorter server name is not cloudflare-api.
Cloudflare API Reference Fallback
For full API documentation when MCP is unavailable, fetch the LLM-optimized reference:
curl -s https://developers.cloudflare.com/llms.txt
Use product-specific llms.txt files from that index when possible.
Direct API Script Setup
1. Get Your API Token
- Go to dash.cloudflare.com/profile/api-tokens
- Create a token with required permissions:
- Zone:Read - List domains
- DNS:Edit - Manage DNS records
- Account:Cloudflare Tunnel:Edit - Manage tunnels
- Copy the token
2. Configure
echo "YOUR_API_TOKEN" > ~/.cloudflare_token
chmod 600 ~/.cloudflare_token
export CLOUDFLARE_API_TOKEN="YOUR_API_TOKEN"
3. Test Connection
./scripts/setup.sh
Commands
Zones (Domains)
./scripts/zones/list.sh
./scripts/zones/list.sh --json
./scripts/zones/get.sh example.com
DNS Records
./scripts/dns/list.sh example.com
./scripts/dns/list.sh example.com --type A
./scripts/dns/list.sh example.com --name api
./scripts/dns/create.sh example.com \
--type A \
--name api \
--content 1.2.3.4 \
--proxied
./scripts/dns/create.sh example.com \
--type CNAME \
--name www \
--content example.com \
--proxied
./scripts/dns/update.sh example.com \
--name api \
--type A \
--content 5.6.7.8
./scripts/dns/delete.sh example.com --name api --type A
Tunnels
./scripts/tunnels/list.sh
./scripts/tunnels/create.sh my-tunnel
./scripts/tunnels/configure.sh my-tunnel \
--hostname app.example.com \
--service http://localhost:3000
./scripts/tunnels/token.sh my-tunnel
./scripts/tunnels/delete.sh my-tunnel
R2 Buckets
./scripts/r2/list.sh
./scripts/r2/list.sh --json
./scripts/r2/get.sh my-bucket
./scripts/r2/create.sh my-bucket
./scripts/r2/create.sh my-bucket --location weur
./scripts/r2/create.sh my-bucket --storage-class InfrequentAccess
./scripts/r2/create.sh my-bucket --no-jurisdiction
./scripts/r2/create.sh my-bucket --jurisdiction eu
./scripts/r2/delete.sh my-bucket
⚠️ Jurisdiction is critical: All R2 commands default to --jurisdiction eu for GDPR compliance. The Cloudflare API completely hides buckets in other jurisdictions — EU-jurisdiction buckets are invisible without the cf-r2-jurisdiction: eu header, and vice versa. If a bucket seems to be missing, check you're using the right jurisdiction. Use --no-jurisdiction to interact with global/default-jurisdiction buckets.
Token Permissions
| Feature | Required Permission |
|---|
| List zones | Zone:Read |
| Manage DNS | DNS:Edit |
| Manage tunnels | Account:Cloudflare Tunnel:Edit |
| Manage R2 buckets | Workers R2 Storage:Write |
Create token at: dash.cloudflare.com/profile/api-tokens
Common Workflows
Point subdomain to server
./scripts/dns/create.sh mysite.com --type A --name api --content 1.2.3.4 --proxied
Set up tunnel for local service
./scripts/tunnels/create.sh webhook-tunnel
./scripts/tunnels/configure.sh webhook-tunnel \
--hostname hook.mysite.com \
--service http://localhost:8080
TUNNEL_ID=$(./scripts/tunnels/list.sh --name webhook-tunnel --quiet)
./scripts/dns/create.sh mysite.com \
--type CNAME \
--name hook \
--content ${TUNNEL_ID}.cfargotunnel.com \
--proxied
TOKEN=$(./scripts/tunnels/token.sh webhook-tunnel)
cloudflared tunnel run --token $TOKEN
Create an R2 bucket in a specific region
./scripts/r2/create.sh my-assets --location weur
./scripts/r2/get.sh my-assets
Output Formats
| Flag | Description |
|---|
--json | Raw JSON from API |
--table | Formatted table (default) |
--quiet | Minimal output (IDs only) |
Troubleshooting
| Error | Solution |
|---|
| "No API token found" | Run setup or set CLOUDFLARE_API_TOKEN |
| "401 Unauthorized" | Check token is valid |
| "403 Forbidden" | Token missing required permission |
| "Zone not found" | Verify domain is in your account |