Endpoints
Both endpoints behave the same way at the protocol level:
Authentication
OAuth
OAuth is the recommended path for interactive MCP clients. Add the server URL without headers; a compatible client discovers Cactal’s authorization server, opens the Cactal sign-in and consent screens, and refreshes access automatically:
Clients request
offline_access as well to receive refresh tokens. Access tokens are signed JWT access tokens (typ: at+jwt) with the Cactal authorization server as issuer and the endpoint’s URL as their exact audience, so a token issued for one endpoint is rejected by the other. Cactal session tokens are never accepted as MCP tokens.
Disconnect
Disconnect an app under Connected apps in Account settings; its next call fails. See AI connections.API keys
For unattended clients, CI, or clients without OAuth support, send an API key on either endpoint:POST /v1/apiKeys. See Create an API key and Authentication.
Browser session cookies are always rejected with 401; the MCP endpoints accept only bearer OAuth tokens or bearer API keys.
Connect a client
Claude and ChatGPT
See Use Cactal in ChatGPT and Claude.Claude Code, Cursor, and other clients
If you connected Cactal in Claude, Claude Code already has it. Otherwise, add the server to your client:The generic example shows the API-key option. Replace
$CACTAL_API_KEY with your key, or use your client’s secret storage so it never lands in a committed file.Verify the connection by asking your agent which Cactal organizations and websites it can use. It answers with
profile_get.Tools
Tools are generated from public API operations. A tool’s name is the operation id with every character outsidea-z, A-Z, 0-9, _, and - replaced by _:
Each tool’s input schema is the operation’s request schema, and its metadata carries the HTTP method, path, and required capability. A tool’s title and description are the same authored prose as its API reference operation, so the two surfaces cannot drift apart.
tools/list returns only the tools the connection or key can call. Calling a tool outside that access fails as if the tool does not exist.
The initialize response carries short server instructions that point the agent to skills_read, profile_get, and the docs tools. Clients that support MCP instructions surface them to the agent automatically.
What the default endpoint includes
The default endpoint never includes account administration: API keys, members, invitations, website editors, billing, the audit log, organization lookups, settings, and deletion, website delete, restore, and transfer, or presigned uploads (
websiteAssets_beginUpload and websiteAssets_finalize). Agents on the default endpoint import files by URL with websiteAssets_importFromUrl and find their organization with profile_get. Everything else is on the full-access endpoint and the REST API.
Docs, skills, and profile
These read-only operations are available over REST and as MCP tools on both endpoints:
The docs operations serve the published documentation, the same content as every surface in AI-readable docs.
Skills
skills_read returns Cactal’s guidance for agents: the same skills the built-in Cactal agent uses, covering platform rules, the tool workflow, and craft defaults such as design direction, copywriting, CMS modeling, and publishing. The tool’s description lists every skill, and the server instructions tell agents to read the matching skill before acting, for example source-editing-workflow before any source edit.
The skills always match the tools you see, because the server serves them. For agents that find Cactal on the web, https://cactal.ai/skill.md and https://cactal.ai/.well-known/agent-skills/index.json point to the MCP server and skills_read in the Agent Skills discovery format.
Outside Cactal
Agents can look at the web beyond your sites the way the built-in Cactal agent does. Each call names one of your websites; that website’s organization pays in AI credits for the vendor work behind it.
A contact-sheet photo can be imported into the website by its number: pass
{ "photo": 12 } in websiteAssets_importFromUrl instead of copying the long image link. Numbers belong to the connection that saw them and last at least 24 hours. Agents should request a business’s photos (images: true) only when the user confirmed the business is theirs, and ask before importing from a site that is not theirs.
Profile
profile_get returns the person the credential acts for (a stable id, plus name and email) and the organizations it can work in. An organization lists websites only when access is limited to those websites. Pass an organization id to websites_list or websites_create.
Edit leases
Source writes run under the website’s single edit lease, and Cactal takes it for you when a write has noleaseToken. If another editor is mid-change, the write fails with a conflict; ask the user before taking over with websiteSourceCode_lease_acquire.
Publish what you checked
websiteSourceCode_head_publish accepts an optional version. Pass the version websiteSourceCode_head_check returned; if the draft changed after that check, publishing refuses with a conflict (The draft changed after it was checked), so a draft nobody checked never goes live.
Asset library
websiteAssets_list accepts search and category filters over each asset’s
one-line description and category, so an agent can find “the logo” or “the
team photo” without opening every file. When an agent imports through
websiteAssets_importFromUrl, or uploads through websiteAssets_beginUpload on
the full-access endpoint, it should pass description and category itself;
websiteAssets_update fixes them later. Reading an image with
websiteAssets_get returns the picture itself to clients that render images,
the same view the built-in Cactal agent gets. websiteAssets_removeBackground
derives a new transparent PNG from a ready image and returns it, picture
included; transparentShare on any image row confirms real transparency.
Image generation
Website content editors can usemediaGeneration_catalog and
mediaGeneration_generate to create up to eight images in one concurrent batch.
Generation can use ready same-website images as references. Successful outputs
are ordinary CDN-backed website assets, and compatible clients receive visual
image content alongside the structured result. idempotencyKey is optional:
send the same key when retrying one request so it never generates or bills
twice, and omit it for a new request. See Generate website
images.
Product feedback
When the user explicitly asks to send Cactal product feedback, an authenticated MCP principal can usefeedback_submit. Briefly describe what happened and what would have made the experience better. An agent must pass authorKind: "agent" even when its OAuth connection acts as the signed-in user; Cactal stores the authenticated principal, authored-by kind, and MCP channel separately. Feedback must never contain secrets or unnecessary sensitive data. See Submit product feedback.
Approvals
Cactal tools carry MCP annotations so ChatGPT, Claude, and other hosts can decide when to ask the user before a tool runs. Cactal adds no approval step of its own over MCP; the host’s approval settings apply.
The built-in Cactal agent still pauses for an in-conversation approval before publishing or any other live change. For agents you run yourself, see Agent-safe publishing.
Errors, rate limits, and audit
A failed tool call returns a result withisError: true. Its payload is the same error shape the REST API uses:
Tool result payload on failure
kind values and their meanings match the REST API exactly. See Errors. Rate limits are shared with REST for the same principal, and an exhausted bucket returns kind: "rate_limited" with retryAfterSeconds. See Rate limits.
Tool calls run through the same audit pipeline as REST. Operations that write organization audit events, such as website lifecycle, editor grants, API keys, domains, and members, write identical events over MCP. Actions through an AI connection are attributed to the person who connected it, and actions through an API key to that key. Review them with GET /v1/organizations/{organizationId}/audit-log. Plan purchases and checkouts happen in the dashboard and are never available over MCP.
Your first session
The steps below sketch the JSON-RPC calls your client makes. MCP clients perform the standardinitialize handshake automatically before these requests; in a client, just ask the agent in plain language and it makes the same calls.
1
Find your organization
id.2
Create a website
id and draft headVersion.3
Read the matching skills
Call
skills_read with source-editing-workflow before editing source, and with skills such as design-direction or copywriting when the agent chooses the look or the words.4
Edit the draft
Write pages and components with
websiteSourceCode_files_upsert or websiteSourceCode_files_strReplace, without a leaseToken. Cactal takes the edit lease for you, and every write becomes a new draft version.5
Check, then publish
Run the quality gate with
websiteSourceCode_head_check and note the version it returns. Publish with websiteSourceCode_head_publish, passing the websiteId and that version. Poll websiteSourceCode_deployment_status until the deployment reaches ready.6
Set the favicon
Import a PNG, SVG, or ICO image from a public URL with
websiteAssets_importFromUrl, then call websiteFavicons_set with its assetId. If the user already uploaded it, find the ready image with websiteAssets_list first. The favicon is current website state, so it applies immediately and needs no lease or publish.7
Open the website
Call
websiteDomains_list to find the website’s platform host, https://<label>.cactal.app, and open it.Publishing and serving on a Cactal platform domain is free. A site counts toward your plan when an organization owner enables custom domains for it. Sites on Cactal domains are unlimited and free. See Plans and limits.
Advanced: full access
https://api.cactal.ai/v1/mcp/full exposes every public operation with MCP support, including the account administration the default endpoint leaves out. Choose it only when an agent genuinely needs those operations; the default endpoint covers working on websites.
Add it on purpose: as a custom connector in Claude, in ChatGPT developer mode, or in a Claude Code or Cursor config:
Claude Code