@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
JavaScript
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