generate_image
Generate marketing images with AI-powered templates. Use a text prompt for automatic template selection, or choose a template directly with custom slot values. Supports sizes for social media and more.
Instructions
Generate a marketing image. Two modes: (1) Prompt mode — provide a text prompt and AI picks the template. (2) Direct mode (recommended) — provide templateId + slots for precise control. Use list_templates to see available templates.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | No | Text prompt describing the image (used in prompt mode) | |
| template_id | No | Template ID for direct render mode. Use list_templates to see options. | |
| slots | No | Template slot values. Keys are slot names, values are strings. | |
| photo_query | No | 1-3 word search query for background photo (e.g. 'italian restaurant'). Only used with photo templates when no image_url is provided. | |
| image_url | No | URL of your own image to use as background | |
| size | No | Image size: '1080x1080' (Instagram, default), '1200x628' (OG/Twitter), '1080x1920' (Stories/Reels), '1200x1200' (Instagram HD), '1280x720' (YouTube) | |
| style | No | Visual style: modern, playful, corporate, dark, minimal, bold | |
| brand_kit_id | No | ID of a saved brand kit to use for consistent branding | |
| font | No | Google Font name to use (e.g. 'Poppins', 'Playfair Display') | |
| logo_url | No | HTTPS URL of a logo to overlay on the image | |
| logo_position | No | Position of the logo overlay. Default: bottom-right | |
| background | No | Background type: auto (AI decides), photo (force photo search), gradient (no photo) | |
| variants | No | Number of design variants to generate (1-3). Each variant has different colors/layout. |
Implementation Reference
- src/tools/generate-image.ts:1-150 (handler)Main tool registration and handler function for 'generate_image'. Calls client.generateImage() with parameters from the schema, handles both single image and multi-variant responses, and formats text output.
import { z } from "zod/v4"; import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import type { RendrKitClient } from "../api-client.js"; import type { GeneratedImage } from "../types.js"; export function registerGenerateImageTool( server: McpServer, client: RendrKitClient, ): void { server.registerTool( "generate_image", { description: "Generate a marketing image. Two modes: (1) Prompt mode — provide a text prompt and AI picks the template. (2) Direct mode (recommended) — provide templateId + slots for precise control. Use list_templates to see available templates.", inputSchema: { prompt: z .string() .optional() .describe("Text prompt describing the image (used in prompt mode)"), template_id: z .string() .optional() .describe( "Template ID for direct render mode. Use list_templates to see options.", ), slots: z .record(z.string(), z.string()) .optional() .describe( "Template slot values. Keys are slot names, values are strings.", ), photo_query: z .string() .optional() .describe( "1-3 word search query for background photo (e.g. 'italian restaurant'). Only used with photo templates when no image_url is provided.", ), image_url: z .string() .optional() .describe("URL of your own image to use as background"), size: z .enum(["1080x1080", "1200x628", "1080x1920", "1200x1200", "1280x720"]) .optional() .describe( "Image size: '1080x1080' (Instagram, default), '1200x628' (OG/Twitter), '1080x1920' (Stories/Reels), '1200x1200' (Instagram HD), '1280x720' (YouTube)", ), style: z .enum(["modern", "playful", "corporate", "dark", "minimal", "bold"]) .optional() .describe( "Visual style: modern, playful, corporate, dark, minimal, bold", ), brand_kit_id: z .string() .optional() .describe( "ID of a saved brand kit to use for consistent branding", ), font: z .string() .optional() .describe("Google Font name to use (e.g. 'Poppins', 'Playfair Display')"), logo_url: z .string() .optional() .describe("HTTPS URL of a logo to overlay on the image"), logo_position: z .enum(["top-left", "top-right", "bottom-left", "bottom-right"]) .optional() .describe("Position of the logo overlay. Default: bottom-right"), background: z .enum(["auto", "photo", "gradient"]) .optional() .describe("Background type: auto (AI decides), photo (force photo search), gradient (no photo)"), variants: z .number() .optional() .describe("Number of design variants to generate (1-3). Each variant has different colors/layout."), }, }, async ({ prompt, template_id, slots, photo_query, image_url, size, style, brand_kit_id, font, logo_url, logo_position, background, variants }) => { try { const result = await client.generateImage({ prompt, templateId: template_id, slots, photoQuery: photo_query, imageUrl: image_url, size, style, brandKitId: brand_kit_id, font, logoUrl: logo_url, logoPosition: logo_position, background, variants, }); // Variants > 1 returns { images: [...] } instead of a single image if (variants && variants > 1) { const multi = result as unknown as { images: GeneratedImage[] }; const lines = multi.images.map( (img: GeneratedImage, i: number) => `Variant ${i + 1}: ${img.url} (template: ${img.templateId})`, ); return { content: [ { type: "text" as const, text: `Generated ${multi.images.length} variants!\n\n${lines.join("\n")}`, }, ], }; } return { content: [ { type: "text" as const, text: [ `Image generated successfully!`, ``, `URL: ${result.url}`, `ID: ${result.id}`, `Size: ${result.width}x${result.height}`, result.templateId ? `Template: ${result.templateId}` : null, `Style: ${result.style}`, `Prompt: ${result.prompt}`, `Created: ${result.createdAt}`, ].filter(Boolean).join("\n"), }, ], }; } catch (error) { const message = error instanceof Error ? error.message : String(error); return { content: [ { type: "text" as const, text: `Failed to generate image: ${message}`, }, ], isError: true, }; } }, ); } - src/tools/generate-image.ts:10-80 (schema)Input schema using Zod validation. Defines all parameters: prompt, template_id, slots, photo_query, image_url, size, style, brand_kit_id, font, logo_url, logo_position, background, variants.
server.registerTool( "generate_image", { description: "Generate a marketing image. Two modes: (1) Prompt mode — provide a text prompt and AI picks the template. (2) Direct mode (recommended) — provide templateId + slots for precise control. Use list_templates to see available templates.", inputSchema: { prompt: z .string() .optional() .describe("Text prompt describing the image (used in prompt mode)"), template_id: z .string() .optional() .describe( "Template ID for direct render mode. Use list_templates to see options.", ), slots: z .record(z.string(), z.string()) .optional() .describe( "Template slot values. Keys are slot names, values are strings.", ), photo_query: z .string() .optional() .describe( "1-3 word search query for background photo (e.g. 'italian restaurant'). Only used with photo templates when no image_url is provided.", ), image_url: z .string() .optional() .describe("URL of your own image to use as background"), size: z .enum(["1080x1080", "1200x628", "1080x1920", "1200x1200", "1280x720"]) .optional() .describe( "Image size: '1080x1080' (Instagram, default), '1200x628' (OG/Twitter), '1080x1920' (Stories/Reels), '1200x1200' (Instagram HD), '1280x720' (YouTube)", ), style: z .enum(["modern", "playful", "corporate", "dark", "minimal", "bold"]) .optional() .describe( "Visual style: modern, playful, corporate, dark, minimal, bold", ), brand_kit_id: z .string() .optional() .describe( "ID of a saved brand kit to use for consistent branding", ), font: z .string() .optional() .describe("Google Font name to use (e.g. 'Poppins', 'Playfair Display')"), logo_url: z .string() .optional() .describe("HTTPS URL of a logo to overlay on the image"), logo_position: z .enum(["top-left", "top-right", "bottom-left", "bottom-right"]) .optional() .describe("Position of the logo overlay. Default: bottom-right"), background: z .enum(["auto", "photo", "gradient"]) .optional() .describe("Background type: auto (AI decides), photo (force photo search), gradient (no photo)"), variants: z .number() .optional() .describe("Number of design variants to generate (1-3). Each variant has different colors/layout."), }, - src/server.ts:3-3 (registration)Import of registerGenerateImageTool from the generate-image module.
import { registerGenerateImageTool } from "./tools/generate-image.js"; - src/server.ts:18-18 (registration)Registration call: registerGenerateImageTool(server, client) wires the tool into the MCP server.
registerGenerateImageTool(server, client); - src/api-client.ts:75-91 (helper)API client helper that sends a POST request to /api/v1/generate with all image generation parameters.
async generateImage(params: GenerateImageParams): Promise<GeneratedImage> { const body: Record<string, unknown> = {}; if (params.prompt) body.prompt = params.prompt; if (params.templateId) body.templateId = params.templateId; if (params.slots) body.slots = params.slots; if (params.photoQuery) body.photoQuery = params.photoQuery; if (params.imageUrl) body.imageUrl = params.imageUrl; if (params.size) body.size = params.size; if (params.style) body.style = params.style; if (params.brandKitId) body.brandKitId = params.brandKitId; if (params.font) body.font = params.font; if (params.logoUrl) body.logoUrl = params.logoUrl; if (params.logoPosition) body.logoPosition = params.logoPosition; if (params.background) body.background = params.background; if (params.variants) body.variants = params.variants; return this.request<GeneratedImage>("POST", "/api/v1/generate", body); } - src/types.ts:47-61 (helper)TypeScript interface GenerateImageParams defining the typed parameters for the API call.
export interface GenerateImageParams { prompt?: string; size?: string; style?: string; brandKitId?: string; templateId?: string; slots?: Record<string, string>; photoQuery?: string; imageUrl?: string; font?: string; logoUrl?: string; logoPosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right"; background?: "auto" | "photo" | "gradient"; variants?: number; } - src/types.ts:1-12 (helper)GeneratedImage interface defining the response shape (id, url, width, height, prompt, style, templateId, createdAt).
/** Response from the generate image endpoint */ export interface GeneratedImage { id: string; url: string; width: number; height: number; prompt: string; style: string; mode?: "direct" | "prompt"; templateId?: string; createdAt: string; }