Skip to main content
Glama

wrmax-criativo

Pipeline de generación y edición de imágenes de WRMax. Claude Code es el cerebro; este repo es la mano.

El código no sabe nada de marketing: recibe parámetros y devuelve un archivo. Quien decide formato, ángulo y prompt es Claude, que después mira la pieza generada y decide si la acepta o la rehace. Es ese bucle cerrado lo que caracteriza la orquestación.

El código, los comentarios y los mensajes están en inglés. La documentación y la conversación con el equipo siguen en portugués.


Configuración (5 minutos)

npm install
export OPENAI_API_KEY="sua-chave"      # https://platform.openai.com/api-keys

Importante: la suscripción a ChatGPT Pro o a la app Gemini no da acceso a la API. Son cobros separados. Se necesita una clave de API con facturación activa.

Motor B (aún no implementado):

export IMAGE_PROVIDER=gemini
export GEMINI_API_KEY="sua-chave"

Related MCP server: MCP OpenAI Image Generation Server

Estructura

Cada carpeta tiene una responsabilidad, y ningún archivo acumula dos.

bin/                      entradas executáveis
  cli.js                    CLI
  mcp-server.js             servidor MCP (só escolhe o transporte)

src/
  bootstrap/              carga do .env e resolução de caminhos
  config/                 ÚNICO ponto que lê process.env; tabelas de modelo,
                          formato e qualidade
  brands/                 brand kit, compliance e montagem do prompt
  media/                  entrada, redução e saída de imagem (Drive, download,
                          arquivo local, preview, upload)
  providers/              motores de imagem, por registro
  core/                   regra de negócio: artwork-service, artifact-store,
                          delivery
  mcp/                    servidor MCP, tools e transportes
  http/                   app Express, middleware, rotas e views
  auth/                   OAuth com Google
  cli/                    args, ajuda e orquestração do CLI

test/                     node --test, sem chave e sem custo
scripts/                  smoke — gasta crédito ou precisa de rede viva
brand/                    um JSON por cliente
out/                      saída local (só com PERSIST_OUTPUT=true)

El diseño central: src/core/artwork-service.js no sabe qué es MCP ni qué es CLI. Recibe una petición simple y devuelve un resultado simple. Quien formatea el content block es src/mcp/tool-result.js; quien escribe JSON en stdout es src/cli/run.js. Por eso los dos frontends comparten un único camino.

Toda dependencia (config, artifact store, directorio de marca) se inyecta, no se importa como singleton — es lo que permite probar la ruta, la tool y el servicio sin tocar el entorno.


Uso

Generar desde cero:

node bin/cli.js --brand forno-paulista --format feed \
  --prompt "Studio product shot of a rustic pizza on a wooden board, steam rising"

Editar foto real del cliente (cambio de fondo preservando el producto):

node bin/cli.js --brand forno-paulista --format square \
  --ref fotos/produto.jpg \
  --prompt "Change only the background to a clean warm studio gradient. Keep the product, its label and the lighting on it exactly unchanged."

Borrador barato antes de gastar en el final:

node bin/cli.js --quality draft --prompt "..."

Siempre borrador antes del final. Cuesta una fracción y evita rehacer caro.


Servidor MCP

npm run mcp          # stdio — é o que o Claude Code fala
npm run mcp:http     # Streamable HTTP em :8787/mcp — é o que conector remoto exige

Herramientas expuestas: list_brands, generate_image, edit_image.

No existe herramienta que liste, busque o navegue imágenes en el servidor, y esto es intencional: quien elige el archivo es el usuario. Una herramienta de búsqueda convertiría un prompt inyectado en una foto de cliente en un escaneo del entorno.

Los detalles de transporte, autenticación y destino de la resolución completa están en CLAUDE.md.


Cómo usa Claude Code el CLI

El comando imprime JSON en stdout y log en stderr. Esto es intencional: Claude ejecuta, lee el JSON, abre el PNG, evalúa y encadena la siguiente llamada. Sin humano en medio de cada iteración.

{"ok":true,"file":"out/1755777.png","seconds":6.2,"aspectRatio":"4:5"}

Códigos de salida: 0 éxito · 1 fallo técnico · 2 bloqueado por compliance — el 2 existe para que un hook distinga los dos casos.


Compliance

