UNPKG

mcp-image-server

Version:

Servidor MCP para geração de imagens e ícones, integrado ao Vibecoding.

78 lines (77 loc) 3.32 kB
import sharp from 'sharp'; import fs from 'fs/promises'; import path from 'path'; import OpenAI from 'openai'; export class IconGenerationService { outputDir; openai; constructor() { this.outputDir = process.env.OUTPUT_DIR || './generated-assets'; this.openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY || '' }); this.ensureOutputDir(); } async ensureOutputDir() { try { await fs.mkdir(this.outputDir, { recursive: true }); } catch (error) { console.error('Erro ao criar diretório de saída:', error); } } async generateIcon(options) { const { prompt, sizes = [128], format = 'png', style, color, background } = options; const results = []; for (const size of sizes) { // Gera o ícone via OpenAI (DALL-E) const enhancedPrompt = this.enhancePrompt(prompt, style, color, background); const response = await this.openai.images.generate({ model: 'dall-e-3', prompt: enhancedPrompt, size: this.getValidSize(size), quality: 'standard', response_format: 'url' }); const imageUrl = response && Array.isArray(response.data) && response.data[0]?.url ? response.data[0].url : undefined; if (!imageUrl) throw new Error('Nenhuma URL de ícone retornada pela OpenAI'); const imageBuffer = await this.downloadImage(imageUrl); const filename = `icon_${prompt.replace(/\s+/g, '_').toLowerCase()}_${size}.${format}`; const filePath = path.join(this.outputDir, filename); let buffer; if (format === 'svg') { // OpenAI só retorna PNG/JPEG/WEBP, então converte para SVG (não recomendado, mas possível) // Aqui apenas salva como PNG buffer = imageBuffer; await fs.writeFile(filePath, buffer); results.push({ filePath: path.resolve(filePath), mimeType: 'image/png', size }); } else { buffer = await sharp(imageBuffer).resize(size, size).toFormat(format).toBuffer(); await fs.writeFile(filePath, buffer); results.push({ filePath: path.resolve(filePath), mimeType: `image/${format}`, size }); } } return results; } enhancePrompt(prompt, style, color, background) { let enhanced = prompt; if (style) enhanced += `, ${style} style`; if (color) enhanced += `, primary color ${color}`; if (background && background !== 'transparent') enhanced += `, ${background} background`; else if (background === 'transparent') enhanced += ', transparent background, isolated subject'; enhanced += ', icon, minimal, flat, centered, high quality, white background if not transparent'; return enhanced; } getValidSize(size) { // OpenAI só aceita tamanhos fixos, então sempre retorna 1024x1024 para ícones return '1024x1024'; } async downloadImage(url) { const response = await fetch(url); return Buffer.from(await response.arrayBuffer()); } }