CineRads

CineRads for agents

Let an agent run your TikTok for you.

CineRads is fully drivable by a coding agent. Mint an API key, point Claude Code or Codex at the CineRads MCP server, and it can go from a URL to a scheduled, branded TikTok slideshow or uploaded MP4 - then learn from what performs and do it again.

What it is

One thin, declarative MCP over the real pipeline.

The CineRads MCP server is a thin wrapper over the same edge functions the app uses. Every tool maps 1:1 to a function with its exact contract names, so an agent drives the identical pipeline you would by hand: hooks → copy → images → branded slideshow → render → publish → schedule, plus local/hosted MP4 video upload and analytics. No parallel orchestration layer, no second source of truth.

Sync-render contract: trigger_slideshow_render blocks until the deck reaches complete — there is no separate poll step. Once it returns, the deck is ready to publish.

Authentication

cra_ API keys, scoped.

Mint a key inside CineRads (it starts with cra_). Keys are sent as the x-api-key header and carry explicit scopes. Key minting is JWT-only by design, so a key can never mint other keys.

  • slideshow:writeCreate/update/render slideshows, manage automations, publish.
  • slideshow:readList and fetch your slideshows.
  • analytics:readRead per-hook analytics and account/post performance.

A 403 means the key is missing the required scope; a 401 means it is invalid or expired.

Install

Add the MCP server to your agent.

The server is published on npm (@cinerads/mcp-server). Pick your platform, run the command or paste the JSON, replace cra_your_key_here with your key, restart.

Claude Code

claude mcp add cinerads -e CINERADS_API_KEY=cra_your_key_here -e CINERADS_BASE_URL=https://nuodqvvgfwptnnlvmqbe.supabase.co/functions/v1 -- npx -y @cinerads/mcp-server

Run in your terminal, then restart Claude Code. (Teams: put the JSON from “Other” in a project .mcp.json instead.)

Codex

codex mcp add cinerads --env CINERADS_API_KEY=cra_your_key_here --env CINERADS_BASE_URL=https://nuodqvvgfwptnnlvmqbe.supabase.co/functions/v1 -- npx -y @cinerads/mcp-server

Run in your terminal, then restart Codex. (Manual alternative: [mcp_servers.cinerads] in ~/.codex/config.toml.)

Cursor

{
  "mcpServers": {
    "cinerads": {
      "command": "npx",
      "args": [
        "-y",
        "@cinerads/mcp-server"
      ],
      "env": {
        "CINERADS_API_KEY": "cra_your_key_here",
        "CINERADS_BASE_URL": "https://nuodqvvgfwptnnlvmqbe.supabase.co/functions/v1"
      }
    }
  }
}

Paste into ~/.cursor/mcp.json (global) or .cursor/mcp.json (project) — or Cursor Settings → MCP → New MCP Server — then reload Cursor.

Windsurf

{
  "mcpServers": {
    "cinerads": {
      "command": "npx",
      "args": [
        "-y",
        "@cinerads/mcp-server"
      ],
      "env": {
        "CINERADS_API_KEY": "cra_your_key_here",
        "CINERADS_BASE_URL": "https://nuodqvvgfwptnnlvmqbe.supabase.co/functions/v1"
      }
    }
  }
}

Paste into ~/.codeium/windsurf/mcp_config.json (Windsurf Settings → Cascade → MCP), then refresh the plugins list.

Any other MCP client

{
  "mcpServers": {
    "cinerads": {
      "command": "npx",
      "args": [
        "-y",
        "@cinerads/mcp-server"
      ],
      "env": {
        "CINERADS_API_KEY": "cra_your_key_here",
        "CINERADS_BASE_URL": "https://nuodqvvgfwptnnlvmqbe.supabase.co/functions/v1"
      }
    }
  }
}

Any MCP-compatible client takes this mcpServers JSON in its config — paste, set your key, restart. Or call the API directly: send your key as the x-api-key header.

Cookbook

The actual production recipes.

These are the paths a user or agent should follow. The same MCP server covers generated decks, slideshow-lab style batches, baked HTML or Canva pages, library scheduling, MP4 publishing, and performance learning.

Generated slideshow from a URL

A rendered draft deck inside CineRads.

