AI image/video/audio generation via MCP — full flow (media → model → estimate → job → poll), scenes and credit costs.
The ugc_* namespace exposes uPubly's content generation engine: image,
video and audio models routed through a provider auction, charged in
credits with automatic refund on failure/cancellation.
media_upload_from_url (URL → file_id in one call, public URLs only,
max 20MB) or the 2-step presigned path
(storage_request_upload → PUT → storage_complete_upload). The
returned file_id is the media_id used in refs, avatars and scenes.ugc_models_list returns model_key + capabilities
(aspectRatios, resolutions, durationsSec, acceptsImageRefs,
acceptsDrivingVideo, lipsync) + price hint.ugc_estimate with the same input as create: runs the
same routing/auction without persisting or charging. The displayed
number is the charged number.credits_balance checks the user has enough credits.ugc_job_create DEBITS CREDITS on creation and returns the
queued job. Send idempotency_key for safe retries (without one the
backend derives it from the payload — retry never double-charges).ugc_job_get until succeeded or failed.
The result lands in resultUrl / resultMediaId — a file_id
reusable as a reference in later jobs.failed auto-refunds; ugc_job_cancel cancels and
refunds in full.ugc_models_list{ "output_kind": "image|video|audio (optional filter)" }→ { "models": [{ "key", "displayName", "outputKind", "brand", "capabilities", "estimatedCreditsPerUnit" }] }
ugc_estimate{
"model_key": "seedance-2.0",
"prompt": "optional when refs are enough",
"params": { "...": "same schema as ugc_job_create" }
}→ { "credits", "usdEstimated", "mode", "provider", "fallbackProvider" }
ugc_job_create{
"model_key": "required (ugc_models_list)",
"prompt": "optional when refs are enough",
"idempotency_key": "recommended",
"params": {
"duration_sec": 5,
"aspect_ratio": "9:16|16:9|1:1",
"resolution": "720p|1080p",
"image_ref_media_ids": ["media_id — direct visual ref (i2i)"],
"extra_ref_media_ids": ["media_id — scene/style; with avatar+pose_copy becomes the copied scene"],
"driving_video_media_id": "media_id of the driving video (motion/lipsync)",
"avatar_ids": ["avatar_id — identity refs (base+sheets)"],
"avatar_include_base": true,
"avatar_sheet_kinds": ["angles", "expressions"],
"pose_copy": true,
"voice_id": "voice (audio/lipsync)",
"timestamps": true,
"format": "mp4",
"scene_id": "library scene as background",
"template_id": "driving template (ugc_templates_list)",
"project_id": "project to organize (ugc_projects_list)",
"script_id": "linked script",
"mentions": [{ "token": "@maria", "kind": "avatar|scene|ref", "id": "..." }],
"extra": { "provider-specific params": "..." }
}
}→ { "job": { "id", "status", "costCredits", "charged", "params", ... }, "replayed": false }
avatar_ids bring the avatar's identity refs (base + current sheets — fine
control via avatar_include_base / avatar_sheet_kinds).
extra_ref_media_ids with pose_copy: true (default when avatar+extras are
present) enable scene recreate mode: the extra image defines pose,
framing and setting, with the avatar replacing the person. With
pose_copy: false extras are just style context.
ugc_job_get{ "job_id": "..." }→ status (queued|running|succeeded|failed|cancelled), costCredits,
charged, refunded, errorReason, resultMediaId, resultUrl. Manual
polling — repeat until a terminal status.
ugc_jobs_list{
"kind": "image|video|audio", "status": "...", "avatar_id": "?",
"project_id": "?", "page": 0, "size": 20, "ready_for_video": true
}→ workspace gallery (newest first).
ugc_job_cancel / ugc_job_deleteCancels a non-terminal job with full refund / removes it from the gallery (an active job is cancelled first — the media_file survives).
{ "job_id": "..." }Scenes are reusable backgrounds — scene_id in job params applies the
scene as the background.
ugc_scene_create — three paths{ "name": "Neon studio", "media_id": "file_id" }→ Direct upload — the image becomes the scene. Free, no job.
{ "name": "Empty beach", "prompt": "beach at dusk", "model_key": "...", "aspect_ratio": "9:16" }→ t2i empty environment (the backend instructs "no people" automatically).
purpose=scene job — returns job_id to poll.
{ "name": "Copy café", "ref_media_ids": ["file_id"], "prompt": "optional extra direction" }→ Scene copy (i2i): recreates location, framing, lighting and mood from the refs removing people. Refs alone are enough — prompt is just extra direction.
ugc_scenes_list / ugc_scene_update / ugc_scene_deleteList (a scene with jobId + url: null is still generating), rename and
remove (soft delete).
media_upload_from_url{ "url": "https://.../image.png", "file_name": "optional" }→ { "file_id", "file_url" } in one call. Public http(s) URLs only —
private/loopback/link-local IPs are rejected (anti-SSRF), max 20MB.
ugc_templates_list / ugc_projects_listTemplates = ingested driving videos (use id as template_id in video).
Projects = job organization (project_id).
credits_balance→ { "monthly_balance", "topup_balance", "total_balance", "monthly_allowance", "cycle_ends_at", "plan_name" }
Check before any debiting operation — insufficient credits return isError
with the balance message.
See also: Avatars · Video generation · Tools