Skip to main content
Glama

generate-image

Generate images from Orshot templates by applying custom modifications to library or studio templates with automatic URL mapping and format options.

Instructions

Generate an image from an Orshot template (automatically detects library vs studio template). For studio templates, automatically maps URLs to appropriate image fields and supports template names.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
apiKeyNoOrshot API key for authentication (optional if set in environment)
templateIdYesThe ID or name of the template to use (will auto-detect if it's library or studio). Numeric IDs are likely studio templates. Studio templates can also be referenced by name.
modificationsNoObject containing modifications/data to apply to the template (works for both library and studio templates). URLs will be auto-mapped to image fields for studio templates.
formatNoOutput format for the generated imagepng
responseTypeNoResponse type: base64 data, download URL, or binary dataurl
webhookNoOptional webhook URL to receive notifications (studio templates only)

Implementation Reference

  • Primary handler function for 'generate-image' tool. Auto-detects library/studio template, auto-maps modifications for studio, calls Orshot API, handles responses with links or raw data.
    async (args) => { const { apiKey, templateId, modifications, format, responseType, webhook } = args; const actualApiKey = apiKey || DEFAULT_API_KEY; if (!actualApiKey) { return { content: [ { type: "text", text: "No API key provided. Please provide an API key parameter or set ORSHOT_API_KEY environment variable.", }, ], }; } // Determine template type const templateType = await getTemplateType(templateId, actualApiKey); if (!templateType) { return { content: [ { type: "text", text: `Template "${templateId}" not found in either library or studio templates. Please check the template ID.`, }, ], }; } if (templateType === 'library') { // Use library template endpoint const requestBody = { templateId: templateId, modifications, response: { type: responseType, format: format }, source: "orshot-mcp-server" }; const response = await makeOrShotRequest<OrShotLibraryResponse>( `${ORSHOT_API_BASE}/v1/generate/images`, { method: "POST", headers: { Authorization: `Bearer ${actualApiKey}`, }, body: JSON.stringify(requestBody), } ); if (!response) { return { content: [ { type: "text", text: "Failed to generate image from library template. Please check your API key and template ID.", }, ], }; } const { data } = response; // Create raw response display (truncate data for readability) const responseForDisplay = { ...response, data: response.data ? (response.data.length > 100 ? `${response.data.substring(0, 100)}... (truncated, total length: ${response.data.length})` : response.data) : response.data }; // Handle different response types for library templates if (responseType === "url" && response.url) { return { content: [ { type: "text", text: `Image generated successfully from library template! šŸ–¼ļø **[View Generated Image](${response.url})** Template Type: Library Task ID: ${response.task_id || 'Not available'} Status: ${response.status || 'Unknown'}`, }, ], }; } else if (responseType === "base64" && response.data && typeof response.data === 'string' && response.data.startsWith('data:image/')) { return { content: [ { type: "text", text: `Image generated successfully from library template! **Raw API Response:** \`\`\`json ${JSON.stringify(responseForDisplay, null, 2)} \`\`\``, }, ], }; } else if (responseType === "binary") { return { content: [ { type: "text", text: `Image generated successfully from library template! **Raw API Response:** \`\`\`json ${JSON.stringify(responseForDisplay, null, 2)} \`\`\``, }, ], }; } // Fallback to text response return { content: [ { type: "text", text: `Image generated successfully from library template! **Raw API Response:** \`\`\`json ${JSON.stringify(responseForDisplay, null, 2)} \`\`\``, }, ], }; } else { // Use studio template endpoint // Resolve template ID from name if needed const resolvedTemplateId = await resolveStudioTemplateId(templateId, actualApiKey); if (!resolvedTemplateId) { return { content: [ { type: "text", text: `āŒ Studio template "${templateId}" not found. Please check the template ID or name.`, }, ], }; } // Auto-map modifications based on template structure const mappedModifications = await autoMapModifications(resolvedTemplateId, modifications, actualApiKey); const requestBody: any = { templateId: resolvedTemplateId, modifications: mappedModifications, // Use auto-mapped modifications response: { type: responseType, format: format }, source: "orshot-mcp-server" }; if (webhook) { requestBody.webhook = webhook; } const response = await makeOrShotRequest<OrShotStudioResponse>( `${ORSHOT_API_BASE}/v1/studio/render`, { method: "POST", headers: { Authorization: `Bearer ${actualApiKey}`, }, body: JSON.stringify(requestBody), } ); if (!response) { return { content: [ { type: "text", text: "Failed to generate image from studio template. Please check your API key and template ID.", }, ], }; } const { data: responseData } = response; // Create raw response display (truncate data for readability) const responseForDisplay = { ...response, data: response.data ? (response.data.length > 100 ? `${response.data.substring(0, 100)}... (truncated, total length: ${response.data.length})` : response.data) : response.data }; // Handle different response types for studio templates if (responseType === "url" && response.url) { return { content: [ { type: "text", text: `Image generated successfully from studio template! šŸ–¼ļø **[View Generated Image](${response.url})** Template Type: Studio Task ID: ${response.task_id || 'Not available'} Status: ${response.status || 'Unknown'} ${webhook ? `Webhook notifications will be sent to: ${webhook}` : ""}`, }, ], }; } else if (responseType === "base64" && response.data && typeof response.data === 'string' && response.data.startsWith('data:image/')) { return { content: [ { type: "text", text: `Image generated successfully from studio template! **Raw API Response:** \`\`\`json ${JSON.stringify(responseForDisplay, null, 2)} \`\`\``, }, ], }; } else if (responseType === "binary") { return { content: [ { type: "text", text: `Image generated successfully from studio template! **Raw API Response:** \`\`\`json ${JSON.stringify(responseForDisplay, null, 2)} \`\`\``, }, ], }; } // Fallback to text response return { content: [ { type: "text", text: `Image generated successfully from studio template! **Raw API Response:** \`\`\`json ${JSON.stringify(responseForDisplay, null, 2)} \`\`\``, }, ], }; } } );
  • Zod input schema defining parameters for the generate-image tool including optional API key, template ID/name, modifications object, output format, response type, and optional webhook.
    { apiKey: z.string().optional().describe("Orshot API key for authentication (optional if set in environment)"), templateId: z.string().describe("The ID or name of the template to use (will auto-detect if it's library or studio). Numeric IDs are likely studio templates. Studio templates can also be referenced by name."), modifications: z.record(z.any()).default({}).describe("Object containing modifications/data to apply to the template (works for both library and studio templates). URLs will be auto-mapped to image fields for studio templates."), format: z.enum(["png", "jpg", "pdf"]).default("png").describe("Output format for the generated image"), responseType: z.enum(["base64", "url", "binary"]).default("url").describe("Response type: base64 data, download URL, or binary data"), webhook: z.string().url().optional().describe("Optional webhook URL to receive notifications (studio templates only)"), },
  • src/index.ts:800-802 (registration)
    Registration of the 'generate-image' tool on the MCP server using server.tool() with name, description, schema, and inline handler function.
    server.tool( "generate-image", "Generate an image from an Orshot template (automatically detects library vs studio template). For studio templates, automatically maps URLs to appropriate image fields and supports template names.",
  • Helper to auto-detect template type (library or studio) by API queries, crucial for generate-image routing.
    // Helper function to determine template type (library vs studio) async function getTemplateType(templateId: string, apiKey: string): Promise<'library' | 'studio' | null> { try { // If it's a numeric ID, it's likely a studio template - check studio first if (isLikelyStudioTemplate(templateId)) { // Check studio templates first for numeric IDs const studioResponse = await fetch(`${ORSHOT_API_BASE}/v1/studio/templates`, { headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json", }, }); if (studioResponse.ok) { const studioTemplates = await studioResponse.json(); const templatesArray = Array.isArray(studioTemplates) ? studioTemplates : []; // Check if templateId exists in studio templates (supports both numeric ID and name matching) const isStudioTemplate = templatesArray.some((template: any) => template.id === templateId || template.id === parseInt(templateId) || template.name?.toLowerCase() === templateId.toLowerCase() ); if (isStudioTemplate) { return 'studio'; } } } // First check if it's a library template const libraryResponse = await fetch(`${ORSHOT_API_BASE}/v1/templates`, { headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json", }, }); if (libraryResponse.ok) { const libraryData = await libraryResponse.json(); const libraryTemplates = Array.isArray(libraryData) ? libraryData : []; // Check if templateId exists in library templates const isLibraryTemplate = libraryTemplates.some((template: any) => template.id === templateId || template.template_id === templateId ); if (isLibraryTemplate) { return 'library'; } } // If not found in library and not numeric, check studio templates (including name matching) if (!isLikelyStudioTemplate(templateId)) { const studioResponse = await fetch(`${ORSHOT_API_BASE}/v1/studio/templates`, { headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json", }, }); if (studioResponse.ok) { const studioTemplates = await studioResponse.json(); const templatesArray = Array.isArray(studioTemplates) ? studioTemplates : []; // Check if templateId exists in studio templates (supports name matching for non-numeric IDs) const isStudioTemplate = templatesArray.some((template: any) => template.id === templateId || template.name?.toLowerCase() === templateId.toLowerCase() ); if (isStudioTemplate) { return 'studio'; } } } return null; // Template not found in either } catch (error) { console.error("Error determining template type:", error); return null; } }
  • Core HTTP client helper for all Orshot API calls, used by generate-image handler with retries and logging.
    async function makeOrShotRequest<T>( url: string, options: RequestInit = {}, retries: number = config.api.retries ): Promise<T | null> { let lastError: Error | null = null; logger.time(`API Request: ${url}`); for (let attempt = 1; attempt <= retries; attempt++) { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), config.api.timeout); const response = await fetch(url, { ...options, headers: { "Content-Type": "application/json", "User-Agent": `${config.server.name}/${config.server.version}`, ...options.headers, }, signal: controller.signal, }); clearTimeout(timeoutId); if (!response.ok) { const errorText = await response.text(); let errorMessage = `HTTP ${response.status} ${response.statusText}`; try { const errorData = JSON.parse(errorText); errorMessage = errorData.message || errorData.error || errorMessage; } catch { // Use the raw error text if JSON parsing fails errorMessage = errorText || errorMessage; } logger.apiRequest(options.method || 'GET', url, response.status); throw new Error(errorMessage); } const result = await response.json(); logger.apiRequest(options.method || 'GET', url, response.status); logger.timeEnd(`API Request: ${url}`); return result as T; } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)); if (error instanceof Error && error.name === 'AbortError') { logger.error(`Request timeout on attempt ${attempt}/${retries}`, { url, timeout: config.api.timeout }); } else { logger.error(`Request failed on attempt ${attempt}/${retries}`, { url, error: lastError.message }); } // Don't retry for certain error types if (error instanceof Error && (error.message.includes('401') || error.message.includes('403') || error.message.includes('404'))) { break; } if (attempt < retries) { // Exponential backoff with configurable delay const delay = Math.pow(2, attempt - 1) * config.api.retryDelay; await new Promise(resolve => setTimeout(resolve, delay)); logger.debug(`Retrying request after ${delay}ms delay`, { url, attempt: attempt + 1, retries }); } } } logger.error("All retry attempts failed", { url, error: lastError?.message }); logger.timeEnd(`API Request: ${url}`); return null; }

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/rishimohan/orshot-mcp-server'

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