mcp-image-server
Version:
Servidor MCP para geração de imagens e ícones, integrado ao Vibecoding.
78 lines (77 loc) • 3.32 kB
JavaScript
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());
}
}