Use when the product URL is the source of truth and CineRads should write the hook, copy, and image matching.

  1. 1scrape_product for the website or product URL.
  2. 2list_products and pick the confirmed product id.
  3. 3generate_hooks, then pick the strongest hook.
  4. 4generate_slide_copy with the chosen carousel_style and soft_cta.
  5. 5assign_slide_images, create_slideshow, then trigger_slideshow_render.
  6. 6Review the /s link or deck in app before any TikTok publish.
Onboard this product from a URL: <url>. Scrape it, pick the confirmed product, generate 5 hooks, write a 6-slide tips_list deck, assign images, create the slideshow, render it, and leave it as a draft for review. Do not publish.

Slideshow-lab style batch

A batch of original, pattern-informed decks with share links and a manifest.

Use when you have research, competitor patterns, or a slideshow lab and want to recreate the production pipeline without copying source content.

  1. 1Read the lab/research and extract hook mechanics, pacing, slide count, visual rules, and CTA mechanics.
  2. 2Write original hooks and slide copy. Do not rewrite competitor slides.
  3. 3Choose the production lane: CineRads-native deck, HTML-rendered page images, or full-res Canva export.
  4. 4For HTML/Canva lanes, upload full-res 1080x1920 page images with upload_image and create imageOnly slideshows.
  5. 5Verify every /s link, record image dimensions, CTA, caption, and QA verdict in a manifest.
  6. 6Queue only approved full-res decks with queue_slideshows on a library automation.
Run a slideshow-lab style batch from <research folder>. Extract only the reusable mechanics, write original copy, choose the right lane for each deck, build full-res drafts, upload imageOnly decks when pages are pre-rendered, verify every /s link, and return a manifest with slideshow_id, share link, dimensions, caption, CTA, and QA notes. Do not queue until I approve.

HTML or Canva full-res page images

A CineRads image-only slideshow that preserves the exact page design.

Use when another renderer already produced final 9:16 PNG/JPG pages, including HTML slide renderers or Canva exports.

  1. 1Confirm pages are full-resolution, ideally 1080x1920 or higher.
  2. 2Upload each ordered page with upload_image.
  3. 3create_slideshow with imageOnly:true per slide, showPill:false, and overlay disabled.
  4. 4Open or fetch the public /s link and check ordering, crop, image load, and CTA readability.
  5. 5Save a manifest before scheduling.
I have full-res page images in <folder>. Upload each page, create an image-only slideshow with showPill false and overlay disabled, verify the public /s link, and return a manifest. Do not queue thumbnail or low-res images.

Library scheduling

Approved pre-built decks post on a schedule as TikTok inbox drafts.

Use after decks are already rendered or image-only and explicitly approved.

  1. 1list_automations and confirm or create an automation with content_source:'library'.
  2. 2Use post_mode:'MEDIA_UPLOAD' unless the user explicitly asks for DIRECT_POST.
  3. 3list_automation_queue before adding anything.
  4. 4queue_slideshows with the approved slideshow ids.
  5. 5Return the new queue state and do not silently direct-post.
Queue these approved slideshow ids on <automation_id> as TikTok inbox drafts: <ids>. Confirm content_source is library and post_mode is MEDIA_UPLOAD, show the queue before and after, then run queue_slideshows. Never use DIRECT_POST unless I say so.

MP4 video publish

A local or hosted MP4 becomes a CineRads generation and can be posted to TikTok.

Use when the final creative is a rendered MP4, not a slideshow row.

  1. 1Use upload_video for an absolute local .mp4 path or ingest_external_video_url for a hosted MP4.
  2. 2Pass product_id and persona_id if the account has multiple options.
  3. 3publish_video_tiktok with privacy_level:'SELF_ONLY' by default.
  4. 4Poll get_publish_status and report generation_id, publish_id, status, and errors.
Publish this MP4 through CineRads: <absolute path or hosted URL>. Use upload_video for local files or ingest_external_video_url for hosted video, then publish_video_tiktok with privacy_level SELF_ONLY unless I explicitly approve public posting. Poll status and report ids/errors.

Performance learning loop

New drafts based on what already worked.

Use after posts have enough performance signal.

  1. 1get_post_performance for recent posts and get_hook_analytics for hook-level signal.
  2. 2Identify winning hook mechanics, visual formats, CTA styles, and slide counts.
  3. 3Create new drafts that reuse patterns, not exact old copy.
  4. 4Render and return /s links for review before publish or queue.
