MCP tool
produce_asset
Produce a finished AI asset attached to an existing creative: video (CTV/cinema 16:9; DOOH 9:16 or 16:9 loops), image (DOOH stills), vo (audio-channel voiceover of the creative script), music (audio bed), or motion — an animated text loop ("moving image") for DOOH/display where the headline/subline/CTA slide and fade in, hold, and exit, looping forever. Motion has two modes: "programmatic" (deterministic animated SVG generated in-process, ready immediately) and "rendered" (a provider-rendered 5–10s video loop). IMPORTANT — production is a SEPARATE HARD wallet charge, debited immediately at submit and stated in the response (chargedMinor + remaining wallet balance). Definite provider failures are auto-refunded; an ambiguous acceptance becomes terminal reconciliation-required with the charge retained and retry disabled to prevent duplicate production. Prices are cost-plus at a configured margin over provider cost — call get_asset_pricing for the current ladder. Never blended into media-spend platform fees. Fails with 402 INSUFFICIENT_FUNDS (including shortfallMinor) when the wallet cannot cover it — top up first. Unset fields default sensibly from the creative’s channel and content. Then poll get_asset_status until ready.
Input
Pass fields from this schema as the tool arguments. Runtime ownership, product scope and readiness checks still apply.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"creativeId": {
"type": "string",
"description": "existing creative the asset attaches to, e.g. cr-1a2b3c4d"
},
"agentStepId": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "pending execute-step id that consumed the exact approved action"
},
"expectedActionDigest": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA-256 digest returned for the exact approved action"
},
"idempotencyKey": {
"type": "string",
"minLength": 8,
"maxLength": 200,
"description": "caller-generated key for this intended production; reuse it after a timeout/network error to receive the original job without another debit or provider submission"
},
"kind": {
"type": "string",
"enum": [
"video",
"image",
"vo",
"music",
"motion"
],
"description": "what to produce: video | image | vo (voiceover) | music (bed) | motion (animated text loop)"
},
"tier": {
"description": "video only: quality/price tier — draft | standard | premium (default comes from the creative’s channel, e.g. cinema → premium); per-second rates come from get_asset_pricing",
"type": "string",
"enum": [
"draft",
"standard",
"premium"
]
},
"durationSeconds": {
"description": "video 5–10s and rendered motion 5–10s (both billed per second), music 5–180s, programmatic motion 5–15s loop; ignored for image/vo",
"type": "integer",
"minimum": 5,
"maximum": 180
},
"promptOverride": {
"description": "override the auto-derived content: the video/image prompt, the vo script, or the music brief (default is built from the creative’s copy/storyboard/script); not used for motion — pass headline/subline/cta instead",
"type": "string",
"minLength": 1
},
"headline": {
"description": "motion only: headline text that animates in/out (default: from the creative’s copy)",
"type": "string",
"minLength": 1
},
"subline": {
"description": "motion only: supporting line staggered behind the headline (default: from the creative)",
"type": "string",
"minLength": 1
},
"cta": {
"description": "motion only: call-to-action text shown last (default: from the creative)",
"type": "string",
"minLength": 1
},
"resolution": {
"description": "motion only: DOOH screen resolution — 1080x1920 portrait D6, 1920x1080 landscape HD, 1400x400 ribbon banner (default fits the creative’s channel)",
"type": "string",
"enum": [
"1080x1920",
"1920x1080",
"1400x400"
]
},
"mode": {
"description": "motion only: \"programmatic\" = deterministic animated SVG loop generated in-process (zero provider cost — priced at the minimum charge; ready immediately); \"rendered\" = provider video loop billed per second (default: programmatic)",
"type": "string",
"enum": [
"programmatic",
"rendered"
]
}
},
"required": [
"creativeId",
"agentStepId",
"expectedActionDigest",
"idempotencyKey",
"kind"
]
}REST mapping and authority
The tool wraps this REST endpoint. The mapping identifies path/query/body transformations and approval or idempotency headers.
{
"method": "POST",
"path": "/api/v1/creatives/{creativeId}/assets",
"pathFields": [
"creativeId"
],
"pathSchema": {
"type": "object",
"properties": {
"creativeId": {
"type": "string",
"description": "existing creative the asset attaches to, e.g. cr-1a2b3c4d"
}
},
"additionalProperties": false,
"required": [
"creativeId"
]
},
"pathEncoding": "encodeURIComponent for each path field",
"governedAction": "asset.submit",
"headers": {
"x-chorus-agent-step-id": "agentStepId",
"x-chorus-agent-action-digest": "expectedActionDigest"
},
"bodySchema": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"idempotencyKey",
"kind"
],
"properties": {
"idempotencyKey": {
"type": "string",
"minLength": 8,
"maxLength": 200,
"description": "caller-generated key for this intended production; reuse it after a timeout/network error to receive the original job without another debit or provider submission"
},
"kind": {
"const": "video",
"type": "string"
},
"spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"tier": {
"description": "video only: quality/price tier — draft | standard | premium (default comes from the creative’s channel, e.g. cinema → premium); per-second rates come from get_asset_pricing",
"type": "string",
"enum": [
"draft",
"standard",
"premium"
]
},
"durationSeconds": {
"description": "video 5–10s and rendered motion 5–10s (both billed per second), music 5–180s, programmatic motion 5–15s loop; ignored for image/vo",
"type": "integer",
"minimum": 5,
"maximum": 180
},
"prompt": {
"description": "override the auto-derived content: the video/image prompt, the vo script, or the music brief (default is built from the creative’s copy/storyboard/script); not used for motion — pass headline/subline/cta instead",
"type": "string",
"minLength": 1
}
}
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"idempotencyKey",
"kind"
],
"properties": {
"idempotencyKey": {
"type": "string",
"minLength": 8,
"maxLength": 200,
"description": "caller-generated key for this intended production; reuse it after a timeout/network error to receive the original job without another debit or provider submission"
},
"kind": {
"const": "image",
"type": "string"
},
"spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"prompt": {
"description": "override the auto-derived content: the video/image prompt, the vo script, or the music brief (default is built from the creative’s copy/storyboard/script); not used for motion — pass headline/subline/cta instead",
"type": "string",
"minLength": 1
}
}
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"idempotencyKey",
"kind"
],
"properties": {
"idempotencyKey": {
"type": "string",
"minLength": 8,
"maxLength": 200,
"description": "caller-generated key for this intended production; reuse it after a timeout/network error to receive the original job without another debit or provider submission"
},
"kind": {
"const": "vo",
"type": "string"
},
"spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"script": {
"description": "override the auto-derived content: the video/image prompt, the vo script, or the music brief (default is built from the creative’s copy/storyboard/script); not used for motion — pass headline/subline/cta instead",
"type": "string",
"minLength": 1
}
}
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"idempotencyKey",
"kind"
],
"properties": {
"idempotencyKey": {
"type": "string",
"minLength": 8,
"maxLength": 200,
"description": "caller-generated key for this intended production; reuse it after a timeout/network error to receive the original job without another debit or provider submission"
},
"kind": {
"const": "music",
"type": "string"
},
"spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"durationSeconds": {
"description": "video 5–10s and rendered motion 5–10s (both billed per second), music 5–180s, programmatic motion 5–15s loop; ignored for image/vo",
"type": "integer",
"minimum": 5,
"maximum": 180
},
"brief": {
"description": "override the auto-derived content: the video/image prompt, the vo script, or the music brief (default is built from the creative’s copy/storyboard/script); not used for motion — pass headline/subline/cta instead",
"type": "string",
"minLength": 1
}
}
}
}
},
{
"type": "object",
"additionalProperties": false,
"required": [
"idempotencyKey",
"kind"
],
"properties": {
"idempotencyKey": {
"type": "string",
"minLength": 8,
"maxLength": 200,
"description": "caller-generated key for this intended production; reuse it after a timeout/network error to receive the original job without another debit or provider submission"
},
"kind": {
"const": "motion",
"type": "string"
},
"spec": {
"type": "object",
"additionalProperties": false,
"properties": {
"durationSeconds": {
"description": "video 5–10s and rendered motion 5–10s (both billed per second), music 5–180s, programmatic motion 5–15s loop; ignored for image/vo",
"type": "integer",
"minimum": 5,
"maximum": 180
},
"headline": {
"description": "motion only: headline text that animates in/out (default: from the creative’s copy)",
"type": "string",
"minLength": 1
},
"subline": {
"description": "motion only: supporting line staggered behind the headline (default: from the creative)",
"type": "string",
"minLength": 1
},
"cta": {
"description": "motion only: call-to-action text shown last (default: from the creative)",
"type": "string",
"minLength": 1
},
"resolution": {
"description": "motion only: DOOH screen resolution — 1080x1920 portrait D6, 1920x1080 landscape HD, 1400x400 ribbon banner (default fits the creative’s channel)",
"type": "string",
"enum": [
"1080x1920",
"1920x1080",
"1400x400"
]
},
"mode": {
"description": "motion only: \"programmatic\" = deterministic animated SVG loop generated in-process (zero provider cost — priced at the minimum charge; ready immediately); \"rendered\" = provider video loop billed per second (default: programmatic)",
"type": "string",
"enum": [
"programmatic",
"rendered"
]
}
}
}
}
}
]
},
"bodyMapping": {
"idempotencyKey": "idempotencyKey",
"kind": "kind",
"spec": {
"video": {
"tier": "tier",
"durationSeconds": "durationSeconds",
"prompt": "promptOverride"
},
"image": {
"prompt": "promptOverride"
},
"vo": {
"script": "promptOverride"
},
"music": {
"durationSeconds": "durationSeconds",
"brief": "promptOverride"
},
"motion": {
"durationSeconds": "durationSeconds",
"headline": "headline",
"subline": "subline",
"cta": "cta",
"resolution": "resolution",
"mode": "mode"
}
},
"omission": "Only supplied fields for the selected kind are included; an empty spec is omitted."
},
"responseMapping": "MCP preserves the REST object and adds a human-readable charged note when chargedMinor is present."
}Output
This is the registered MCP output envelope. Nested fields are only modeled where the schema explicitly defines them.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"job": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
}
},
"required": [
"job"
],
"additionalProperties": {}
}Safety annotations
{
"readOnlyHint": false,
"destructiveHint": true,
"idempotentHint": true,
"openWorldHint": true
}Annotations help a client present the tool. The API independently enforces authorization and exact action approvals. Error and retry guidance →