UNPKG

@devinrcai/mcp-image-generator

Version:

MCP server for generating images using ModelScope API - works with Claude Desktop and other MCP clients

203 lines (200 loc) 7.66 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import axios from "axios"; import fs from "fs/promises"; import path from "path"; import { fileURLToPath } from "url"; import { dirname } from "path"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Create an MCP server for image generation const server = new McpServer({ name: "image-generator-server", version: "1.0.0", description: "MCP server for generating images using ModelScope API" }); // Store API key in memory (provided by the client) let apiKey = null; // Register tool to set API key server.registerTool("set-api-key", { title: "Set ModelScope API Key", description: "Set the ModelScope API key for image generation. Keep this key secure.", inputSchema: { key: z.string().describe("Your ModelScope API key") } }, async ({ key }) => { apiKey = key; return { content: [{ type: "text", text: "API key has been set successfully. You can now use the image generation tool." }] }; }); // Register image generation tool server.registerTool("generate-image", { title: "Generate Image", description: "Generate an image based on text description using ModelScope FLUX model", inputSchema: { prompt: z.string().describe("Text description of the image to generate"), filename: z.string().optional().describe("Optional filename for the generated image (without extension)") } }, async ({ prompt, filename }) => { if (!apiKey) { return { content: [{ type: "text", text: "Error: API key not set. Please use the 'set-api-key' tool first to provide your ModelScope API key." }], isError: true }; } try { // Call ModelScope API const response = await axios.post('https://api-inference.modelscope.cn/v1/images/generations', { model: 'MusePublic/489_ckpt_FLUX_1', prompt: prompt }, { headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' } }); const imageUrl = response.data.images[0].url; // Download the image const imageResponse = await axios.get(imageUrl, { responseType: 'arraybuffer' }); // Create images directory if it doesn't exist const imagesDir = path.join(process.cwd(), 'generated-images'); await fs.mkdir(imagesDir, { recursive: true }); // Save the image const imageFilename = filename ? `${filename}.jpg` : `image-${Date.now()}.jpg`; const imagePath = path.join(imagesDir, imageFilename); await fs.writeFile(imagePath, imageResponse.data); return { content: [ { type: "text", text: `Image generated successfully!\nPrompt: "${prompt}"\nSaved to: ${imagePath}\nImage URL: ${imageUrl}` }, { type: "resource_link", uri: `file://${imagePath}`, name: imageFilename, mimeType: "image/jpeg", description: `Generated image: ${prompt}` } ] }; } catch (error) { return { content: [{ type: "text", text: `Error generating image: ${error.response?.data?.message || error.message}` }], isError: true }; } }); // Register tool to generate placeholder image HTML server.registerTool("generate-placeholder-html", { title: "Generate Placeholder HTML", description: "Generate HTML img tag with placeholder that can be replaced with generated image", inputSchema: { altText: z.string().describe("Alternative text for the image"), width: z.number().optional().describe("Image width in pixels"), height: z.number().optional().describe("Image height in pixels"), className: z.string().optional().describe("CSS class name for styling") } }, async ({ altText, width, height, className }) => { const imgTag = `<img src="placeholder.jpg" alt="${altText}" ${width ? `width="${width}"` : ''} ${height ? `height="${height}"` : ''} ${className ? `class="${className}"` : ''} data-mcp-placeholder="true" data-mcp-prompt="${altText}" />`; return { content: [{ type: "text", text: `HTML placeholder generated:\n\n${imgTag}\n\nYou can use the 'generate-image' tool with the prompt "${altText}" to create the actual image.` }] }; }); // Register resource to list generated images server.registerResource("generated-images", "images://generated", { title: "Generated Images", description: "List all generated images", mimeType: "application/json" }, async (uri) => { try { const imagesDir = path.join(process.cwd(), 'generated-images'); const files = await fs.readdir(imagesDir); const imageFiles = files.filter(file => file.endsWith('.jpg') || file.endsWith('.png')); const imageList = imageFiles.map(file => ({ filename: file, path: path.join(imagesDir, file), uri: `file://${path.join(imagesDir, file)}` })); return { contents: [{ uri: uri.href, text: JSON.stringify(imageList, null, 2), mimeType: "application/json" }] }; } catch (error) { return { contents: [{ uri: uri.href, text: JSON.stringify({ error: "No images directory found", images: [] }), mimeType: "application/json" }] }; } }); // Register prompt for image generation workflow server.registerPrompt("image-generation-workflow", { title: "Image Generation Workflow", description: "Guide through the image generation process", argsSchema: { description: z.string().describe("What kind of image do you need?") } }, ({ description }) => ({ messages: [{ role: "assistant", content: { type: "text", text: `I'll help you generate an image for your website. Based on your description: "${description}" Here's what I'll do: 1. First, make sure you've set your ModelScope API key using the 'set-api-key' tool 2. Generate the image using the 'generate-image' tool 3. Provide you with the file path and HTML code to use it Would you like me to proceed with generating this image?` } }] })); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); // Log to stderr to avoid interfering with stdio communication console.error("MCP Image Generator Server is running..."); console.error("Available tools:"); console.error("- set-api-key: Set your ModelScope API key"); console.error("- generate-image: Generate images from text descriptions"); console.error("- generate-placeholder-html: Create HTML placeholder for images"); console.error("- Resource: images://generated - List all generated images"); } main().catch((error) => { console.error("Server error:", error); process.exit(1); }); //# sourceMappingURL=index.js.map