Crear un post (carrusel) de Instagram o TikTok de N slides a partir de una plantilla propia de Canva, cambiando solo los textos (y, si la plantilla lo pide, una imagen libre de derechos). Úsala cuando el usuario pida un post, una publicación, un carrusel o contenido nuevo sobre un tema concreto, o mencione una de sus plantillas. También cuando pida "otro igual pero de X".
Resources
12Install
npx skillscat add josevictorgarcia/mcp-server-chinesereads-canva Install via the SkillsCat registry.
This skill generates multi-slide Instagram or TikTok carousel posts from a user's existing Canva template, replacing only the text and optionally one royalty-free image. It solves the repetitive task of manually adapting branded templates for new topics by following an eleven-step workflow that checks history, validates slide counts, and avoids recently used content. Use it when an agent needs to produce new social media content from a specified template, whether from scratch or as a variant on a previous post.
Generar un post de N slides desde plantilla
Flujo de once pasos. No te saltes la validación ni el registro.
1. Elegir plantilla y determinar N
Si el usuario no dice cuál plantilla, llama a listar_plantillas y elige por la
descripción. Si dos encajan, pregunta en vez de adivinar.
El número de slides (N) lo dice el usuario en la propia petición ("5 palabras",
"6 redes sociales..."). Si no da un número explícito, pregúntaselo — no lo
inventes. N no puede superar el max_paginas de la plantilla (preparar_encargo
lo rechazará si te pasas, pero avisa antes si ya sabes que N es demasiado alto).
2. Pedir el contrato
Antes de nada, si trabajas en el Mac y publicacion_config.json tienevps.ssh, baja el historial del servidor por si el generador autónomo
publicó algo mientras tanto (si no, repetirías palabras o portadas):
rsync -a --update <vps.ssh>:/home/chinesereads/publicador/historial.json ./historial.json--update solo sobrescribe si el del servidor es más nuevo, así que nunca
pierdes lo tuyo. Si el VPS no responde, sigue sin bloquearte y dilo en el
resumen final.
Luego llama a preparar_encargo(plantilla_id, tema, numero_slides). Te devuelve los
huecos por slide, las reglas de estilo, los temas ya publicados y loselementos_recientes (palabras usadas en los últimos posts de esta plantilla,
que hay que evitar por ahora — no para siempre).
Si tema_ya_usado es true, avisa al usuario antes de seguir. Puede que quiera
otro tema o una segunda parte con palabras distintas.
3. Generar el contenido de cada slide
Para cada una de las N slides, escribe el contenido respetando las reglas de
estilo al pie de la letra. Cuenta los caracteres: los huecos tienen límites
porque el texto no cabe de otro modo y la plantilla se rompe visualmente.
- Evita repetir palabras que aparezcan en
elementos_recientes. - No repitas nada entre las propias slides del post (todas del mismo campo
semántico, pero cada una distinta). - Cada slide necesita un
identificadorpropio (normalmente la palabra/carácter
principal de esa slide) — es lo que se registrará luego para el control de
repetidos.
Si la plantilla tiene un hueco de tipo imagen: busca en la API pública de
Openverse (https://api.openverse.org/v1/images/?q=<consulta>&license=cc0,pdm)
una imagen que represente el significado del carácter, filtrando solo
licencia cc0 o pdm (dominio público). Nunca uses una imagen de otra
licencia, aunque el resultado parezca perfecto — es la regla que evita
problemas legales.
Si no hay ningún resultado CC0/PDM que encaje, segundo intento con IA:
llama a generar_imagen_ia(prompt, ruta_destino) con un prompt de objeto
literal ("a bowl of white steamed rice, minimalist food photography, clean
background") y la ruta dentro de la carpeta del post. La herramienta elige el
mejor modelo disponible, descarga la imagen y devuelve url_para_canva para
el upload-asset-from-url posterior. Mira el fichero descargado; si tras
2-3 semillas ninguna es clara y reconocible, o el servicio no responde (se
satura a ratos), para y pide la imagen al usuario. Una imagen generada por IA
no tiene el problema de licencia, pero sí puede salir deforme — el filtro
visual no es opcional.
4. Validar
Llama a validar_contenido(plantilla_id, contenido) con el contenido de texto de
cada slide por separado (no hace falta pasar los huecos de imagen). Sivalido es false, corrige lo que diga errores y vuelve a validar. No
pases al paso 5 sin que las N slides estén en verde. Reformula en vez de
truncar a lo bruto.
5. Crear el diseño en Canva
Con las herramientas del servidor MCP de Canva:
- Carpeta del post en Canva: la carpeta madre
chinesereads-postsya
existe y su id está enplantillas.json(carpeta_posts_canva_id); si
Canva dice que no existe, recréala concreate-folderenrooty
actualiza ese id. Crea dentro una carpeta nueva para este post
con el mismo nombre que la carpeta local (<tema>[-<plantilla>]-<fecha>).
Todos los diseños que crees en los pasos siguientes se mueven ahí conmove-item-to-folder— así cada post queda agrupado en Canva y no
suelto en la raíz. - Duplica el diseño maestro:
copy-design(design_id=canva_design_id, page_numbers=[1..N]). Esto crea un diseño nuevo de exactamente N páginas, ya
independiente del maestro. Muévelo a la carpeta del post. - Por cada una de las N páginas:
start-editing-transactionsobre el diseño
nuevo, localiza los elementos de esa página cuyo texto actual coincide con eltexto_actualde cada hueco, y sustitúyelos conperform-editing-operations
(replace_textpara huecos de texto). Para un hueco de imagen: sube la
imagen encontrada conupload-asset-from-urly sustitúyela conupdate_fill
sobre el elemento de imagen de esa página. commit-editing-transactioncuando todas las páginas estén editadas.
Trabaja solo con elementos que ya están en la plantilla y con recursos
gratuitos. No añadas elementos premium: salen con marca de agua en cuentas
gratuitas.
Regla que no se rompe nunca: no edites el diseño maestro (canva_design_id
del catálogo). Todo el trabajo va sobre el diseño copiado en el paso 1.
6. Exportar
Llama a get-export-formats sobre el diseño copiado y luego export-design
(con pages cubriendo todas las N páginas). Canva no empaqueta un PNG
multi-página en un solo archivo: devuelve una URL por página. Descarga las
N con curl a una carpeta local posts/<tema>[-<plantilla>]-<fecha>/ dentro
del repo (esa carpeta está en .gitignore, no se sube a git — son imágenes
regenerables, no código).
7. Portada
Todo post lleva portada salvo que el usuario diga lo contrario. Es un diseño
independiente (la plantilla portada del catálogo, de 1 página), pero su
PNG se guarda en la misma carpeta del post, como 00-portada.png, para que
el post quede completo en un solo sitio. Si el catálogo aún no tiene la
plantilla portada, salta este paso y avísalo en el resumen final.
- Título: en inglés, gancho corto tipo "5 words you must know if you go
to China" o "4 food words in Chinese". Consultaportadas_recientesy varía
la redacción respecto a los títulos recientes. Valídalo convalidar_contenido('portada', {"TITULO": ...}). - Imagen de fondo — dos orígenes, por preferencia del usuario:
IA gratuita (Pollinations): llama a
generar_imagen_ia(prompt, ruta_destino=<carpeta del post>/portada-candidata.png)
con un prompt escrito con guiones en vez de espacios (una URL sin
percent-encoding es la única que el fetcher de Canva descarga bien) y
fotográfico de estética China ligado al tema del post:
comida → mercado o plato; transporte → tren, estación, bicis; naturaleza
→ paisaje... No siempre el mismo tipo de escena (los callejones con
farolillos quedan muy bien, pero varía la imaginería respecto aportadas_recientes). Paisajes, arquitectura y primeros planos sin
gente funcionan mejor que escenas con personas. Y manda la legibilidad:
mejor una imagen algo menos espectacular con una zona tranquila donde
el título respire que una espectacular que se coma las letras. La herramienta elige sola el mejor modelo oficial
del catálogo (klein/zimage/flux si hay clave en.pollinations_tokeny
saldo de pollen; si no, cae al clásico anónimo a 768×768 — aceptable, y
el resultado dice enendpointyavisosqué pasó), descarga la imagen y
devuelveurl_para_canvapara el montaje. Mira el fichero (lee la
imagen): si sale borrosa, deforme o pobre, reintenta con otraseed
(hasta 3 veces; si ninguna convence, pasa a galería o pregunta). No
reutilices un prompt+seed que aparezca enportadas_recientes. Ojo: el
servicio gratuito se cae a ratos; si la herramienta falla, no insistas
más de un par de minutos — pasa a la galería del usuario o a una foto
CC0 de paisaje de Openverse y díselo en el resumen.Frugalidad con el pollen: cada generación nueva gasta saldo, así que
piensa el prompt con calma ANTES de generar — incluida la composición
(pide una zona tranquila, oscura o despejada, donde irá el título:
regenerar por legibilidad es el error caro típico). El objetivo es
acertar a la primera; el tope de 3 intentos es un máximo, no una
rutina. Volver a descargar un prompt+seed ya generado es gratis
(caché); cambiar de semilla o de prompt, no.Descartes: las candidatas que no acaben en la portada no se borran —
muévelas aposts/descartes/con nombre descriptivo
(<fecha>-<tema>-vN.jpg). Son del usuario y ya están pagadas. Además,
súbelas a Canva (la copia que sobrevive aunque se limpie el disco):upload-asset-from-urlcon laurl_para_canvade cada candidata
(gratis: es caché) y nombredescarte-<fecha>-<tema>-vN, y mueve el
asset conmove-item-to-foldera la carpetadescartesde Canva
(id enplantillas.json→carpeta_descartes_canva_id).Galería del usuario (assets de Canva): lista sus fotos subidas con
get-assetsy elige una cuyo nombre/id no esté enportadas_recientes— la rotación es lo que evita que la portada se
repita. Descarga su miniatura para el paso de brillo.
- Brillo: pasa el fichero descargado a
analizar_brillo. Si recomienda
título "claro" u "oscuro" distinto del color por defecto de la plantilla,
ajústalo conformat_textal editar. Sicontraste_justoestrue,
comprueba que el degradado/sombra de la plantilla sigue detrás del título. - Montaje:
copy-designde la plantillaportada(1 página) → muévelo
conmove-item-to-foldera la misma carpeta del post en Canva que el
diseño de slides → sube la imagen (upload-asset-from-urlcon laurl_para_canvaque devolviógenerar_imagen_ia, o el asset ya
existente de galería) →update_fillen el hueco de imagen +replace_textdel título →commit. La marca de agua de chinesereads ya
vive en la plantilla maestra: no la toques. - Exportar y descargar como
00-portada.pngen la carpeta del post.
8. Slide final
Todo post cierra con una slide final (después de las de vocabulario), salvo
que no haya ninguna disponible. Las plantillas de cierre las mantiene el
usuario A MANO en la carpeta de Canva chinesereads-plantillas-final (id enplantillas.json → carpeta_finales_canva_id): puede añadir, borrar o
renombrar plantilla-final-N cuando quiera, así que consúltala en vivo
en cada post:
list-folder-itemssobre esa carpeta (tipodesign). Si está vacía, el
post va sin cierre — no es un error: salta el paso y dilo en el resumen.- Pasa los títulos a
elegir_final(candidatos). La rotación (la que lleva
más posts sin usarse; entre nunca-usadas, al azar) la decide código — no
elijas tú. - La slide elegida no se edita ni se copia:
export-designdirectamente
sobre ese diseño (1 página, solo lectura) y descarga el PNG como99-final.pngen la carpeta del post — el 99 la deja siempre la última
al ordenar, detrás de portada y slides. - Guarda título e id para el registro del paso siguiente.
9. Registrar
Llama una sola vez a registrar_publicacion(plantilla_id, tema, slides, url_diseno, portada=..., final=...)
con slides siendo la lista de las N slides (identificador + contenido de
cada una) y url_diseno el link de edición del diseño en Canva (no el de
exportación). Si hubo portada, pasaportada={"titulo": ..., "imagen": <nombre del asset o prompt+seed>, "origen": "ia"|"galeria"|"manual"} —
sin esto el cooldown de portadas no funciona. Para una portada de IA, imagen
es el prompt+seed (y el modelo). Si hubo slide final, pasa tambiénfinal={"nombre": <título de la plantilla-final>, "design_id": ...} — sin
esto la rotación de elegir_final no aprende. Solo después de que el diseño
exista. Esto es lo que evita repetir palabras, temas, fotos de portada y
slide de cierre.
10. Encolar para publicación automática
Si existe publicacion_config.json en la raíz del repo con la secciónvps rellena, el post se encola para que el VPS lo publique solo (ver
docs/publicacion.md). Si el fichero no existe, salta este paso sin más y dilo en
el resumen final.
Caption (descripción de la publicación), en inglés y en la voz de
la cuenta (@chinesereadsapp). Su patrón real, corto y sin adornos:How to express surprise in chinese Follow for more! #learnchinese #chineseexpressions #dku #chineselanguage #chineselanguagelearning- Primera línea: gancho corto o pregunta directa ("Have you ever
mistaken them?", "Did you know all of them? 🤔"). Puede variar el
título de la portada, no calcarlo. - Una línea de llamada a la acción que invite a comentar o seguir
("Let me know in the comments!", "Comment if you knew them!",
"Follow for more!"). Los comentarios tempranos ayudan al alcance. - Cuando encaje, el plug de la web tal y como lo escribe él:
"Learn chinese with chinesereads.com". - Nada de listas de palabras: sus captions son breves; el
vocabulario ya está en las slides. - Hashtags: si el usuario dio hashtags en la petición, usa ESOS. Si
no, no los escribas en la caption: el publicador añade loshashtags_por_defecto. Enhashtagsdel meta.json puedes poner una
mezcla de esos y 2-3 específicos del tema — unos 5 en total, que
es lo que usa la cuenta. Nada de bloques de 20 hashtags.
- Primera línea: gancho corto o pregunta directa ("Have you ever
Convertir las imágenes: llama a
preparar_para_cola(<carpeta del post>). Instagram solo admite JPEG y TikTok limita a 1080p y 20 MB,
así que los PNG de 2048 px de Canva no valen para publicar: la
herramienta deja en<carpeta del post>/_cola/los.jpga 1080 px
listos (los PNG originales se quedan intactos como archivo).meta.jsondentro de esa carpeta_cola/, con el formato
documentado en docs/publicacion.md:tema,titulo(el de la portada),caption(sin hashtags),hashtags(opcional, ver arriba),imagenes
(los .jpg, en orden: portada primero, luego las slides y99-final.jpgla última si la hay),creado(fecha de hoy).Subir a la cola (siempre la carpeta
_cola/, nunca la del post
entero — los PNG no se publican y ocuparían el triple):- Si
vps.sshtiene valor (estás en el Mac):rsync -av <carpeta del post>/_cola/ <vps.ssh>:<vps.ruta_cola>/<nombre del post>/. Si el
rsync falla (VPS caído, sin red), no es un error del post: dilo en el
resumen y deja el comando listo para que el usuario lo lance luego. - Si
vps.sshestá vacío (estás EN el VPS, modo autónomo): copia_cola/acola/<nombre del post>/en la raíz del repo y comprueba
conpython3 publicador.py colaque aparece.
- Si
Sube el historial actualizado al servidor, para que el generador
autónomo conozca lo que acabas de publicar:rsync -a --update ./historial.json <vps.ssh>:/home/chinesereads/publicador/historial.json
(omítelo si estás EN el VPS: ahí ya es el mismo fichero).Enséñaselo al usuario: manda las imágenes del post
(SendUserFilecon los.jpgde_cola/, portada primero) junto con la
caption y los hashtags exactos que se publicarán. Es su única
oportunidad de revisarlo antes de que salga solo: la API de Instagram no
crea borradores, así que lo que hay en la cola se publica tal cual.
El post se publicará automáticamente a las 20:00 (hora española) del primer
día en que sea el más antiguo de la cola. Si el usuario quiere retenerlo
hasta una fecha, o revisarlo con calma antes, pon no_publicar_antes_de en
el meta.json (así se queda en la cola sin publicarse hasta esa fecha).
11. Al terminar
Resume en pocas líneas: qué plantilla usaste, el tema, cuántas slides y en qué
carpeta local quedaron descargadas las imágenes. Recuerda al usuario que
revise el diseño antes de publicar — la sustitución de texto puede descuadrar
un salto de línea, y eso se ve a simple vista pero el modelo no lo ve. Si
alguna slide llevaba imagen buscada automáticamente, señálalo explícitamente:
la licencia está garantizada, pero el acierto temático de la imagen conviene
revisarlo a ojo. Lo mismo con una portada generada por IA: ya la filtraste
visualmente, pero la última palabra sobre si representa bien a la cuenta es
del usuario.
Si el post quedó encolado (paso 10), di cuándo saldrá (posición en la cola ×
1 post/día a las 20:00) y recuerda que sigue a tiempo de retocarlo en Canva y
reexportar antes de esa hora. Si no hay publicación automática configurada,
la subida a Instagram y TikTok es manual.