The auth ladder (detect in this order)
Pick one transport at the start of a session. Never mix, never switch mid-session, never narrate the choice.1
MCP (preferred)
If ContentHero MCP tools are visible in your toolset, use them. Match loosely across namespaces:
mcp__contenthero__* (hosted OAuth at https://mcp.contenthero.ai), mcp__contenthero-local__* (a local stdio build), or any mcp__*contenthero*__* variant your host assigns. OAuth or a configured key handles auth. No key handling in chat.2
CLI
If no MCP is visible, use the
contenthero CLI when contenthero auth status exits 0, or when CONTENTHERO_API_KEY is set in the environment. The pattern is contenthero <noun> <verb>, JSON on stdout by default. Add --cost to preview the cost and --no-wait plus contenthero generation wait <id> for non-blocking polling.3
Raw /api/v1
Last resort, only when neither MCP nor the CLI is available but the user has an API key and an HTTP client. Bearer the key against
https://app.contenthero.ai/api/v1.4
Neither
Tell the user once: “To use ContentHero, connect the MCP server (
https://mcp.contenthero.ai) or install the CLI: npm install -g @contenthero/cli then contenthero login.”Hard rules
- Ground every draft. When you draft copy, ground it in the user’s real context (their outliers, brand voice, and past posts), and get their approval before publishing. Grounded drafting in the user’s voice is the goal; generic ungrounded copy is not on-brand. See how it works.
- One transport per session. Detect once. If an operation is not exposed in your detected transport, tell the user. Do not switch transports to reach it.
- Never publish or schedule without explicit approval of the final content.
- Preview cost before a large or batched generation and show it. MCP passes
getCost: trueon the generate call. CLI uses--cost. It charges nothing. - Be concise. Report the result (the media, the post link, the cost), not the plumbing (output ids, raw payloads, transport choice).
The failure mode to avoid
Do not hand the user acurl script as a substitute for doing the work. If you can see MCP tools, call them. If the CLI is installed and authed, run it. A script that the user cannot run because no key was ever provisioned is not a deliverable. Verify auth, then execute.
Install the agent skills
The fastest way to drive ContentHero well is to install the official skills, which encode the workflows and our model-specific prompt craft.contenthero-ai/skills. It includes three skills: contenthero-generate (generation), contenthero-pipeline (research to published, the hero), and contenthero-brand (your context).
Async, chaining, and scopes
- Async generation:
generate_*runs a smart-wait (about 50s) then hands back anoutputIdif the render is still going. Poll withget_generation_status, or block withwait_for_generation. TheoutputIdis always returned, so keep polling. - Chaining: a reference (start frame, image input) accepts a raw URL or a ContentHero output-id token
<uuid>-<N>(the Nth variation of a prior output). The server resolves either, type-checks it, and scopes it to the owner. Prefer passing the output-id straight through rather than re-uploading. - Scopes: keys are scope-gated (generation,
publish:write,pipeline:write,brandkit:read/brandkit:write). If a call fails on scope, tell the user which scope to grant in API Keys settings. Do not work around it.