Run the performance learning loop. Pull recent get_post_performance and get_hook_analytics, identify the best hooks, CTAs, visuals, and slide counts, then create 3 new rendered draft decks that reuse the winning patterns with original copy. Return /s links and do not publish.

Tools

The toolset, by lifecycle stage.

Every tool is a thin wrapper over a CineRads edge function. An agent threads ids forward — product → hook → copy → images → slideshow → publish → analytics.

Discover

Find the product and what's already working.
  • list_productsList the products in your account.
  • scrape_productScrape a URL into a product (name, description, images).
  • list_use_casesBrowse ready-made use-case recipes to start from.
  • list_tiktok_connectionsList connected TikTok accounts.
  • list_slideshowsPaginated list of your decks.
  • get_slideshowFetch one deck with image URLs resolved.
  • get_brand_profileRead the brand-voice profile (audience, offer, voice do/don't, pillars).
  • list_presetsList saved generation configs.
  • list_slideshow_templatesList saved brand frames (full settings + skeleton).
  • get_slideshow_templateFetch one saved brand frame by id.
  • get_product_cta_imagesRead a product's reusable CTA image set.
  • list_collectionsList image collections (the buckets assign_slide_images draws from).
  • list_collection_imagesPaginated images inside one collection, each with a hosted URL.

Build

Generate hooks, copy, images, and a branded deck.
  • generate_hooksHook lines for a product/prompt — pick the strongest.
  • generate_slide_copyBody/CTA copy from a hook (tone, length, style, research, soft_cta).
  • assign_slide_imagesRank + assign collection images to each slide.
  • generate_slide_imageCustom text-to-image for any slide from your own prompt.
  • generate_persona_imageRealistic ICP selfie for the hook slide.
  • regenerate_slide_imageAI-regen one slide image (admin-gated server-side).
  • set_brand_profileFill the brand-voice profile copy-gen studies for on-brand copy.
  • set_brand_referencesAttach swipe copy / competitor research for style (never copied).
  • create_slideshowCreate a draft with full customization (text, font, logo, overlays).
  • update_slideshowPatch name/settings/slides/status of a deck.
  • save_presetSave a full generation config to reuse across runs.
  • apply_presetReuse a saved config so a brand look is remembered.
  • create_slideshow_templateSave a reusable brand frame to stamp at deck-build time.
  • upload_imageUpload a local logo/diagram/screenshot, get a hosted URL.
  • create_image_collectionCreate a named bucket of brand/product images.
  • upload_collection_imageAdd a local image into a collection (deduped by content hash).
  • set_product_cta_imagesSet a product's reusable CTA images (auto-used on CTA slides).
  • upload_videoUpload a local MP4 into CineRads as a completed generation.
  • ingest_external_video_urlIngest a hosted MP4 URL as a completed generation.

Publish

Render, post to TikTok, or schedule it on a recipe.
  • trigger_slideshow_renderRender a draft on the VPS. Blocks until status = complete (sync).
  • publish_slideshow_tiktokPublish a rendered deck to a connected TikTok account.
  • publish_video_tiktokPublish a completed video generation. Defaults to SELF_ONLY.
  • get_publish_statusPoll a publish by id/slideshow, or all.
  • create_automationRecurring generated or library posting recipe.
  • update_automationEdit a recurring recipe (cadence, style, branding).
  • list_automationsList your recurring posting recipes.
  • list_automation_queueList queued pre-built decks for a library automation.
  • queue_slideshowsAppend approved slideshow ids to a library automation queue.
  • remove_queued_slideshowRemove rejected or wrong slideshow ids from a queue.
  • delete_automationStop and remove a recurring recipe.

Learn

Read performance and make more of what wins.
  • get_hook_analyticsWhich hook works — performance grouped by hook.
  • get_post_performancePer-post views/likes/shares for published decks.
  • get_account_insightsAccount-level TikTok performance summary over time.

End to end

From a URL to a scheduled, learning loop.

A realistic agent run. Each numbered step is one tool call; ids thread forward.

# Path A: URL -> generated slideshow draft
scrape_product            { url: "https://acme.com" }
  -> products[0].id
generate_hooks            { product_id, prompt: "why teams switch to us", count: 5 }
  -> pick hooks[0].text / hooks[0].id
generate_slide_copy       { hook_text, product_id, carousel_style: "tips_list",
                            copy_length: "short", research_mode: "always",
                            soft_cta: "link in bio for the free trial" }
  -> slides[]
assign_slide_images       { slides, product_id }
  -> merge image assignments back onto slides
create_slideshow          { name, product_id, hook_id, slides,
                            settings: { text: { color: "#0B1F3A" }, fontFamily: "Poppins",
                                        logo: { url: "...", enabled: true,
                                                position: "bottom-right", sizePct: 12 } } }
  -> slideshow.id
trigger_slideshow_render  { slideshow_id }            -> status: "complete"

# Path B: HTML/Canva full-res page images -> image-only slideshow
upload_image              { path: "/abs/deck-01/page-01.png" } -> url
create_slideshow          { name, product_id,
                            slides: [{ id:"s1", type:"hook", order:1,
                                       text:"", imageId:"custom-upload",
                                       customImageUrl:url, imageOnly:true }],
                            settings: { showPill:false,
                                        overlay:{ enabled:false, opacity:0 } } }
  -> slideshow.id and /s/<id> review link

# Path C: schedule approved pre-built decks as drafts
create_automation         { product_id, connection_id, content_source:"library",
                            post_mode:"MEDIA_UPLOAD", posts_per_day:1,
                            post_times:["09:00"], timezone:"America/Los_Angeles",
                            hashtags:["consulting","caseinterview"], force_hashtags:true }
list_automation_queue     { automation_id }
queue_slideshows          { automation_id, slideshow_ids:["..."] }

# Path D: local MP4 -> TikTok video publish
upload_video              { path:"/absolute/path/final.mp4", product_id, persona_id }
  -> generation_id
publish_video_tiktok      { generation_id, connection_id, title:"...", privacy_level:"SELF_ONLY" }
get_publish_status        { generation_id }

# Learn
get_post_performance      { limit: 50 }   -> top decks by views
get_hook_analytics        { limit: 50 }   -> best hooks
# feed the winners back into step 2 and repeat

Copy / paste

Prompts to hand your agent.

Once the MCP server is connected, paste any of these straight into Claude Code or Codex.

Audit my CineRads agent setup. Use list_products, list_tiktok_connections, list_automations, list_slideshows, get_post_performance, and get_account_insights. Tell me what can be generated, what can be scheduled, what is already queued, and what blockers remain. Do not create, publish, or queue anything.

Onboard this product from a URL: <url>. Scrape it, pick or create the brand profile, generate 5 hooks, write a 6-slide tips_list deck, assign images, create the slideshow, render it, and leave it as a draft for review. Do not publish until I approve.

Run a slideshow-lab style batch from <research folder>. Extract only reusable mechanics, write original copy, choose the right lane for each deck, build full-res drafts, upload imageOnly decks when pages are pre-rendered, verify every /s link, and return a manifest with slideshow_id, share link, dimensions, caption, CTA, and QA notes. Do not queue until I approve.

Build a baked image slideshow from local HTML/PNG output. I have one folder per deck at <folder>, with 1080x1920 page images in order. Upload each page with upload_image, create an image-only slideshow with showPill false and overlay disabled, verify the public /s/ link, and save the slideshow ids. Do not queue thumbnail or low-res images.

Take my full-resolution Canva exports from <folder>. For each deck, upload the page PNGs, create an image-only slideshow, verify the /s/ link, set the provided caption if I give one, and return a manifest with deck name, slideshow_id, share link, image dimensions, and QA notes. Do not schedule until I explicitly approve.

Queue these approved pre-built slideshow ids as TikTok inbox drafts: <ids>. First run list_automations and list_automation_queue for <automation_id>. Confirm the automation uses content_source library and post_mode MEDIA_UPLOAD. Then run queue_slideshows and show the new queue count. Never use DIRECT_POST unless I say so.

Publish a locally rendered MP4 through CineRads. Upload /absolute/path/final.mp4 with upload_video, then publish_video_tiktok using privacy_level SELF_ONLY unless I explicitly request public direct posting. Poll get_publish_status until it is not uploading, and report the generation_id, publish_id, status, and any TikTok error.

Run the performance learning loop. Pull get_post_performance and get_hook_analytics for the last 50 posts, identify the best hooks, CTAs, visuals, and slide counts, then create 3 new draft decks that reuse only the winning patterns. Render them, return the /s/ links, and do not publish.

Wire it up in two minutes.

Create a key, paste the config, hand your agent a prompt.