UNPKG

@aiondadotcom/mcp-openai-image

Version:

MCP server for OpenAI image generation with STDIO transport

110 lines (109 loc) 3.96 kB
import { promises as fs } from 'fs'; import { join } from 'path'; import { homedir } from 'os'; export class FileManager { desktopPath; constructor() { this.desktopPath = join(homedir(), 'Desktop'); } async saveImageToDesktop(base64Data, format, metadata) { try { // Validate input if (!base64Data || base64Data.trim().length === 0) { throw new Error('Invalid base64 data provided'); } // Generate unique filename const fileName = await this.generateUniqueFilename(format); const filePath = join(this.desktopPath, fileName); // Convert base64 to buffer and save const imageBuffer = Buffer.from(base64Data, 'base64'); // Check if image is too large (> 50MB) if (imageBuffer.length > 50 * 1024 * 1024) { // Large image warning - but continue processing } await fs.writeFile(filePath, imageBuffer); // Image saved successfully - metadata is returned in response, no need to save as file return filePath; } catch (error) { throw new Error(`Failed to save image to desktop: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async generateUniqueFilename(format) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const randomId = Math.random().toString(36).substring(2, 8); const extension = format === 'jpeg' ? 'jpg' : format; return `openai-image-${timestamp}-${randomId}.${extension}`; } getDesktopPath() { return this.desktopPath; } async ensureDesktopExists() { try { await fs.access(this.desktopPath); } catch (error) { throw new Error(`Desktop directory not accessible: ${this.desktopPath}`); } } async checkDiskSpace() { try { // Basic check - try to write a small test file const testFile = join(this.desktopPath, '.mcp-test'); await fs.writeFile(testFile, 'test'); await fs.unlink(testFile); return true; } catch (error) { return false; } } async getImageHistory() { try { const files = await fs.readdir(this.desktopPath); return files .filter(file => file.startsWith('openai-image-') && (file.endsWith('.png') || file.endsWith('.jpg') || file.endsWith('.jpeg') || file.endsWith('.webp'))) .map(file => join(this.desktopPath, file)) .sort((a, b) => b.localeCompare(a)); // Sort by name (newer first due to timestamp) } catch (error) { // Failed to get image history - return empty array return []; } } async cleanupOldImages(keepCount = 50) { try { const history = await this.getImageHistory(); if (history.length <= keepCount) return; const toDelete = history.slice(keepCount); for (const imagePath of toDelete) { try { await fs.unlink(imagePath); } catch (error) { // Failed to delete old image - continue cleanup } } } catch (error) { // Failed to cleanup old images - not critical } } validateFormat(format) { const supportedFormats = ['png', 'jpeg', 'webp']; return supportedFormats.includes(format.toLowerCase()); } getFileExtension(format) { switch (format.toLowerCase()) { case 'jpeg': return 'jpg'; case 'png': return 'png'; case 'webp': return 'webp'; default: return 'png'; } } }