brand/*.json tiene un array forbidden_terms. El assertPromptAllowed() se ejecuta antes de la llamada y bloquea — ahorra crédito y, más importante, no depende de que el modelo obedezca la instrucción.

{
  "name": "Forno Paulista",
  "visual": {
    "style": "appetizing food photography, rustic warmth, artisanal",
    "colors": ["wood brown", "tomato red", "warm cream"],
    "lighting": "warm golden light, natural window light",
    "avoid": ["cold blue tones", "plastic-looking food"]
  },
  "forbidden_terms": [],
  "compliance_reason": ""
}

Marca

Bloqueo

cliente-medico

paciente, antes/después, cuerpo, resultado de procedimiento — CFM 2.336/2023

Prueba rápida del guardarraíl, sin clave y sin coste:

node bin/cli.js --brand cliente-medico --prompt "before and after of a patient"
# x BLOCKED by compliance rules for "Cliente médico (template CFM)"

Pruebas

npm test          # 110 testes, sem chave de API, sem rede externa, sem custo

Cubre: compliance, brand kit, config, artifact store, conversión de enlace de Drive, todos los modos de fallo de descarga, reducción, subida, tablas de tamaño, el flujo OAuth completo (con un Google falso), el descubrimiento que hace claude.ai, y los dos transportes MCP de extremo a extremo.

Las pruebas que gastan crédito o dependen de red viva quedan fuera de la suite, en scripts/:

npm run probe            # ~US$ 0,005 — separa "chave ruim" de "pipeline ruim"
npm run smoke:drive      # ~US$ 0,01  — link do Drive de ponta a ponta
npm run smoke:edit       # ~US$ 0,02  — o modelo edita ou só regenera?
npm run smoke:stateless  # ~US$ 0,01  — não deixa um byte para trás

Variables de entorno

Variable

Por defecto

Para qué

OPENAI_API_KEY

Obligatoria con el provider openai

IMAGE_PROVIDER

openai

Cambia el motor de imagen

MCP_TRANSPORT

stdio

stdio o http

PORT

8787

Puerto del modo HTTP

MCP_PATH

/mcp

Ruta del endpoint MCP

MCP_TOKEN

Bearer fijo (script y prueba; claude.ai no lo acepta)

MCP_BASE_URL

Obligatoria con OAuth: es el issuer, y debe ser fija

GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET

Activan el OAuth

MCP_EMAILS

Quién puede autorizar. Una cuenta de Google válida no es permiso

PERSIST_OUTPUT

false

Guarda la resolución completa en out/ (solo dev local)

ARTIFACT_TTL_MS

900000

Validez del enlace de descarga

ARTIFACT_MAX_BYTES

134217728

Tope de memoria del depósito de piezas


Alojamiento (EasyPanel, o cualquier host de contenedor)

El servidor guarda estado en memoria a propósito: clientes OAuth, tokens y el depósito de piezas son Map(). Esto exige un proceso vivo y único, y es lo que descarta la plataforma serverless: allí el POST /register caería en una instancia y el GET /authorize en otra, que no conoce al cliente. El inicio de sesión fallaría de forma intermitente, con un síntoma que no parece la causa.

Por eso el despliegue es contenedor, y la regla vale para cualquier host: una réplica solo. Para escalar más allá, cambia los tres almacenamientos en memoria por Redis primero.

El Dockerfile en la raíz sirve para cualquier plataforma de contenedor. Los pasos siguientes son de EasyPanel; en otro host cambia la interfaz, no el contenido.

El dominio viene antes

Google no acepta dirección IP como redirect de OAuth, y exige HTTPS. Es decir, un dominio es un requisito previo, no un acabado.

Apunta un registro A del subdominio a la IP del servidor. Quien no tenga dominio puede usar DNS comodín — mcp.<ip-con-guiones>.sslip.io resuelve solo a la IP incrustada en el nombre, y Let's Encrypt emite normalmente siempre que el puerto 80 esté abierto.

Servicio

  1. Crear servicio → App, con source en este repositorio y rama main.

  2. Build: Dockerfile, en la raíz.

  3. Environment:

    Variable

    Valor

    PORT

    8787

    MCP_BASE_URL

    https://<tu-dominio> — sin barra al final

    OPENAI_API_KEY

    la clave de OpenAI

    GOOGLE_CLIENT_ID

    del cliente OAuth (Aplicación Web)

    GOOGLE_CLIENT_SECRET

    del mismo cliente

    MCP_EMAILS

    quién puede autorizar, separado por comas

    MCP_TRANSPORT=http ya viene del Dockerfile — no lo definas.

  4. Domains: el subdominio apuntando al puerto 8787, con HTTPS activado.

  5. Deploy.

  6. Google Cloud Console → Credenciales → tu cliente OAuth, añade el redirect autorizado, exactamente:

    https://<seu-dominio>/oauth/google/callback
  7. claude.ai → conectores: https://<tu-dominio>/mcp.

El MCP_BASE_URL se convierte en el issuer del OAuth y se compara carácter por carácter con lo que el cliente descubre. Un dominio diferente del configurado, o una barra sobrante, hace que el vínculo falle sin mensaje útil.

Comprobación

curl https://<seu-dominio>/health

El campo que importa es "auth":"oauth". Si viene "none", alguna variable de Google no llegó — y entonces el servidor se levantó abierto, aceptando cualquier llamada y gastando la clave de quien lo aloja.


Notas de API que ahorran depuración

  • La K de image_size es mayúscula. 2k se rechaza.

  • gpt-image-2 acepta cualquier WxH divisible por 16; los más pequeños solo aceptan tres tamaños fijos. Story/reels final necesita gpt-image-2.

  • En la edición, la imagen viene antes del texto en el array de input.

  • No existe refacción encadenada en el provider openai: previous_interaction_id es de la Interactions API de Gemini. Para ajustar, reenvía la imagen como referencia.

  • Entrada por URL envía User-Agent propio: varios orígenes (Wikimedia entre ellos) devuelven 400/403 para una solicitud sin UA identificable.

  • Pieza con texto: define la copy primero, luego pide la imagen con esa copy.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Generate on-brand images from your AI agent: design, edit, and render templates over MCP.

  • Generate images with any major model — one API key, one prepaid balance, one MCP.

  • Generate and manage AI UGC video ads through eleven typed MCP tools

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/WrMaxMarketing/wrmmax-criativo-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server