Refine AIRefine Docs
MCP server

Errors & limits

Knowing how the server pushes back helps you build resilient integrations. Here’s every limit it enforces and how failures surface.

Limits at a glance#

LimitValue
Active API keys per account20
Requests per key60 / minute
Monitored prompts per brand25
Max request duration300 seconds

Authentication errors#

Requests without a valid key are rejected with HTTP 401 before any tool runs. Common causes:

  • Missing or malformed Authorization header.
  • A key that doesn’t start with rfn_live_.
  • A key that has been revoked, or whose brand was deleted.

See Authentication to fix these.

Tool errors#

Once you’re authenticated, errors are returned inside the MCP response with isError: true rather than as an HTTP error — so your client sees a clean, human-readable message:

error result
{
  "content": [
    { "type": "text", "text": "Rate limit exceeded. Try again in a minute." }
  ],
  "isError": true
}

You’ll see these for:

  • Plan gating — calling a tool your plan doesn’t cover. The message names the required plan and links to upgrade.
  • Rate limiting — more than 60 requests in a minute on one key.
  • Validation — invalid arguments (e.g. a malformed UUID or a color that isn’t a hex code).
  • Not found — referencing a prompt, tag or competitor that doesn’t belong to the key’s brand.

Rate limiting#

Each key is limited to 60 requests per minute on a fixed window. When you exceed it, calls return the rate-limit error above until the window resets. Back off and retry after a short pause — a second is plenty.

Content generation rules#

Content generation is asynchronous: generate_content returns a contentId immediately, and you poll get_content until its status is complete. A few rules apply:

  • Monthly generation quotas apply per content type, on top of the Autopilot plan requirement.
  • Any sourceUrls you pass are validated against SSRF — only public http/https URLs are fetched. Private IPs, localhost and cloud metadata endpoints are rejected.

Polling tip

Poll get_content every few seconds rather than in a tight loop — generation takes time, and tight polling burns your rate-limit budget. The progress field tells you how far along it is.