Developer documentation
Build with the Neurodance API and MCP server.
Use the REST API for deterministic integrations or connect the remote MCP server to let compatible AI clients operate Neurodance with user approval. Both surfaces share the same workspace, scopes, rate limits and capability model.
Reviewed by Neurodance ·
REST API foundations
The OpenAPI 3.1 contract exposes 93 operations across 79 paths. Authenticate server-side requests with a workspace-scoped nd_live_ or nd_test_ API key in the Authorization Bearer header.
Every mutation requires a stable Idempotency-Key. Long-running template, generation, variation and distribution operations return a job handle; poll the linked job endpoint using poll_after_seconds instead of creating a duplicate operation.
- Production base URL: https://api-public.neurodance.ai
- OpenAPI contract: https://api-public.neurodance.ai/v1/openapi.json
- Scopes: read, generate and distribute
Complete REST operation index (93)
The interactive documentation includes searchable parameters, request fields, response codes, scope, rate tier, async-job and idempotency metadata for every operation.
- GET /v1/account — Get account status [read]
- GET /v1/templates — List templates [read]
- GET /v1/templates/{id} — Get a template [read]
- POST /v1/templates/build — Build a template (async) [generate]
- POST /v1/templates/{id}/variations — Create a variation (synchronous) [generate]
- GET /v1/assets — List asset library [read]
- GET /v1/generations — List generations [read]
- POST /v1/generations — Create a generation (async) [generate]
- GET /v1/generations/{id} — Get generation status [read]
- GET /v1/distributions — List distributions [read]
- POST /v1/distributions — Distribute a generation (async) [distribute]
- GET /v1/distributions/{id} — Get distribution status [read]
- DELETE /v1/distributions/{id} — Delete an Instagram or YouTube distribution [distribute]
- POST /v1/distributions/{job_id}/activate — Activate a Meta Ads distribution [distribute]
- POST /v1/distributions/{job_id}/dismiss — Dismiss a Meta Ads distribution [distribute]
- POST /v1/distributions/{job_id}/cancel — Cancel a Meta Ads distribution [distribute]
- POST /v1/distributions/{job_id}/sync — Sync one distribution [distribute]
- POST /v1/distributions/sync-all — Sync distributions [distribute]
- GET /v1/metrics — List performance metrics [read]
- GET /v1/metrics/diagnostics — Diagnose metrics polling [read]
- GET /v1/metrics/{platform_post_id} — Get post metrics time series [read]
- POST /v1/performance-briefs — Compose a performance brief [generate]
- GET /v1/performance-briefs/{platform_post_id} — List performance briefs [read]
- GET /v1/jobs/{job_id} — Get any job's status [read]
- POST /v1/uploads/reference — Upload a reference image [generate]
- GET /v1/capabilities — Search the typed capability catalog [read]
- GET /v1/search — Search workspace [read]
- GET /v1/campaigns/{campaign_id}/memory — List campaign memory [read]
- POST /v1/campaigns/{campaign_id}/memory — Record campaign memory [generate]
- GET /v1/notes — List workspace notes [read]
- POST /v1/notes — Add workspace note [generate]
- DELETE /v1/notes/{note_id} — Delete workspace note [generate]
- GET /v1/generations/{generation_id}/review-thread — List review thread [read]
- POST /v1/review-entries/{source}/{entry_id}/resolution — Resolve review entry [generate]
- PATCH /v1/campaign-memory/{entry_id} — Update campaign memory lifecycle [generate]
- GET /v1/memory-ledger — List workspace decision ledger [read]
- GET /v1/campaigns/{campaign_id}/related-learnings — List related campaign learnings [read]
- GET /v1/assets/library — List asset library [read]
- PATCH /v1/assets/{asset_id}/library — Rename or file asset [generate]
- GET /v1/archive/generations — List generation archive [read]
- GET /v1/trash — List trash [read]
- DELETE /v1/archive/{entity_type}/{entity_id} — Move object to trash [generate]
- POST /v1/archive/{entity_type}/{entity_id}/restore — Restore object from trash [generate]
- PATCH /v1/templates/{template_id}/name — Rename template [generate]
- GET /v1/campaigns/{campaign_id}/asset-folders — List campaign asset folders [read]
- POST /v1/campaigns/{campaign_id}/asset-folders — Create campaign asset folder [generate]
- PATCH /v1/asset-folders/{folder_id} — Rename campaign asset folder [generate]
- DELETE /v1/asset-folders/{folder_id} — Delete campaign asset folder [generate]
- GET /v1/review-workspace — Load review workspace [read]
- PATCH /v1/generations/{generation_id}/qc — Set generation QC decision [generate]
- PATCH /v1/generations/{generation_id}/folder — Move generation to review folder [generate]
- POST /v1/generations/{generation_id}/cancel — Cancel active generation [generate]
- POST /v1/review-folders — Create review folder [generate]
- PATCH /v1/review-folders/{folder_id} — Rename review folder [generate]
- DELETE /v1/review-folders/{folder_id} — Delete review folder [generate]
- GET /v1/generation-workflow-status — Get batch, carousel, or reusable generation status [read]
- DELETE /v1/carousels/{carousel_id} — Delete carousel group [generate]
- GET /v1/flyer-suite — Load Flyer Suite workspace [read]
- POST /v1/flyer-suite/tours — Create Flyer Suite tour [generate]
- GET /v1/shares/targets — List share targets [read]
- GET /v1/shares — List object shares [read]
- POST /v1/shares — Create object share [generate]
- DELETE /v1/shares/{share_id} — Revoke object share [generate]
- GET /v1/generations/{generation_id}/lineage — Get generation lineage [read]
- GET /v1/distribution-planning — Load distribution planning workspace [read]
- POST /v1/distribution-planning/campaigns — Create distribution campaign [generate]
- POST /v1/distribution-planning/narratives — Create distribution narrative [generate]
- PATCH /v1/distribution-planning/campaigns/{campaign_id} — Update distribution campaign [generate]
- DELETE /v1/distribution-planning/campaigns/{campaign_id} — Delete distribution campaign [generate]
- POST /v1/distribution-planning/campaigns/{campaign_id}/archive — Archive distribution campaign [generate]
- POST /v1/distribution-planning/campaigns/{campaign_id}/restore — Restore distribution campaign [generate]
- PATCH /v1/distribution-planning/narratives/{narrative_id} — Update distribution narrative [generate]
- DELETE /v1/distribution-planning/narratives/{narrative_id} — Delete distribution narrative [generate]
- POST /v1/distribution-planning/assignments — Organize distribution assignment [generate]
- DELETE /v1/distribution-planning/assignments/{assignment_id}/narrative — Unassign creative from narrative [generate]
- GET /v1/distribution-planning/generation-assignments/{generation_id} — List generation assignments [read]
- GET /v1/performance/workspace — Load performance workspace [read]
- GET /v1/performance/attributes — List performance attributes [read]
- POST /v1/performance/attributes — Add performance attribute [generate]
- DELETE /v1/performance/attributes/{attribute_id} — Delete performance attribute [generate]
- GET /v1/performance/attributes/analysis — Analyze performance cohorts [read]
- GET /v1/performance/audience-balance — Assess audience balance [read]
- GET /v1/editor/media — List editor media [read]
- GET /v1/editor/projects — Load editor project [read]
- POST /v1/editor/projects — Save editor project [generate]
- POST /v1/editor/sources/resolve — Resolve editor sources [read]
- PATCH /v1/editor/asset-names — Set editor asset name [generate]
- DELETE /v1/editor/asset-names — Delete editor asset name [generate]
- POST /v1/editor/uploads — Begin editor media upload [generate]
- POST /v1/editor/uploads/confirm — Confirm editor media upload [generate]
- POST /v1/editor/exports — Begin editor export [generate]
- GET /v1/editor/exports/{export_id} — Get editor export [read]
- POST /v1/editor/exports/{export_id}/complete — Complete editor export [generate]
Connect the MCP server
The Neurodance MCP v2.0.0 server uses Streamable HTTP at https://mcp.neurodance.ai/mcp. Compatible clients discover OAuth automatically, open Neurodance sign-in and request read, generate or distribute scopes. No API key is pasted into the client.
The server supports direct tools, embedded MCP Apps workflow views and a typed capability bridge. A client may show fewer tools if it does not support MCP Apps or applies its own connector curation.
- Claude.ai and Claude Desktop: Settings → Connectors → Add custom connector
- ChatGPT: Settings → Apps → Developer Mode → Create App, then choose OAuth
- Other clients: configure the remote Streamable HTTP endpoint and follow OAuth protected-resource discovery
Complete MCP tool index (48)
These are the non-legacy tools advertised by the server. Expand the interactive reference for complete descriptions, inputs, workflow, scope and safety annotations.
- upload_image — Open the Neurodance upload widget so the user can pick a product or style image directly from their device and save it to their asset library. This is the normal path for Claude.ai attachments and local/device files: the user picks the file in the widget, and the widget/host handles the upload details without asking the agent to read bytes, paste base64, or reuse temporary chat URLs. After upload, use list_assets to resolve the saved asset by label and pass its stable asset id internally to create_generation or generate_image; do not ask the user to paste storage URLs. Call this tool whenever the user wants to upload an image from their local machine, especially in Claude.ai where attachment URLs are session-scoped and cannot be fetched server-side. Requires: generate scope. [generate; direct_tool]
- list_templates — List the video ad templates available in your Neurodance account. Returns template names, IDs, and metadata. Use template IDs with create_generation. Optional filters: campaign / narrative (name or id — only templates used in that bucket) and search (matches name, description, and scene prompt text). Requires: read scope. [read; direct_tool]
- list_campaigns — List the user's Campaigns workspace hierarchy. A campaign is the top-level commercial initiative or testing bucket, with an optional optimization goal and notes. Narratives sit inside a campaign and represent audience/angle lanes; each can carry a target audience and notes. Templates, generations, and variants are assigned into this hierarchy. Call this when the user references an existing campaign or narrative by name, then pass campaign/narrative on write_template_json, rewrite_template_canvas, or create_generation to sort new work as it is created. Requires: read scope. [read; direct_tool]
- create_campaign — Create a Campaigns workspace campaign. In Neurodance, campaigns are top-level commercial/testing buckets such as a launch, product line, funnel, or experiment. They contain narratives, and narratives contain the templates/generations/variants. Use this when the user explicitly asks to create or set up a campaign. If the campaign already exists by name, this returns the existing campaign instead of duplicating it. Requires: generate scope. [generate; direct_tool]
- create_narrative — Create a narrative inside a Campaigns workspace campaign. In Neurodance, a narrative is an angle/audience lane within one campaign, for example 'Founder pain', 'Cost objection', or 'Enterprise proof'. Narratives can carry a target audience and notes, and templates, generations, and variants are sorted under them. Use this when the user explicitly asks to create a narrative or define campaign lanes. If the narrative already exists in the campaign by name, this returns the existing narrative instead of duplicating it. Requires: generate scope. [generate; direct_tool]
- get_template — Get details of a specific template by ID. Requires: read scope. [read; direct_tool]
- get_template_canvas — Load the editable canvas for a template, including node ids, prompts, narrative roles, stored variation counts, and testable nodes. The node summaries include reference_images; ['product'] means the node should use generation-level product references. Start here before editing the canvas, creating canvas variations, previewing test plans, or generating from an edited template. Some older canvases may show generic roles such as Scene; that is valid canvas state. For variations, pass the node_id and variation_axis to create_canvas_variation and let the backend resolve the node's effective role from canvas context. Recommended workflow: get_template_canvas → rewrite_template_canvas (bulk edit the full manifest for an existing template) → get_template_canvas again to verify → create_generation or run_test_plan. Requires: read scope. [read; direct_tool]
- write_template_json — Create a NEW video ad template instantly from a complete video-manifest-v1 payload that YOU, the MCP agent, have already generated as JSON. This tool directly inserts the caller's template row; it does not call build_template, start_template, or any queued builder. For a user's request to make a new template, use this tool once with no template_id. Do NOT call build_template before or after write_template_json for the same manifest. Do NOT use list_templates to find an existing template unless the user explicitly asked to edit an existing template. For bulk edits to an existing template, use rewrite_template_canvas instead; it requires template_id and preserves builder-owned metadata and stored variants for stable node ids. Manifest shape: { templateName, segments: [{ id: 'video1', promptText, duration (1-15), usesProductReference?, nodes: [{ id, promptText, duration (1-15), narrativeRole }] }] }. Every node narrativeRole must be one of the app component names: Hook, Problem, Demo, Proof, Social proof, Transformation, Objection, CTA. The server stores node labels as those canonical component names; do not invent custom component names. Set segments[].usesProductReference=true on every segment that should use the product image supplied to create_generation. Do not replace product details with {{product_name}} or {{cta_url}} placeholders; use literal creative prompts and blueprintSummary for narrative metadata. Include blueprintSummary (product, audience, whyCare, cta, duration) when you want the app's Narrative/Goal/CTA panel populated. Node durations must sum to a 15s multiple (15-120). DURATION EQUATIONS (server-enforced): for every segment, segment.duration MUST equal the sum of that segment's nodes[].duration; totalDurationSeconds MUST equal the sum of all segments[].duration. Example: three 5s nodes require one segment with duration: 15, never duration: 5. A mismatch is rejected and must never be sent to create_generation. SEGMENTATION: a segment is ONE Seedance provider call of up to 15 seconds, and its nodes are the internal cuts of that call. Group beats into 15-second segments — a 15s ad is ONE segment with 2-4 nodes; a 30s ad is TWO 15s segments. Never emit one short segment per beat (eight 4s segments instead of two 15s ones): each segment generates as a separate clip conditioned on the first, which degrades quality. The server packs over-segmented manifests automatically, but authoring correct 15s segments is strongly preferred. PROMPTTEXT CONTRACT (server-enforced by a deterministic realism lint; violations return a 400 with per-finding remediations — fix and retry): every promptText must OPEN with a physical capture anchor — what camera and where it physically is (e.g. 'Vertical phone video filmed by a friend across the counter', 'Handheld documentary footage on the rig deck', 'Locked-off studio macro shot'). Name ONE practical light source ('grey overcast daylight', 'warm tungsten practicals') and never style words — banned vocabulary includes: cinematic, photorealistic, dramatic lighting, stunning, 8K, vibrant colors, golden glow. Stage any subject — fantastical ones included — as the closest shot a real crew could film: reframe the camera, never drop the idea. Keep faces mid-distance or partially occluded unless the capture anchor is phone/UGC. Specify the soundscape in every prompt (one ambient bed grounded in the scene, plus the exact spoken line with speaker or explicitly 'no speech'). Do NOT request any on-screen text, captions, titles, subtitles, or overlays — rendered text never looks right; deliver messaging through voiceover instead. Restate persistent state in every cut (product color/variant, wardrobe, worn props). For product/UGC ads: keep the product in the real scene, held or used (never floating/rotating on a plain, seamless, gradient, or blurred backdrop, and no display-only beat); keep its real container and form (a rigid box does not tear open like a packet); keep any device off/dim/out-of-focus (screen content renders as gibberish); keep the brand only on the hero product; and for UGC keep eyelines and dialogue to who is actually in frame (one or more presenters both fine). Avoid beauty/skin tells (flawless/glowing skin, ring light) — write real skin under flat light. Soft findings are returned as realism_warnings on success. Requires: generate scope. [generate; direct_tool]
- rewrite_template_canvas — Bulk edit an existing template by replacing its canvas with a complete video-manifest-v1 manifest. This is the preferred MCP editing path after a template has been created by start_template/build_template: call get_template_canvas first, keep stable node ids where you want stored variants and scene metadata preserved, include blueprintSummary to update the app's Narrative/Goal/CTA panel, then call get_template_canvas again to verify. The MCP agent must provide the full edited manifest JSON directly; this tool does not call a queued builder. Every node narrativeRole must be a canonical app component name: Hook, Problem, Demo, Proof, Social proof, Transformation, Objection, CTA. When the user asks to add/use product references on nodes, set segments[].usesProductReference=true for each product-visible segment so the rebuilt canvas has reference_images ['product']; do not invent template variables like {{product_name}} or {{cta_url}}. Unlike write_template_json, this requires template_id and preserves builder-owned fields such as agent instructions/model, activation state, examples, guide, and stored variants for node ids that still exist. It prunes scene-block metadata for deleted node ids. Use create_canvas_variation for single-node test variants instead of rewriting the whole template. Keep segments at 15 seconds with beats as internal nodes (a 30s ad is two 15s segments, not eight thin ones); the server packs over-segmented manifests but correct segmentation is preferred. PROMPTTEXT CONTRACT: any promptText you add or modify must follow the same server-enforced realism lint as write_template_json — open with a physical capture anchor (what camera, where it physically is), one named practical light source, no banned style vocabulary (cinematic, photorealistic, dramatic lighting, 8K, vibrant colors, golden glow, ...), a specified soundscape (ambient bed + exact spoken line or 'no speech'), NO on-screen text/captions/overlays of any kind, and persistent state (product color, wardrobe, props) restated per cut. For product/UGC: product stays in the real scene held or used (never isolated on a plain/blurred backdrop, no display-only beat), keeps its real form, devices off/out-of-focus, brand on the hero product only, UGC eyelines/dialogue matched to who is in frame, and no beauty/skin tells (flawless/glowing skin, ring light). Violations return a 400 with per-finding remediations — fix and retry. Prompts you pass through UNCHANGED from get_template_canvas are grandfathered and reported as non-blocking realism_warnings instead. Requires: generate scope. [generate; direct_tool]
- start_template — Open the Neurodance blueprint widget so the user answers the five intake questions (product, main benefit, call-to-action, ad format, duration) and saves a new template through write_template_json direct manifest persistence. For agent-only creation, prefer generating the video-manifest-v1 payload yourself and calling write_template_json with no template_id. Do not call build_template for new MCP templates. Requires: generate scope. [generate; direct_tool]
- create_generation — Submit a new video ad generation job. Provide a template, product name, and product description. Optionally attach reference images (product photos or style references) by saved asset ID or public URL. Prefer asset_id from list_assets because signed URLs expire. Use this only after the canvas is already ready and verified. If you manually changed nodes or edges, call get_template_canvas again before generating so you confirm the final canvas state. If you want to test node-level variations, create them on the canvas first and use preview_test_plan/run_test_plan. Do not use this tool to invent variations after the fact. video_model defaults to seedance; choose kling-v3 only when the first video node has a canvas image node connected as its first frame. Product/style reference_images are prompt context and do not count as Kling first frames. video_resolution defaults to 720p; Seedance 1080p costs 3x its 720p token rate and Kling 1080p costs 2x. Returns a job_id immediately. Use wait_for_job to wait for completion (takes 2–10 minutes for video). Check get_account first to confirm you have enough tokens. PREFER A REFERENCE IMAGE: if the user has not already provided or uploaded one, ask whether they want to attach a product/style reference and, if so, call upload_image and wait for the upload to complete BEFORE submitting this job. Only submit without a reference when the user explicitly confirms they don't want one. IMPORTANT: if the user has attached an image in Claude.ai or wants to use a device/local image, call upload_image first so the upload widget saves it, then resolve its asset id with list_assets. Use upload_reference_image only for public HTTPS image URLs or an explicit small base64 fallback. Never pass raw temporary chat-attachment URLs. Requires: generate scope. [generate; direct_tool]
- list_assets — List the product images saved in the user's asset library. These are the same images shown on the Assets page in the app — permanently stored, reusable across any generation. Call this before upload_image or upload_reference_image to check if the user already has the image they want. Use the returned id as reference_images[].asset_id in generation tools; this avoids caching expiring signed URLs. Filter with campaign (one campaign's asset library) or scope=general (references not filed into any campaign). Requires: read scope. [read; direct_tool]
- list_generations — List the user's past generations, newest first. Returns id, product_name, status, job_id, output_url (when complete), ad_format, template_id, video_model, created_at, and tokens_used. Use this to find a previous generation to distribute, re-run, reference, or anchor a later run_test_plan variation. Never ask the user to paste IDs; inspect this list and choose the matching generation yourself, asking a plain-language clarification only if ambiguous. Requires: read scope. [read; direct_tool]
- generate_image — Submit an AI image generation job and return the job_id immediately. Unlike create_generation (which makes a video ad), this produces a still image. For image carousels that need previous-slide visual continuity, call this sequentially: wait for slide N, then pass slide N's completed output URL as a style reference for slide N+1. For batch carousels whose references are already known, prefer create_image_carousel. After calling this tool, ALWAYS call wait_for_job with the returned job_id — wait_for_job will return the image inline in the chat window once it's ready. Do NOT call generate_image again while waiting — that wastes tokens by creating duplicate jobs. Provide your product name, a description of what to generate, and optional reference images (product photos or style refs) by saved asset ID or public URL. PREFER A REFERENCE IMAGE: if the user has not already provided or uploaded one, ask whether they want to attach a product/style reference and, if so, call upload_image and wait for the upload to complete BEFORE submitting this job; only submit without one on explicit confirmation. IMPORTANT: if the user has attached an image in Claude.ai or wants to use a device/local image, call upload_image first so the upload widget saves it, then resolve its asset id with list_assets. Use upload_reference_image only for public HTTPS image URLs or an explicit small base64 fallback. Never pass raw temporary chat-attachment URLs. Check get_account first to confirm you have enough tokens. Requires: generate scope. [generate; direct_tool]
- create_image_carousel — Create an ordered image carousel by submitting 2-10 still-image generation jobs as one group. Use this when the user asks for a carousel, swipe-through ad, multi-card image concept, or Meta/Instagram carousel creative and the card prompts/references are already known. The agent must write the individual image prompt for every card in product_features; the backend does not infer a story arc or know that 'slide 3' should say anything specific. Each card becomes an ordinary image generation with shared carousel_group_id metadata; after every returned job_id is complete, publish with create_distribution using post_type=carousel, generation_id set to the first card, and carousel_generation_ids set to the completed generation ids in order. Instagram carousel publishing requires 2-10 completed image generations. Meta Ads can also use the same ordered ids for a carousel creative, alongside its normal campaign/ad set/targeting/copy fields. If slide-to-slide visual consistency depends on the previous generated slide, create the cards sequentially with generate_image instead: wait for each slide, then pass its output URL as a style reference to the next slide. Call wait_for_job for each returned job_id and do not create duplicate carousel jobs while waiting. Requires: generate scope. [generate; direct_tool]
- upload_reference_image — Fallback API upload: save an image permanently to the user's asset library. Returns a short-lived URL for immediate use; for later reuse, resolve the saved asset with list_assets and pass its asset_id. The image will appear on the Assets page in the app and can be reused in future generations. For Claude.ai chat attachments, local files, or device images, prefer upload_image instead — it opens the upload widget and keeps the agent trace clean. Do not call this after upload_image succeeds; resolve the saved asset with list_assets. IMPORTANT: call list_assets first — if the user has already uploaded this product image, use the existing asset_id instead of uploading again. HOW TO PROVIDE THE IMAGE — choose one path: • image_url (preferred for public/ChatGPT URLs): public HTTPS URLs such as ChatGPT attachment URLs (dalle.sandboxusercontent.com/...) are fetched server-side. Do NOT pass a local filesystem path or a claude.ai/api/... URL — those are inaccessible to the server. • image_base64 (fallback only): only use when the MCP client can reliably read the bytes and the image is small. For Claude.ai composer attachments, call upload_image instead unless the user explicitly asks for this fallback. Works for images up to ~5 MB raw. Accepted formats: JPEG, PNG, WebP, AVIF, GIF, HEIC, HEIF. Max 20 MB via image_url. Requires: generate scope. [generate; direct_tool]
- create_canvas_variation — Create a pre-generation variation on a specific canvas node inside a template. This is the correct workflow for testing hooks/tones/CTAs: load the canvas, pick a node_id, choose a variation_axis, create one or more variations, preview the test plan, then run the test plan. You normally do not need to pass narrative_role; the backend resolves the effective role from the canvas, scene-block metadata, prompt, and node position, so older generic Scene roles do not block variation testing. By default the variant is saved onto the template's scene-block state for later testing. Requires: generate scope. [generate; direct_tool]
- preview_test_plan — Preview the pre-generation test plan for a template from stored canvas variations. Returns a control plus one version per saved node variation, including the node_overrides that would be sent to generation. Use this before run_test_plan. Requires: read scope. [read; direct_tool]
- run_test_plan — Run one or more pre-generation canvas test versions for a template. This is the preferred way to test variations: upload references first if needed, preview the test plan, select version ids, then run. The tool creates one generation job per selected version and returns all job_ids together. When the user asks for a variation of an ad that already exists, do not ask them for IDs: use control_strategy='auto' and either let this tool find the latest matching control generation or pass control_job_id/control_generation_id from list_generations or a previous run_test_plan result. video_model and video_resolution have the same Seedance/Kling constraints and token multipliers as create_generation. Requires: generate scope. [generate; direct_tool]
- create_distribution — Distribute a completed ad generation to Instagram organic, YouTube Shorts, or Meta Ads. The generation must have status=complete. Instagram supports captions, Reel, Story, Carousel, user/location tags, alt text, paid partnership labels, and trial Reels. YouTube supports title, description, tags, privacy, and made-for-kids. Meta Ads supports video, single image, or carousel creatives and requires explicit campaign, ad set, targeting, destination URL, primary text, and CTA fields; it will not infer creative copy or targeting. For carousel publishing, first use create_image_carousel or completed image generations, then pass post_type=carousel, generation_id as the first image, and carousel_generation_ids as the 2-10 completed image ids in display order. For Instagram or YouTube, use get_account once if you need account ids, then call create_distribution directly. For Meta Ads, ask the user for any missing campaign/ad set/budget/targeting/copy fields before calling so the trace stays clean. Returns a job_id immediately; use wait_for_job/get_job_status to track progress. Requires: distribute scope. [distribute; direct_tool]
- list_distributions — List distribution history across Instagram organic, YouTube Shorts, and Meta Ads. Returns stable job_id values such as dist:ig:<id>, dist:yt:<id>, and dist:meta:<id>, plus raw id values for compatibility, platform ids/permalinks, generation/template metadata, publishing fields, and metrics polling error state where relevant. Requires: read scope. [read; direct_tool]
- activate_distribution — Activate a Meta Ads distribution that is ready for review. Pass the job_id from create_distribution or list_distributions, e.g. dist:meta:<id>. This maps to the same user-facing approval action as the app. Unsupported for Instagram and YouTube. Requires: distribute scope. [distribute; direct_tool]
- dismiss_distribution — Dismiss or cancel a non-active Meta Ads distribution job from public API/MCP. Pass the job_id from create_distribution or list_distributions, e.g. dist:meta:<id>. Unsupported for Instagram and YouTube. Requires: distribute scope. [distribute; direct_tool]
- delete_distribution — Delete an Instagram organic post or YouTube Short that was created by Neurodance. Pass the job_id from list_distributions, e.g. dist:ig:<id> or dist:yt:<id>. Meta Ads deletion is intentionally not exposed here; use dismiss_distribution before activation or manage active campaigns in Meta. Requires: distribute scope. [distribute; direct_tool]
- sync_distribution — Sync one distribution against its platform to verify the remote object still exists. Supports Meta Ads, Instagram organic, and YouTube Shorts. Pass the job_id from list_distributions, e.g. dist:meta:<id>, dist:ig:<id>, or dist:yt:<id>. Requires: distribute scope. [distribute; direct_tool]
- sync_all_distributions — Sync distributions against their remote platforms and report how many were checked and how many appear missing. Supports all platforms together or one of Meta Ads, Instagram organic, and YouTube Shorts. This mirrors the app's distribution maintenance action. Requires: distribute scope. [distribute; direct_tool]
- get_metrics — Retrieve post performance metrics snapshots. By default returns the latest snapshot per post; set latest_only=false for raw paginated snapshots. Supports platform, generation_id, platform_post_id, since, and until filters. Requires: read scope. [read; direct_tool]
- get_metric_timeseries — Return the full oldest-first metrics time series for one platform post id. Use this for trend charts, debugging hourly polling, or before composing a brief. Requires: read scope. [read; direct_tool]
- diagnose_metrics_polling — Explain why an Instagram or YouTube distribution is or is not eligible for the metrics poller. Reports status, missing platform ids, metrics_paused/error state, account reauth state, poll-window checks, and whether it already has this hour's snapshot. Requires: read scope. [read; direct_tool]
- compose_performance_brief — Compose and persist an AI performance brief from the latest metrics for a published post. Returns the same structured brief used by the app to re-brief the next generation, including generationRequirementsPrompt. Requires: generate scope. [generate; direct_tool]
- list_performance_briefs — List previously composed performance briefs for one platform post, newest first. Use this to retrieve re-brief history and generationRequirementsPrompt values. Requires: read scope. [read; direct_tool]
- get_job_status — Get the current status of any async job by its job_id. Works for generation, template build, variation, and distribution jobs. Status values: pending | running | complete | failed. When complete, output_url is set for generations and published organic distribution jobs. Requires: read scope. [read; direct_tool]
- get_generation_media — Fetch a completed generation's output as base64 bytes so a widget can render it inline (Claude.ai iframes block loading media from external URLs). Called automatically by the generation-result widget via tools/call; do not call this manually — for an agent, the output_url from get_job_status is what you want. Returns { media_base64, media_type, too_large } — too_large=true (no bytes) when the file exceeds the inline limit. Requires: read scope. [read; direct_tool]
- wait_for_job — Wait briefly for an async job to complete and return the final result. Each call polls every 8 seconds for about 20 seconds, then returns status=still_running if the job is not done yet. Call wait_for_job again with the same job_id until complete; never submit a duplicate generation/image/distribution while waiting. Use this after create_generation, generate_image, run_test_plan, or create_distribution to get the final result without manual polling. Requires: read scope. [read; direct_tool]
- get_account — Get your account status including token balance and which platforms are connected. Check token_balance before creating generations — video jobs cost tokens based on duration, model, and resolution. If no platforms are connected, open your Neurodance Settings → Connections to connect Instagram, YouTube, or Meta Ads. The accounts arrays contain ids accepted by create_distribution. Requires: read scope. [read; direct_tool]
- get_upload_url — Generate a presigned upload URL so the browser widget can PUT an image file directly to Neurodance storage in MCP hosts that allow widget network PUTs, such as ChatGPT. Claude.ai blocks external widget PUT/fetch calls; there the upload widget uses host-forwarded tools/call instead. Called automatically by compatible upload widgets; agents should not call this manually. Returns upload_url (PUT target) and a tenant-scoped storage_path. Requires: generate scope. [generate; direct_tool]
- confirm_upload — Record an uploaded image in the user's asset library after the browser widget has PUT the file to the presigned URL from get_upload_url. Called automatically by the upload widget via tools/call; do not call this manually. Requires: generate scope. [generate; direct_tool]
- search_capabilities — Search the typed Neurodance capability catalog for application workflows that are not part of the curated dedicated-tool set. Returns schemas, required scope, rate tier, idempotency requirements, and REST mapping. Run a result with run_read_capability, run_creative_capability, or run_external_capability according to its rate_tier. Requires: read scope. [read; capability_bridge]
- open_campaign_workspace — Open the focused Neurodance campaign planning and memory app. It exposes typed campaign, narrative, note, and decision-ledger workflows with text fallback. Requires: read scope. [read; workflow_app]
- open_library_workspace — Open the focused Neurodance library and search app. It exposes typed search, asset, folder, archive, trash, and sharing workflows with text fallback. Requires: read scope. [read; workflow_app]
- open_flyer_workspace — Open the Neurodance Flyer Suite app to inspect tours, filed outputs, base assets, and recent flyer generations or create a tour. Requires: read scope. [read; workflow_app]
- open_review_workspace — Open the focused Neurodance reviews and lineage app. It exposes typed QC, feedback, folder, lineage, and generation-control workflows with text fallback. Requires: read scope. [read; workflow_app]
- open_distribution_workspace — Open the focused Neurodance distribution planning app. It exposes typed campaign, narrative, assignment, readiness, and status workflows with text fallback. Requires: read scope. [read; workflow_app]
- open_performance_workspace — Open the focused Neurodance performance analysis app. It exposes typed rollup, cohort, attribute, audience-balance, and brief workflows with text fallback. Requires: read scope. [read; workflow_app]
- open_editor_workspace — Open the focused Neurodance editor and export app. It exposes typed media, timeline persistence, source resolution, naming, upload, and export workflows with text fallback. Requires: read scope. [read; workflow_app]
- run_read_capability — Run one read-only typed capability returned by search_capabilities. Rejects every mutation and is not an HTTP proxy. Requires: read scope. [read; capability_bridge]
- run_creative_capability — Run one normal creative mutation returned by search_capabilities, such as notes, reviews, folders, campaigns, or Flyer tours. Requires the target capability scope and a stable idempotency_key. [read; capability_bridge]
- run_external_capability — Run one externally visible or destructive mutation returned by search_capabilities. Rejects reads and normal creative writes. Requires the target capability scope, explicit approval, and a stable idempotency_key. [read; capability_bridge]
Rate limits and errors
Current per-credential, per-workspace limits are 120 reads per minute, 60 creative writes per minute, 10 external writes per minute and 10 credential writes per minute. Follow Retry-After after a 429 and use exponential backoff with jitter for transient failures.
Errors provide a stable machine-readable type, human message, remediation when available, documentation URL and request ID. Integrations should branch on the error type rather than message text.
