Skip to main content
Glama

generate_story

Create sequential images to visualize stories, processes, tutorials, or timelines with customizable steps, styles, and layouts.

Instructions

Generate a sequence of related images that tell a visual story or show a process

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
promptYesDescription of the story or process to visualize
stepsNoNumber of sequential images to generate (2-8)
typeNoType of sequence to generatestory
styleNoVisual consistency across framesconsistent
layoutNoOutput layout formatseparate
transitionNoTransition style between stepssmooth
formatNoOutput formatindividual
previewNoAutomatically open generated images in default viewer

Implementation Reference

  • The primary handler function that implements the logic for generating a sequence of images telling a visual story. It iteratively creates tailored prompts for each step and generates images using the OpenRouter API.
    async generateStorySequence( request: ImageGenerationRequest, args?: StorySequenceArgs ): Promise<ImageGenerationResponse> { try { const outputPath = FileHandler.ensureOutputDirectory(); const generatedFiles: string[] = []; const steps = request.outputCount || 4; const type = args?.type || "story"; const style = args?.style || "consistent"; const transition = args?.transition || "smooth"; let firstError: string | null = null; logger.debug(`Generating ${steps}-step ${type} sequence`); for (let i = 0; i < steps; i++) { const stepNumber = i + 1; let stepPrompt = `${request.prompt}, step ${stepNumber} of ${steps}`; switch (type) { case "story": stepPrompt += `, narrative sequence, ${style} art style`; break; case "process": stepPrompt += `, procedural step, instructional illustration`; break; case "tutorial": stepPrompt += `, tutorial step, educational diagram`; break; case "timeline": stepPrompt += `, chronological progression, timeline visualization`; break; default: stepPrompt += `, ${type} sequence`; break; } if (i > 0) { stepPrompt += `, ${transition} transition from previous step`; } logger.debug(`Generating step ${stepNumber}: ${stepPrompt}`); try { const payload: Record<string, unknown> = { model: this.modelName, input: [ { role: "user", content: [ { type: "input_text", text: stepPrompt, }, ], }, ], }; if (request.seed !== undefined) { payload.seed = request.seed; } const response = await this.postJson<OpenRouterImageResponse>( this.generationPath, payload ); const imageBase64 = this.parseImageFromResponse(response); if (imageBase64) { const filename = FileHandler.generateFilename( `${type}step${stepNumber}${request.prompt}`, "png", 0 ); const fullPath = await FileHandler.saveImageFromBase64( imageBase64, outputPath, filename ); generatedFiles.push(fullPath); logger.debug(`Step ${stepNumber} saved to:`, fullPath); } else { logger.warn(`No image data returned for step ${stepNumber}`); } } catch (error: unknown) { const errorMessage = this.handleApiError(error); if (!firstError) { firstError = errorMessage; } logger.warn(`Error generating step ${stepNumber}:`, errorMessage); if (errorMessage.toLowerCase().includes("authentication failed")) { return { success: false, message: "Story generation failed", error: errorMessage, }; } } if (generatedFiles.length < stepNumber) { logger.warn( `Step ${stepNumber} failed to generate - no valid image data received` ); } } logger.debug( `Story generation completed. Generated ${generatedFiles.length} out of ${steps} requested images` ); if (generatedFiles.length === 0) { return { success: false, message: "Failed to generate any story sequence images", error: firstError || "No image data returned from OpenRouter. Try adjusting your prompt.", }; } await this.handlePreview(generatedFiles, request); const wasFullySuccessful = generatedFiles.length === steps; const successMessage = wasFullySuccessful ? `Successfully generated complete ${steps}-step ${type} sequence` : `Generated ${generatedFiles.length} out of ${steps} requested ${type} steps (${steps - generatedFiles.length} steps failed)`; return { success: true, message: successMessage, generatedFiles, }; } catch (error: unknown) { logger.error("Error in generateStorySequence:", error); return { success: false, message: `Failed to generate ${request.mode} sequence`, error: this.handleApiError(error), }; }
  • Defines the tool schema including name, description, and detailed input schema with properties like prompt, steps, type, style, etc., for validation in MCP tool calls.
    { name: "generate_story", description: "Generate a sequence of related images that tell a visual story or show a process", inputSchema: { type: "object", properties: { prompt: { type: "string", description: "Description of the story or process to visualize", }, steps: { type: "number", description: "Number of sequential images to generate (2-8)", minimum: 2, maximum: 8, default: 4, }, type: { type: "string", enum: ["story", "process", "tutorial", "timeline"], description: "Type of sequence to generate", default: "story", }, style: { type: "string", enum: ["consistent", "evolving"], description: "Visual consistency across frames", default: "consistent", }, layout: { type: "string", enum: ["separate", "grid", "comic"], description: "Output layout format", default: "separate", }, transition: { type: "string", enum: ["smooth", "dramatic", "fade"], description: "Transition style between steps", default: "smooth", }, format: { type: "string", enum: ["storyboard", "individual"], description: "Output format", default: "individual", }, preview: { type: "boolean", description: "Automatically open generated images in default viewer", default: false, }, }, required: ["prompt"], }, },
  • MCP server request handler case for 'generate_story' tool that prepares the ImageGenerationRequest from input args and delegates execution to the imageGenerator's generateStorySequence method.
    case "generate_story": { const storyRequest: ImageGenerationRequest = { prompt: args?.prompt as string, outputCount: (args?.steps as number) || 4, mode: "generate", variations: ["sequence-step"], preview: args?.preview as boolean, noPreview: (args?.noPreview as boolean) || (args?.["no-preview"] as boolean), }; response = await this.imageGenerator.generateStorySequence( storyRequest, args ); break;
  • The generate_story tool is registered by including its definition in the tools array returned by the listTools MCP handler.
    "Automatically open generated images in default viewer", default: false, }, }, required: ["prompt"], }, }, { name: "generate_story", description: "Generate a sequence of related images that tell a visual story or show a process", inputSchema: { type: "object", properties: { prompt: { type: "string", description: "Description of the story or process to visualize", }, steps: { type: "number", description: "Number of sequential images to generate (2-8)", minimum: 2, maximum: 8, default: 4, }, type: { type: "string", enum: ["story", "process", "tutorial", "timeline"], description: "Type of sequence to generate", default: "story", }, style: { type: "string", enum: ["consistent", "evolving"], description: "Visual consistency across frames", default: "consistent", }, layout: { type: "string", enum: ["separate", "grid", "comic"], description: "Output layout format", default: "separate", }, transition: { type: "string", enum: ["smooth", "dramatic", "fade"], description: "Transition style between steps", default: "smooth", }, format: { type: "string", enum: ["storyboard", "individual"], description: "Output format", default: "individual", }, preview: { type: "boolean", description: "Automatically open generated images in default viewer", default: false, }, }, required: ["prompt"], }, }, { name: "generate_diagram", description: "Generate technical diagrams, flowcharts, and architectural mockups", inputSchema: { type: "object", properties: { prompt: { type: "string", description: "Description of the diagram content and structure", }, type: { type: "string", enum: [ "flowchart", "architecture", "network", "database", "wireframe", "mindmap", "sequence", ], description: "Type of diagram to generate", default: "flowchart", }, style: { type: "string", enum: ["professional", "clean", "hand-drawn", "technical"], description: "Visual style of the diagram", default: "professional", }, layout: { type: "string", enum: ["horizontal", "vertical", "hierarchical", "circular"], description: "Layout orientation", default: "hierarchical", }, complexity: { type: "string", enum: ["simple", "detailed", "comprehensive"], description: "Level of detail in the diagram", default: "detailed", }, colors: { type: "string", enum: ["mono", "accent", "categorical"], description: "Color scheme", default: "accent", }, annotations: { type: "string", enum: ["minimal", "detailed"], description: "Label and annotation level", default: "detailed", }, preview: { type: "boolean", description: "Automatically open generated images in default viewer", default: false, }, }, required: ["prompt"], }, }, ]; return { tools,

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/Aeven-AI/mcp-nanobanana'

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