Skip to main content
Glama

Seedance MCP

Servidor MCP (stdio) para generar video con Seedance 2.0 de ByteDance/Ark, accesible desde OpenClaw como cualquier otra herramienta.

Cero dependencias: solo node:crypto y fetch. Requiere Node 20+.

Instalación

git clone https://github.com/luc444s/seedance-mcp
cd seedance-mcp
cp .env.example .env      # rellena SEEDANCE_API_KEY
bash scripts/install.sh

El instalador busca las credenciales en, por orden:

  1. Variables de entorno (SEEDANCE_API_KEY, R2_*)

  2. SEEDANCE_ENV_FILES="/a/.env /b/.env"

  3. ./.env, ../../backend/.env, ~/Proyectos/orquestador_ardi/backend/.env

Después las persiste en $OPENCLAW_STATE_DIR/seedance.env con chmod 600 y registra el server con openclaw mcp add.

Verifica con:

openclaw mcp probe seedance    # -> 5 tools

Related MCP server: seedance-2-mcp

Seguridad

Ninguna credencial se versiona. Para que no dependa de que me acuerde:

Mecanismo

Qué hace

.gitignore

Ignora .env*, seedance.env, state/, *.mp4, *.mov

.env.example

Plantilla con los nombres de variable, todos vacíos

scripts/audit-secrets.mjs

Escanea el repo y falla si encuentra una clave

CI

Corre el auditor en cada push y PR

Reglas que detecta el auditor: oc_sk_*, ark-*, AKIA*, firmas TOS, Bearer <literal>, claves privadas PEM, y cualquier valor asignado a una variable sensible que no sea un placeholder o una indirección ($OTRA_VAR).

npm run audit

Herramientas

Tool

Qué hace

seedance_generate

Crea un video (t2v / i2v / v2v). wait:true espera y devuelve la URL.

seedance_from_file

Atajo: publica un archivo del chat y genera en una sola llamada.

seedance_upload

Publica un archivo local (o URL) en R2 y devuelve su URL.

seedance_status

Consulta el estado de una tarea por id.

seedance_wait

Espera a que una tarea termine y devuelve la URL.

seedance_archive

Sube el video de una tarea a R2 (URL permanente).

seedance_list

Lista las tareas registradas localmente.

Por qué R2 es obligatorio en la práctica

ByteDance corre en servidores remotos: cuando le mandás una URL, ellos la descargan. No pueden ver tu disco.

OpenClaw guarda lo que subís al chat en state/media/inbound/<id>, y al agente le llega como path local. Ese path no le sirve a Seedance.

Por eso el flujo es siempre:

1. Subís el archivo al chat   → state/media/inbound/abc.mp4   (local, invisible para ByteDance)
2. seedance_upload            → https://aihopper.sihuen8.workers.dev/...
3. seedance_generate          → ByteDance la descarga y funciona

seedance_from_file hace los pasos 2 y 3 juntos. Resuelve el path solo gracias a OPENCLAW_MEDIA_DIR, que el instalador detecta ($OPENCLAW_STATE_DIR/media/inbound).

Ejemplo desde el chat:

"subí este video, hacé una versión en cámara lenta"

El agente llama seedance_from_file({ source: "abc123.mp4", prompt: "slow motion, camera push in" }) y listo.

R2 (archivos permanentes)

Las URLs de ByteDance están firmadas por TOS y expiran en 24h. Para conservar un resultado o reutilizarlo como referencia de v2v hay que publicarlo en Cloudflare R2.

Dos formas:

// 1. Al generar, con archive:true → devuelve publicUrl además de videoUrl
{ "prompt": "...", "archive": true }

// 2. Después, sobre una tarea existente (o directamente una URL de video)
seedance_archive({ "taskId": "cgt-2026...", "key": "seedance/mi-video.mp4" })

Config (el instalador las lee de backend/.env):

R2_ENABLED=true
R2_ACCOUNT_ID / R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY
R2_BUCKET=ai-hopper-assets
R2_PUBLIC_URL=https://aihopper.sihuen8.workers.dev

scripts/r2.mjs implementa el PUT con AWS SigV4 usando solo node:crypto — sin boto3 ni dependencias extra. Si R2 no está configurado, el server sigue funcionando y solo lo avisa en archiveError.

Modos soportados

Modo

Parámetro

Payload

text-to-video

solo prompt

{type:"text"}

image-to-video

imageUrl

+ {type:"image_url"}

video-to-video

videoUrls[]

+ {type:"video_url", role:"reference_video"}

En v2v el prompt es una instrucción de qué cambiar (movimiento de cámara, transposición de estilo, etc.), no una descripción completa.

Restricciones de v2v (verificadas contra la API): máx 3 videos, duración total ≤15s, formatos mp4/mov. La URL debe ser pública y accesible para ByteDance.

Tiempos reales medidos

Modo

Duración

t2v 5s 480p

~40s

v2v 5s 480p

~6 min

Por eso el server da 900s de presupuesto automático cuando detecta videoUrls. Para v2v conviene wait: false y consultar después.

Parámetros de seedance_generate

Campo

Tipo

Default

Notas

prompt

string

—

Requerido. Inglés o chino.

imageUrl

string

—

URL pública → modo image-to-video

videoUrls

string[]

—

URLs públicas de videos de referencia → modo v2v. Máx 3, ≤15s total

model

string

dreamina-seedance-2-0-260128

resolution

enum

720p

480p / 720p / 1080p

duration

number

5

2–12s

ratio

string

—

16:9, 9:16, 1:1, 4:3, 21:9

generateAudio

boolean

true

Seedance 2.0 genera audio nativo

watermark

boolean

false

cameraFixed

boolean

—

seed

number

—

Reproducibilidad

wait

boolean

true

false devuelve solo el taskId

pollInterval

number

5

segundos entre polls

Formato de prompt recomendado

El prompt canónico de Seedance:

FORMAT: cinematic 8-second single shot.
SUBJECT: a lone lighthouse keeper walking across a rain-slicked pier.
ENVIRONMENT: stormy North Atlantic night, crashing waves, heavy fog.
MOOD: solitary, tense.
STYLE: anamorphic, shallow depth of field, teal-orange grade.
LOGIC RULE: camera moves slowly, subject stays centered.
NEGATIVE PROMPT: no text, no watermark, no distortion.
SHOT 1: slow dolly-in following him from behind.

Máximo recomendado: 800 caracteres.

Notas importantes

  • Las URLs expiran en 24h (firma TOS). Si necesitás el archivo permanente, descargalo y subilo a R2/CDN.

  • El timeout de polling por defecto es 300s (SEEDANCE_POLL_MAX). Un video de 10s suele tardar 1–3 min.

  • Seedance 2.0 es el único con soporte de audio nativo y refs multimodales; los modelos 1.x degradan a first/last frame.

  • Los videos se registran en $SEEDANCE_STATE_DIR (default /tmp/seedance-mcp).

Verificación manual

KEY=$(grep '^SEEDANCE_API_KEY=' ../../backend/.env | cut -d= -f2)
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | SEEDANCE_API_KEY="$KEY" node scripts/seedance-mcp.mjs

Related MCP Connectors

Related MCP Servers