Skip to content

Cloudflare API MCP – Session Learnings

Documentation of learnings from using the Cloudflare API MCP (Cursor) for Workers and Secrets Store. Use this as a reference when scripting against the API via MCP or debugging failures.


1. MCP Overview

  • Server: user-cloudflare-api (shows as "cloudflare-api" in Cursor).
  • Tools:
    • search – Query the Cloudflare OpenAPI spec. You get spec.paths, operation schemas, request bodies, parameters. Use it to find endpoints and payload shapes before calling the API.
    • execute – Run JavaScript that calls the API via cloudflare.request(options). You have accountId in scope; when the user has multiple accounts, you must pass the account_id parameter to execute or the call is rejected.

How to tell the MCP is being used: In the composer/agent UI you’ll see tool calls for user-cloudflare-api / search or execute. Results (endpoint lists, account/worker/secret data, or Cloudflare error codes) are only possible if the MCP was called.


2. Workers

Creating a worker via API

  • Endpoint: PUT /accounts/{account_id}/workers/scripts/{script_name}
  • Body: multipart/form-data with:
    • metadata part: JSON. For a classic worker use { "body_part": "script" }. For an ES module worker the API may reject with Unexpected token 'export' depending on configuration.
    • script part (classic): Content-Type: application/javascript, body = worker code.

Classic worker example (works):

js
addEventListener("fetch", (event) => {
  event.respondWith(
    new Response("Hello from Worker!", { headers: { "Content-Type": "text/plain" } }),
  );
});

Important: Use the classic format (body_part: "script", single script part) if you get syntax errors with export default / module format.

Multiple accounts

If you don’t pass account_id and the user has more than one account, the MCP returns something like:

Multiple accounts available. Please specify account_id parameter.

Always pass account_id in the execute arguments when you have multiple accounts.


3. Secrets Store

Creating a store

  • Endpoint: POST /accounts/{account_id}/secrets_store/stores
  • Body: A single object { "name": "your-store-name" }. The OpenAPI spec shows an array, but the API accepted a single object in practice; sending an array can lead to invalid_json_body.
  • Limits: Each account has a maximum number of stores (e.g. one on free/standard). If you hit it you get:
    • 1003: maximum_stores_exceeded
  • You cannot choose the store ID; Cloudflare assigns it.

Creating a secret in a store

  • Endpoint: POST /accounts/{account_id}/secrets_store/stores/{store_id}/secrets
  • Body: An array of secret objects, e.g.:
    json
    [
      {
        "name": "MY_SECRET",
        "value": "the-secret-value",
        "scopes": ["workers"],
        "comment": "Optional description"
      }
    ]
  • Required fields: name, value, scopes. value is write-only and never returned by the API.
  • Scopes: e.g. ["workers"], ["workers","ai_gateway","dex","access"] depending on which products should use the secret.

Editing a secret (including value)

  • Endpoint: PATCH /accounts/{account_id}/secrets_store/stores/{store_id}/secrets/{secret_id}
  • Documented body: name (required), comment, scopes. The public OpenAPI spec does not document a value field for PATCH.
  • Observed behavior: Sending PATCH with various bodies (only name, or with value/comment/scopes) consistently returned 1001: invalid_json_body. So we could not reliably change the secret value via this endpoint in this session.
  • Practical options:
    1. Dashboard: Edit the secret and its value in Cloudflare Dashboard → Secrets Store.
    2. Delete + recreate: DELETE the secret, then POST a new secret with the same name and the new value. There will be a short period where the secret does not exist; the new secret will have a new secret_id.

4. Authentication and token scope

  • 10000 Authentication error: The token used by the MCP does not have access to the requested resource. Common causes:
    • Token not authorized for that account (check Account Resources in the token).
    • Token missing permission for that product (e.g. Secrets Store needs “Secrets Store” → Edit).
  • 9109 Unauthorized: Returned when calling sensitive endpoints such as user API token management (/user/tokens, /user/tokens/permission_groups). Normal API tokens typically cannot list or update user tokens; that’s expected.
  • Reconnecting after token changes: Updating the token in the Cloudflare dashboard does not update the MCP’s connection. Log out and log back in (or re-enter the token) in Cursor’s MCP settings so the new permissions/account scope are used.

5. Common API error codes seen

CodeMessage / meaning
10000Authentication error (wrong account or missing permission)
1001invalid_json_body (wrong shape or format of request body)
1003maximum_stores_exceeded (account at store limit)
9109Unauthorized (e.g. user token management)