siliconflow-image-mcp 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +4 -0
- package/dist/index.js.map +2 -2
- package/package.json +2 -3
- package/src/index.ts +6 -0
- package/bin/siliconflow-image-mcp +0 -5
- package/bin/siliconflow-image-mcp.cmd +0 -5
- package/dist/package.json +0 -33
package/dist/index.js
CHANGED
|
@@ -498,6 +498,10 @@ if (process.argv.includes("--build")) {
|
|
|
498
498
|
console.log("\u{1F4DD} Note: This project uses tsx for runtime execution.");
|
|
499
499
|
process.exit(0);
|
|
500
500
|
}
|
|
501
|
+
if (process.argv.includes("--version") || process.argv.includes("-v")) {
|
|
502
|
+
console.log("1.0.8");
|
|
503
|
+
process.exit(0);
|
|
504
|
+
}
|
|
501
505
|
var SILICONFLOW_API_KEY = process.env.SILICONFLOW_API_KEY;
|
|
502
506
|
var MOCK_MODE = process.env.SILICONFLOW_MOCK === "true";
|
|
503
507
|
if (!SILICONFLOW_API_KEY && !MOCK_MODE) {
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/services/siliconflow.ts", "../src/types/index.ts", "../src/utils/file.ts", "../src/tools/generate.ts", "../src/tools/edit.ts", "../src/tools/list-models.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n/**\n * SiliconFlow Image MCP Server\n *\n * A Model Context Protocol server for image generation and editing using SiliconFlow\n * Optimized for China users\n */\n\n// Handle build flag for compilation\nif (process.argv.includes('--build')) {\n console.log('\u2705 Project structure is ready. Use \"npm start\" to run the server.');\n console.log('\uD83D\uDCDD Note: This project uses tsx for runtime execution.');\n process.exit(0);\n}\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { SiliconFlowService } from \"./services/siliconflow.js\";\nimport { createGenerateImageTool } from \"./tools/generate.js\";\nimport { createEditImageTool } from \"./tools/edit.js\";\nimport { createListModelsTool } from \"./tools/list-models.js\";\n\n// Environment variable check\nconst SILICONFLOW_API_KEY = process.env.SILICONFLOW_API_KEY;\nconst MOCK_MODE = process.env.SILICONFLOW_MOCK === \"true\";\n\nif (!SILICONFLOW_API_KEY && !MOCK_MODE) {\n console.error(\"\u274C Error: SILICONFLOW_API_KEY environment variable is required\");\n console.error(\"\\nTo use this MCP server:\");\n console.error(\"1. Get your API key from https://siliconflow.cn\");\n console.error(\"2. Set it as an environment variable:\");\n console.error(\" export SILICONFLOW_API_KEY=your-api-key-here\");\n console.error(\"\\nFor Claude Desktop, add to your config.json:\");\n console.error(`{\n \"mcpServers\": {\n \"siliconflow-image-mcp\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"siliconflow-image-mcp\"],\n \"env\": {\n \"SILICONFLOW_API_KEY\": \"your-api-key-here\"\n }\n }\n }\n}`);\n console.error(\"\\nOptional configurations:\");\n console.error(\" export SILICONFLOW_MOCK=true # Use mock mode for testing\");\n console.error(\" export SILICONFLOW_IMAGE_DIR=/path # Custom directory for saved images\");\n process.exit(1);\n}\n\n// Initialize services and server\nasync function main() {\n console.error(\"\uD83D\uDE80 Starting SiliconFlow Image MCP Server...\");\n\n try {\n // Initialize SiliconFlow service\n let siliconFlowService;\n if (MOCK_MODE) {\n console.error(\"\u26A0\uFE0F Running in MOCK mode - API calls will be simulated\");\n // Create a mock service that returns fake data\n siliconFlowService = {\n generateImage: async () => [{ data: \"mock-base64-data\", mimeType: \"image/png\" }],\n editImage: async () => ({ data: \"mock-base64-data\", mimeType: \"image/png\" }),\n listImageModels: async () => [\n { id: \"black-forest-labs/FLUX.1-dev\", name: \"FLUX.1-dev\", description: \"Mock model\", output_modalities: [\"image\"] }\n ],\n testConnection: async () => true\n };\n } else {\n siliconFlowService = new SiliconFlowService(SILICONFLOW_API_KEY);\n\n // Test connection\n const isConnected = await siliconFlowService.testConnection();\n if (!isConnected) {\n console.error(\"\u274C Failed to connect to SiliconFlow. Please check your API key.\");\n process.exit(1);\n }\n console.error(\"\u2705 Connected to SiliconFlow successfully\");\n }\n\n // Create MCP server\n const server = new McpServer({\n name: \"siliconflow-image-mcp\",\n version: \"1.0.0\",\n capabilities: {\n tools: {\n listChanged: true,\n },\n },\n });\n\n // Register tools\n const generateTool = createGenerateImageTool(siliconFlowService);\n const editTool = createEditImageTool(siliconFlowService);\n const listModelsTool = createListModelsTool(siliconFlowService);\n\n server.registerTool(\n generateTool.name,\n {\n description: generateTool.description,\n inputSchema: generateTool.inputSchema,\n },\n generateTool.handler\n );\n\n server.registerTool(\n editTool.name,\n {\n description: editTool.description,\n inputSchema: editTool.inputSchema,\n },\n editTool.handler\n );\n\n server.registerTool(\n listModelsTool.name,\n {\n description: listModelsTool.description,\n inputSchema: listModelsTool.inputSchema,\n },\n listModelsTool.handler\n );\n\n // Connect to stdio transport\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n console.error(\"\u2705 SiliconFlow Image MCP Server is running\");\n console.error(\"\uD83D\uDCCB Available tools: generate_image, edit_image, list_image_models\");\n console.error(\"\uD83D\uDCDD Waiting for requests...\");\n\n // Handle graceful shutdown\n process.on(\"SIGINT\", async () => {\n console.error(\"\\n\uD83D\uDED1 Shutting down gracefully...\");\n await server.close();\n process.exit(0);\n });\n\n } catch (error) {\n console.error(\"\u274C Failed to start server:\", error instanceof Error ? error.message : \"Unknown error\");\n process.exit(1);\n }\n}\n\n// Run the server\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});", "/**\n * SiliconFlow service wrapper for image generation and editing\n * Optimized for China users\n */\n\nimport { ImageResult, ModelInfo } from \"../types/index.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\nexport class SiliconFlowService {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(apiKey: string) {\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"SiliconFlow API key is required\");\n }\n this.apiKey = apiKey;\n this.baseUrl = \"https://api.siliconflow.cn/v1\";\n }\n\n /**\n * Make API call to SiliconFlow\n */\n private async makeApiCall<T = any>(endpoint: string, body: any): Promise<T> {\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error (${response.status}): ${errorText}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Make GET API call to SiliconFlow\n */\n private async makeGetCall<T = any>(endpoint: string, params?: Record<string, any>): Promise<T> {\n const url = new URL(`${this.baseUrl}${endpoint}`);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n });\n }\n\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error (${response.status}): ${errorText}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Generate images using SiliconFlow's image generation models\n */\n async generateImage(\n prompt: string,\n model: string = \"black-forest-labs/FLUX.1-dev\",\n aspectRatio?: string,\n imageSize?: string,\n count: number = 1,\n negativePrompt?: string,\n seed?: number,\n ): Promise<ImageResult[]> {\n try {\n // Build request body\n const requestBody: any = {\n model,\n prompt,\n batch_size: Math.min(count, 4), // SiliconFlow max is 4\n };\n\n // Handle image size mapping from aspect ratio\n if (aspectRatio || imageSize) {\n requestBody.image_size = this.mapAspectRatioToSize(aspectRatio, imageSize, model);\n }\n\n if (negativePrompt) {\n requestBody.negative_prompt = negativePrompt;\n }\n\n if (seed !== undefined) {\n requestBody.seed = seed;\n }\n\n // Use SiliconFlow's image generation endpoint\n const result = await this.makeApiCall(\"/images/generations\", requestBody);\n\n if (!result.images || result.images.length === 0) {\n throw new Error(\"No images were generated\");\n }\n\n // Download images and convert to base64\n const images: ImageResult[] = [];\n for (const img of result.images) {\n const imageUrl = img.url;\n const imageResponse = await fetch(imageUrl);\n if (!imageResponse.ok) {\n throw new Error(`Failed to download image: ${imageResponse.status}`);\n }\n\n const imageBuffer = await imageResponse.arrayBuffer();\n const base64Data = Buffer.from(imageBuffer).toString(\"base64\");\n\n // Determine mime type from URL or default to PNG\n const mimeType = imageUrl.includes(\".png\")\n ? \"image/png\"\n : imageUrl.includes(\".jpg\") || imageUrl.includes(\".jpeg\")\n ? \"image/jpeg\"\n : \"image/png\";\n\n images.push({\n data: base64Data,\n mimeType,\n });\n }\n\n return images;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Image generation failed: ${error.message}`);\n }\n throw new Error(\"Image generation failed with unknown error\");\n }\n }\n\n /**\n * Edit an existing image using SiliconFlow\n */\n async editImage(\n image: string,\n prompt: string,\n model: string = \"Qwen/Qwen-Image-Edit-2509\",\n ): Promise<ImageResult> {\n try {\n // Determine if image is base64, URL, or local file path\n let imageContent: string;\n\n if (image.startsWith(\"data:image/\")) {\n // Already a data URL\n imageContent = image;\n } else if (image.startsWith(\"http://\") || image.startsWith(\"https://\")) {\n // URL - SiliconFlow accepts URLs directly\n imageContent = image;\n } else if (fs.existsSync(image) && fs.statSync(image).isFile()) {\n // Local file path - read and convert to base64 data URL\n const imageBuffer = fs.readFileSync(image);\n const base64Data = imageBuffer.toString(\"base64\");\n\n // Determine mime type from file extension\n const ext = path.extname(image).toLowerCase();\n const mimeType =\n ext === \".png\"\n ? \"image/png\"\n : ext === \".jpg\" || ext === \".jpeg\"\n ? \"image/jpeg\"\n : ext === \".webp\"\n ? \"image/webp\"\n : \"image/png\";\n\n imageContent = `data:${mimeType};base64,${base64Data}`;\n } else {\n // Assume raw base64 string, convert to data URL\n imageContent = `data:image/png;base64,${image}`;\n }\n\n // Build request body for image editing\n const requestBody: any = {\n model,\n prompt,\n image: imageContent,\n };\n\n const result = await this.makeApiCall(\"/images/generations\", requestBody);\n\n if (!result.images || result.images.length === 0) {\n throw new Error(\"No edited image was returned\");\n }\n\n // Download the edited image and convert to base64\n const img = result.images[0];\n const imageUrl = img.url;\n\n const imageResponse = await fetch(imageUrl);\n if (!imageResponse.ok) {\n throw new Error(`Failed to download edited image: ${imageResponse.status}`);\n }\n\n const imageBuffer = await imageResponse.arrayBuffer();\n const base64Data = Buffer.from(imageBuffer).toString(\"base64\");\n\n const mimeType = imageUrl.includes(\".png\")\n ? \"image/png\"\n : imageUrl.includes(\".jpg\") || imageUrl.includes(\".jpeg\")\n ? \"image/jpeg\"\n : \"image/png\";\n\n return {\n data: base64Data,\n mimeType,\n };\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Image editing failed: ${error.message}`);\n }\n throw new Error(\"Image editing failed with unknown error\");\n }\n }\n\n /**\n * List all available image generation models\n */\n async listImageModels(): Promise<ModelInfo[]> {\n try {\n // Get all models, then filter for image generation models\n const result = await this.makeGetCall(\"/models\", { type: \"image\" });\n\n if (!result.data || result.data.length === 0) {\n return [];\n }\n\n // Filter for text-to-image and image-to-image models\n const imageModels = result.data\n .filter((model: any) => {\n // SiliconFlow doesn't always provide detailed modality info in the basic list\n // We'll include models that are commonly known for image generation\n const modelId = model.id.toLowerCase();\n return (\n modelId.includes(\"flux\") ||\n modelId.includes(\"sd\") ||\n modelId.includes(\"stable-diffusion\") ||\n modelId.includes(\"qwen-image\") ||\n modelId.includes(\"kolors\") ||\n modelId.includes(\"dall\") ||\n modelId.includes(\"painting\")\n );\n })\n .map((model: any) => ({\n id: model.id,\n name: model.id,\n description: `Image generation model: ${model.id}`,\n output_modalities: [\"image\"],\n }));\n\n return imageModels;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to list models: ${error.message}`);\n }\n throw new Error(\"Failed to list models with unknown error\");\n }\n }\n\n /**\n * Test the API key validity\n */\n async testConnection(): Promise<boolean> {\n try {\n await this.makeGetCall(\"/models\");\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Map aspect ratio and image size to SiliconFlow's image_size format\n */\n private mapAspectRatioToSize(aspectRatio?: string, imageSize?: string, model?: string): string {\n // SiliconFlow uses \"widthxheight\" format\n // Based on their documentation, we'll map common aspect ratios\n\n // For Qwen models\n if (model && model.includes(\"qwen\")) {\n const qwenSizes: { [key: string]: string } = {\n \"1:1\": \"1328x1328\",\n \"16:9\": \"1664x928\",\n \"9:16\": \"928x1664\",\n \"4:3\": \"1472x1140\",\n \"3:4\": \"1140x1472\",\n \"3:2\": \"1584x1056\",\n \"2:3\": \"1056x1584\",\n };\n if (aspectRatio && qwenSizes[aspectRatio]) {\n return qwenSizes[aspectRatio];\n }\n }\n\n // For Kolors models\n const kolorsSizes: { [key: string]: string } = {\n \"1:1\": \"1024x1024\",\n \"3:4\": \"960x1280\",\n \"4:3\": \"1280x960\",\n \"1:2\": \"720x1440\",\n \"9:16\": \"720x1280\",\n \"16:9\": \"1280x720\",\n };\n\n if (aspectRatio && kolorsSizes[aspectRatio]) {\n return kolorsSizes[aspectRatio];\n }\n\n // Default sizes\n if (imageSize === \"4K\") return \"2048x2048\";\n if (imageSize === \"2K\") return \"1536x1536\";\n\n // Default to 1024x1024\n return \"1024x1024\";\n }\n}\n", "/**\n * Type definitions for SiliconFlow Image MCP\n */\n\nimport { z } from \"zod\";\n\n// Image generation input schema\nexport const GenerateImageInputSchema = z.object({\n prompt: z\n .string()\n .min(1, \"Prompt is required\")\n .max(2000, \"Prompt must be 2000 characters or less\")\n .describe(\"Detailed description of the image to generate\"),\n\n model: z\n .string()\n .optional()\n .describe(\"Model to use for generation (defaults to black-forest-labs/FLUX.1-dev)\"),\n\n aspectRatio: z\n .enum([\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"4:5\", \"5:4\", \"9:16\", \"16:9\", \"21:9\"])\n .optional()\n .describe(\"Aspect ratio for generated images\"),\n\n imageSize: z.enum([\"1K\", \"2K\", \"4K\"]).optional().describe(\"Image size (higher resolution)\"),\n\n count: z\n .number()\n .int()\n .min(1)\n .max(4)\n .optional()\n .default(1)\n .describe(\"Number of images to generate (1-4)\"),\n\n negativePrompt: z.string().optional().describe(\"Negative prompt - what to avoid in the image\"),\n\n seed: z\n .number()\n .int()\n .min(0)\n .max(9999999999)\n .optional()\n .describe(\"Seed for reproducible results\"),\n});\n\nexport type GenerateImageInput = z.infer<typeof GenerateImageInputSchema>;\n\n// Image editing input schema\nexport const EditImageInputSchema = z.object({\n image: z\n .string()\n .min(1, \"Image data is required\")\n .describe(\"Base64 encoded image data, image URL, or local file path to edit\"),\n\n prompt: z\n .string()\n .min(1, \"Edit prompt is required\")\n .max(2000, \"Edit prompt must be 2000 characters or less\")\n .describe(\"Instructions for editing the image\"),\n\n model: z\n .string()\n .optional()\n .describe(\"Model to use for editing (defaults to Qwen/Qwen-Image-Edit-2509)\"),\n});\n\nexport type EditImageInput = z.infer<typeof EditImageInputSchema>;\n\n// List models input schema (empty)\nexport const ListModelsInputSchema = z.object({});\n\nexport type ListModelsInput = z.infer<typeof ListModelsInputSchema>;\n\n// Image result type\nexport interface ImageResult {\n data: string; // Base64 encoded image data\n mimeType: string; // e.g., \"image/png\"\n size?: number; // File size in bytes\n width?: number; // Image width in pixels\n height?: number; // Image height in pixels\n}\n\n// Model information type\nexport interface ModelInfo {\n id: string;\n name: string;\n description?: string;\n output_modalities?: string[];\n pricing?: {\n prompt?: number;\n completion?: number;\n image?: number;\n };\n context_length?: number;\n}\n\n// Tool response type\nexport interface ToolResponse {\n content: Array<{\n type: \"text\" | \"image\" | \"resource\";\n text?: string;\n data?: string;\n mimeType?: string;\n uri?: string;\n name?: string;\n }>;\n isError?: boolean;\n}\n", "/**\n * File utility functions for saving images\n */\n\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\n\n/**\n * Get the base directory for storing images\n * Uses SILICONFLOW_IMAGE_DIR env var if set, otherwise defaults to system temp dir\n */\nfunction getImageBaseDir(): string {\n const customDir = process.env.SILICONFLOW_IMAGE_DIR;\n if (customDir) {\n return customDir;\n }\n return path.join(os.tmpdir(), \"siliconflow-images\");\n}\n\n/**\n * Save base64 image data to a temporary file\n * @param base64Data - Base64 encoded image data\n * @param prefix - Prefix for the filename\n * @param mimeType - MIME type to determine file extension\n * @returns Path to the saved file\n */\nexport async function saveImageToFile(\n base64Data: string,\n prefix: string,\n mimeType: string,\n): Promise<string> {\n const tempDir = getImageBaseDir();\n await fs.mkdir(tempDir, { recursive: true });\n\n const extension = mimeType === \"image/jpeg\" ? \"jpg\" : \"png\";\n const timestamp = Date.now();\n const filename = `${prefix}_${timestamp}.${extension}`;\n const filepath = path.join(tempDir, filename);\n\n const buffer = Buffer.from(base64Data, \"base64\");\n await fs.writeFile(filepath, buffer);\n\n return filepath;\n}\n\n/**\n * Get the temporary directory path for siliconflow images\n * Uses SILICONFLOW_IMAGE_DIR env var if set, otherwise defaults to system temp dir\n * @returns The temporary directory path\n */\nexport function getTempDir(): string {\n return getImageBaseDir();\n}\n", "/**\n * Image generation tool implementation for SiliconFlow\n */\n\nimport { SiliconFlowService } from \"../services/siliconflow.js\";\nimport { GenerateImageInputSchema, ToolResponse } from \"../types/index.js\";\nimport { saveImageToFile, getTempDir } from \"../utils/file.js\";\n\nexport function createGenerateImageTool(service: SiliconFlowService) {\n return {\n name: \"generate_image\",\n description:\n \"Generate images using SiliconFlow's AI models. Supports various aspect ratios, image sizes, negative prompts, and seeds for reproducible results. Images are saved to temporary files and paths are returned.\",\n inputSchema: GenerateImageInputSchema,\n\n handler: async (input: unknown): Promise<ToolResponse> => {\n const parsed = GenerateImageInputSchema.safeParse(input);\n\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.errors.map((e) => e.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n const { prompt, model, aspectRatio, imageSize, count, negativePrompt, seed } = parsed.data;\n\n try {\n const images = await service.generateImage(\n prompt,\n model || \"black-forest-labs/FLUX.1-dev\",\n aspectRatio,\n imageSize,\n count,\n negativePrompt,\n seed,\n );\n\n if (images.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No images were generated. Please try a different prompt.\",\n },\n ],\n isError: true,\n };\n }\n\n // Save images to files and return file paths\n const savedFiles: string[] = [];\n\n for (let i = 0; i < images.length; i++) {\n const img = images[i];\n const filepath = await saveImageToFile(img.data, `generated_${i + 1}`, img.mimeType);\n savedFiles.push(filepath);\n }\n\n // Create response with file paths\n const tempDir = getTempDir();\n const response: ToolResponse = {\n content: [\n {\n type: \"text\",\n text:\n `Successfully generated ${images.length} image${images.length > 1 ? \"s\" : \"\"} for prompt: \"${prompt}\"\\n` +\n `Saved to:\\n${savedFiles.map((f) => `- ${f}`).join(\"\\n\")}\\n\\n` +\n `Temporary directory: ${tempDir}\\n` +\n `Note: These are temporary files. Use the file paths to access the images.`,\n },\n ],\n };\n\n return response;\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Image generation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n },\n ],\n isError: true,\n };\n }\n },\n };\n}\n", "/**\n * Image editing tool implementation for SiliconFlow\n */\n\nimport { SiliconFlowService } from \"../services/siliconflow.js\";\nimport { EditImageInputSchema, ToolResponse } from \"../types/index.js\";\nimport { saveImageToFile, getTempDir } from \"../utils/file.js\";\n\nexport function createEditImageTool(service: SiliconFlowService) {\n return {\n name: \"edit_image\",\n description:\n \"Edit existing images using SiliconFlow's AI models. Accepts base64 encoded image data, image URLs, or local file paths. Provide instructions for modifications. Uses Qwen/Qwen-Image-Edit-2509 by default. Images are saved to temporary files and paths are returned.\",\n inputSchema: EditImageInputSchema,\n\n handler: async (input: unknown): Promise<ToolResponse> => {\n const parsed = EditImageInputSchema.safeParse(input);\n\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.errors.map((e) => e.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n const { image, prompt, model } = parsed.data;\n\n try {\n const editedImage = await service.editImage(\n image,\n prompt,\n model || \"Qwen/Qwen-Image-Edit-2509\",\n );\n\n // Save edited image to file\n const filepath = await saveImageToFile(editedImage.data, \"edited\", editedImage.mimeType);\n\n // Create response with file path\n const tempDir = getTempDir();\n const response: ToolResponse = {\n content: [\n {\n type: \"text\",\n text:\n `Successfully edited image with prompt: \"${prompt}\"\\n` +\n `Saved to: ${filepath}\\n\\n` +\n `Temporary directory: ${tempDir}\\n` +\n `Note: This is a temporary file. Use the file path to access the image.`,\n },\n ],\n };\n\n return response;\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Image editing failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n },\n ],\n isError: true,\n };\n }\n },\n };\n}\n", "/**\n * List image models tool implementation for SiliconFlow\n */\n\nimport { SiliconFlowService } from \"../services/siliconflow.js\";\nimport { ListModelsInputSchema, ToolResponse } from \"../types/index.js\";\n\nexport function createListModelsTool(service: SiliconFlowService) {\n return {\n name: \"list_image_models\",\n description:\n \"List all available image generation models from SiliconFlow. Shows model IDs and capabilities.\",\n inputSchema: ListModelsInputSchema,\n\n handler: async (input: unknown): Promise<ToolResponse> => {\n const parsed = ListModelsInputSchema.safeParse(input);\n\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.errors.map((e) => e.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n const models = await service.listImageModels();\n\n if (models.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No image generation models found. This might be a temporary issue with the API.\",\n },\n ],\n isError: true,\n };\n }\n\n // Format the response for readability\n const modelList = models\n .map((model, index) => {\n const parts = [\n `${index + 1}. **${model.name}** (\\`${model.id}\\`)`,\n model.description ? ` - ${model.description}` : null,\n model.output_modalities\n ? ` - Capabilities: ${model.output_modalities.join(\", \")}`\n : null,\n ].filter(Boolean);\n\n return parts.join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n // Add SiliconFlow-specific usage tips\n const usageTips = `\\n\\n---\\n\\n**Usage:** Use the \\`generate_image\\` tool with the model ID to generate images.\\n\\n**SiliconFlow Tips:**\\n- Recommended models: \\`black-forest-labs/FLUX.1-dev\\` (generation), \\`Qwen/Qwen-Image-Edit-2509\\` (editing)\\n- Supports advanced options: negative prompts, seeds, CFG values\\n- Image sizes: Use aspect ratios like \"1:1\", \"16:9\", \"9:16\"\\n- Optimized for China users with fast local network access`;\n\n return {\n content: [\n {\n type: \"text\",\n text: `## Available Image Generation Models (SiliconFlow)\\n\\nFound ${models.length} model${models.length > 1 ? \"s\" : \"\"} that support image generation:\\n\\n${modelList}${usageTips}`,\n },\n ],\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Failed to list models: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n },\n ],\n isError: true,\n };\n }\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n/**\n * SiliconFlow Image MCP Server\n *\n * A Model Context Protocol server for image generation and editing using SiliconFlow\n * Optimized for China users\n */\n\n// Handle build flag for compilation\nif (process.argv.includes('--build')) {\n console.log('\u2705 Project structure is ready. Use \"npm start\" to run the server.');\n console.log('\uD83D\uDCDD Note: This project uses tsx for runtime execution.');\n process.exit(0);\n}\n\n// Handle version flag\nif (process.argv.includes('--version') || process.argv.includes('-v')) {\n console.log('1.0.8');\n process.exit(0);\n}\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { SiliconFlowService } from \"./services/siliconflow.js\";\nimport { createGenerateImageTool } from \"./tools/generate.js\";\nimport { createEditImageTool } from \"./tools/edit.js\";\nimport { createListModelsTool } from \"./tools/list-models.js\";\n\n// Environment variable check\nconst SILICONFLOW_API_KEY = process.env.SILICONFLOW_API_KEY;\nconst MOCK_MODE = process.env.SILICONFLOW_MOCK === \"true\";\n\nif (!SILICONFLOW_API_KEY && !MOCK_MODE) {\n console.error(\"\u274C Error: SILICONFLOW_API_KEY environment variable is required\");\n console.error(\"\\nTo use this MCP server:\");\n console.error(\"1. Get your API key from https://siliconflow.cn\");\n console.error(\"2. Set it as an environment variable:\");\n console.error(\" export SILICONFLOW_API_KEY=your-api-key-here\");\n console.error(\"\\nFor Claude Desktop, add to your config.json:\");\n console.error(`{\n \"mcpServers\": {\n \"siliconflow-image-mcp\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"siliconflow-image-mcp\"],\n \"env\": {\n \"SILICONFLOW_API_KEY\": \"your-api-key-here\"\n }\n }\n }\n}`);\n console.error(\"\\nOptional configurations:\");\n console.error(\" export SILICONFLOW_MOCK=true # Use mock mode for testing\");\n console.error(\" export SILICONFLOW_IMAGE_DIR=/path # Custom directory for saved images\");\n process.exit(1);\n}\n\n// Initialize services and server\nasync function main() {\n console.error(\"\uD83D\uDE80 Starting SiliconFlow Image MCP Server...\");\n\n try {\n // Initialize SiliconFlow service\n let siliconFlowService;\n if (MOCK_MODE) {\n console.error(\"\u26A0\uFE0F Running in MOCK mode - API calls will be simulated\");\n // Create a mock service that returns fake data\n siliconFlowService = {\n generateImage: async () => [{ data: \"mock-base64-data\", mimeType: \"image/png\" }],\n editImage: async () => ({ data: \"mock-base64-data\", mimeType: \"image/png\" }),\n listImageModels: async () => [\n { id: \"black-forest-labs/FLUX.1-dev\", name: \"FLUX.1-dev\", description: \"Mock model\", output_modalities: [\"image\"] }\n ],\n testConnection: async () => true\n };\n } else {\n siliconFlowService = new SiliconFlowService(SILICONFLOW_API_KEY);\n\n // Test connection\n const isConnected = await siliconFlowService.testConnection();\n if (!isConnected) {\n console.error(\"\u274C Failed to connect to SiliconFlow. Please check your API key.\");\n process.exit(1);\n }\n console.error(\"\u2705 Connected to SiliconFlow successfully\");\n }\n\n // Create MCP server\n const server = new McpServer({\n name: \"siliconflow-image-mcp\",\n version: \"1.0.0\",\n capabilities: {\n tools: {\n listChanged: true,\n },\n },\n });\n\n // Register tools\n const generateTool = createGenerateImageTool(siliconFlowService);\n const editTool = createEditImageTool(siliconFlowService);\n const listModelsTool = createListModelsTool(siliconFlowService);\n\n server.registerTool(\n generateTool.name,\n {\n description: generateTool.description,\n inputSchema: generateTool.inputSchema,\n },\n generateTool.handler\n );\n\n server.registerTool(\n editTool.name,\n {\n description: editTool.description,\n inputSchema: editTool.inputSchema,\n },\n editTool.handler\n );\n\n server.registerTool(\n listModelsTool.name,\n {\n description: listModelsTool.description,\n inputSchema: listModelsTool.inputSchema,\n },\n listModelsTool.handler\n );\n\n // Connect to stdio transport\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n console.error(\"\u2705 SiliconFlow Image MCP Server is running\");\n console.error(\"\uD83D\uDCCB Available tools: generate_image, edit_image, list_image_models\");\n console.error(\"\uD83D\uDCDD Waiting for requests...\");\n\n // Handle graceful shutdown\n process.on(\"SIGINT\", async () => {\n console.error(\"\\n\uD83D\uDED1 Shutting down gracefully...\");\n await server.close();\n process.exit(0);\n });\n\n } catch (error) {\n console.error(\"\u274C Failed to start server:\", error instanceof Error ? error.message : \"Unknown error\");\n process.exit(1);\n }\n}\n\n// Run the server\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});", "/**\n * SiliconFlow service wrapper for image generation and editing\n * Optimized for China users\n */\n\nimport { ImageResult, ModelInfo } from \"../types/index.js\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\nexport class SiliconFlowService {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(apiKey: string) {\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"SiliconFlow API key is required\");\n }\n this.apiKey = apiKey;\n this.baseUrl = \"https://api.siliconflow.cn/v1\";\n }\n\n /**\n * Make API call to SiliconFlow\n */\n private async makeApiCall<T = any>(endpoint: string, body: any): Promise<T> {\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error (${response.status}): ${errorText}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Make GET API call to SiliconFlow\n */\n private async makeGetCall<T = any>(endpoint: string, params?: Record<string, any>): Promise<T> {\n const url = new URL(`${this.baseUrl}${endpoint}`);\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, String(value));\n }\n });\n }\n\n const response = await fetch(url.toString(), {\n method: \"GET\",\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error (${response.status}): ${errorText}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n /**\n * Generate images using SiliconFlow's image generation models\n */\n async generateImage(\n prompt: string,\n model: string = \"black-forest-labs/FLUX.1-dev\",\n aspectRatio?: string,\n imageSize?: string,\n count: number = 1,\n negativePrompt?: string,\n seed?: number,\n ): Promise<ImageResult[]> {\n try {\n // Build request body\n const requestBody: any = {\n model,\n prompt,\n batch_size: Math.min(count, 4), // SiliconFlow max is 4\n };\n\n // Handle image size mapping from aspect ratio\n if (aspectRatio || imageSize) {\n requestBody.image_size = this.mapAspectRatioToSize(aspectRatio, imageSize, model);\n }\n\n if (negativePrompt) {\n requestBody.negative_prompt = negativePrompt;\n }\n\n if (seed !== undefined) {\n requestBody.seed = seed;\n }\n\n // Use SiliconFlow's image generation endpoint\n const result = await this.makeApiCall(\"/images/generations\", requestBody);\n\n if (!result.images || result.images.length === 0) {\n throw new Error(\"No images were generated\");\n }\n\n // Download images and convert to base64\n const images: ImageResult[] = [];\n for (const img of result.images) {\n const imageUrl = img.url;\n const imageResponse = await fetch(imageUrl);\n if (!imageResponse.ok) {\n throw new Error(`Failed to download image: ${imageResponse.status}`);\n }\n\n const imageBuffer = await imageResponse.arrayBuffer();\n const base64Data = Buffer.from(imageBuffer).toString(\"base64\");\n\n // Determine mime type from URL or default to PNG\n const mimeType = imageUrl.includes(\".png\")\n ? \"image/png\"\n : imageUrl.includes(\".jpg\") || imageUrl.includes(\".jpeg\")\n ? \"image/jpeg\"\n : \"image/png\";\n\n images.push({\n data: base64Data,\n mimeType,\n });\n }\n\n return images;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Image generation failed: ${error.message}`);\n }\n throw new Error(\"Image generation failed with unknown error\");\n }\n }\n\n /**\n * Edit an existing image using SiliconFlow\n */\n async editImage(\n image: string,\n prompt: string,\n model: string = \"Qwen/Qwen-Image-Edit-2509\",\n ): Promise<ImageResult> {\n try {\n // Determine if image is base64, URL, or local file path\n let imageContent: string;\n\n if (image.startsWith(\"data:image/\")) {\n // Already a data URL\n imageContent = image;\n } else if (image.startsWith(\"http://\") || image.startsWith(\"https://\")) {\n // URL - SiliconFlow accepts URLs directly\n imageContent = image;\n } else if (fs.existsSync(image) && fs.statSync(image).isFile()) {\n // Local file path - read and convert to base64 data URL\n const imageBuffer = fs.readFileSync(image);\n const base64Data = imageBuffer.toString(\"base64\");\n\n // Determine mime type from file extension\n const ext = path.extname(image).toLowerCase();\n const mimeType =\n ext === \".png\"\n ? \"image/png\"\n : ext === \".jpg\" || ext === \".jpeg\"\n ? \"image/jpeg\"\n : ext === \".webp\"\n ? \"image/webp\"\n : \"image/png\";\n\n imageContent = `data:${mimeType};base64,${base64Data}`;\n } else {\n // Assume raw base64 string, convert to data URL\n imageContent = `data:image/png;base64,${image}`;\n }\n\n // Build request body for image editing\n const requestBody: any = {\n model,\n prompt,\n image: imageContent,\n };\n\n const result = await this.makeApiCall(\"/images/generations\", requestBody);\n\n if (!result.images || result.images.length === 0) {\n throw new Error(\"No edited image was returned\");\n }\n\n // Download the edited image and convert to base64\n const img = result.images[0];\n const imageUrl = img.url;\n\n const imageResponse = await fetch(imageUrl);\n if (!imageResponse.ok) {\n throw new Error(`Failed to download edited image: ${imageResponse.status}`);\n }\n\n const imageBuffer = await imageResponse.arrayBuffer();\n const base64Data = Buffer.from(imageBuffer).toString(\"base64\");\n\n const mimeType = imageUrl.includes(\".png\")\n ? \"image/png\"\n : imageUrl.includes(\".jpg\") || imageUrl.includes(\".jpeg\")\n ? \"image/jpeg\"\n : \"image/png\";\n\n return {\n data: base64Data,\n mimeType,\n };\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Image editing failed: ${error.message}`);\n }\n throw new Error(\"Image editing failed with unknown error\");\n }\n }\n\n /**\n * List all available image generation models\n */\n async listImageModels(): Promise<ModelInfo[]> {\n try {\n // Get all models, then filter for image generation models\n const result = await this.makeGetCall(\"/models\", { type: \"image\" });\n\n if (!result.data || result.data.length === 0) {\n return [];\n }\n\n // Filter for text-to-image and image-to-image models\n const imageModels = result.data\n .filter((model: any) => {\n // SiliconFlow doesn't always provide detailed modality info in the basic list\n // We'll include models that are commonly known for image generation\n const modelId = model.id.toLowerCase();\n return (\n modelId.includes(\"flux\") ||\n modelId.includes(\"sd\") ||\n modelId.includes(\"stable-diffusion\") ||\n modelId.includes(\"qwen-image\") ||\n modelId.includes(\"kolors\") ||\n modelId.includes(\"dall\") ||\n modelId.includes(\"painting\")\n );\n })\n .map((model: any) => ({\n id: model.id,\n name: model.id,\n description: `Image generation model: ${model.id}`,\n output_modalities: [\"image\"],\n }));\n\n return imageModels;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to list models: ${error.message}`);\n }\n throw new Error(\"Failed to list models with unknown error\");\n }\n }\n\n /**\n * Test the API key validity\n */\n async testConnection(): Promise<boolean> {\n try {\n await this.makeGetCall(\"/models\");\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Map aspect ratio and image size to SiliconFlow's image_size format\n */\n private mapAspectRatioToSize(aspectRatio?: string, imageSize?: string, model?: string): string {\n // SiliconFlow uses \"widthxheight\" format\n // Based on their documentation, we'll map common aspect ratios\n\n // For Qwen models\n if (model && model.includes(\"qwen\")) {\n const qwenSizes: { [key: string]: string } = {\n \"1:1\": \"1328x1328\",\n \"16:9\": \"1664x928\",\n \"9:16\": \"928x1664\",\n \"4:3\": \"1472x1140\",\n \"3:4\": \"1140x1472\",\n \"3:2\": \"1584x1056\",\n \"2:3\": \"1056x1584\",\n };\n if (aspectRatio && qwenSizes[aspectRatio]) {\n return qwenSizes[aspectRatio];\n }\n }\n\n // For Kolors models\n const kolorsSizes: { [key: string]: string } = {\n \"1:1\": \"1024x1024\",\n \"3:4\": \"960x1280\",\n \"4:3\": \"1280x960\",\n \"1:2\": \"720x1440\",\n \"9:16\": \"720x1280\",\n \"16:9\": \"1280x720\",\n };\n\n if (aspectRatio && kolorsSizes[aspectRatio]) {\n return kolorsSizes[aspectRatio];\n }\n\n // Default sizes\n if (imageSize === \"4K\") return \"2048x2048\";\n if (imageSize === \"2K\") return \"1536x1536\";\n\n // Default to 1024x1024\n return \"1024x1024\";\n }\n}\n", "/**\n * Type definitions for SiliconFlow Image MCP\n */\n\nimport { z } from \"zod\";\n\n// Image generation input schema\nexport const GenerateImageInputSchema = z.object({\n prompt: z\n .string()\n .min(1, \"Prompt is required\")\n .max(2000, \"Prompt must be 2000 characters or less\")\n .describe(\"Detailed description of the image to generate\"),\n\n model: z\n .string()\n .optional()\n .describe(\"Model to use for generation (defaults to black-forest-labs/FLUX.1-dev)\"),\n\n aspectRatio: z\n .enum([\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"4:5\", \"5:4\", \"9:16\", \"16:9\", \"21:9\"])\n .optional()\n .describe(\"Aspect ratio for generated images\"),\n\n imageSize: z.enum([\"1K\", \"2K\", \"4K\"]).optional().describe(\"Image size (higher resolution)\"),\n\n count: z\n .number()\n .int()\n .min(1)\n .max(4)\n .optional()\n .default(1)\n .describe(\"Number of images to generate (1-4)\"),\n\n negativePrompt: z.string().optional().describe(\"Negative prompt - what to avoid in the image\"),\n\n seed: z\n .number()\n .int()\n .min(0)\n .max(9999999999)\n .optional()\n .describe(\"Seed for reproducible results\"),\n});\n\nexport type GenerateImageInput = z.infer<typeof GenerateImageInputSchema>;\n\n// Image editing input schema\nexport const EditImageInputSchema = z.object({\n image: z\n .string()\n .min(1, \"Image data is required\")\n .describe(\"Base64 encoded image data, image URL, or local file path to edit\"),\n\n prompt: z\n .string()\n .min(1, \"Edit prompt is required\")\n .max(2000, \"Edit prompt must be 2000 characters or less\")\n .describe(\"Instructions for editing the image\"),\n\n model: z\n .string()\n .optional()\n .describe(\"Model to use for editing (defaults to Qwen/Qwen-Image-Edit-2509)\"),\n});\n\nexport type EditImageInput = z.infer<typeof EditImageInputSchema>;\n\n// List models input schema (empty)\nexport const ListModelsInputSchema = z.object({});\n\nexport type ListModelsInput = z.infer<typeof ListModelsInputSchema>;\n\n// Image result type\nexport interface ImageResult {\n data: string; // Base64 encoded image data\n mimeType: string; // e.g., \"image/png\"\n size?: number; // File size in bytes\n width?: number; // Image width in pixels\n height?: number; // Image height in pixels\n}\n\n// Model information type\nexport interface ModelInfo {\n id: string;\n name: string;\n description?: string;\n output_modalities?: string[];\n pricing?: {\n prompt?: number;\n completion?: number;\n image?: number;\n };\n context_length?: number;\n}\n\n// Tool response type\nexport interface ToolResponse {\n content: Array<{\n type: \"text\" | \"image\" | \"resource\";\n text?: string;\n data?: string;\n mimeType?: string;\n uri?: string;\n name?: string;\n }>;\n isError?: boolean;\n}\n", "/**\n * File utility functions for saving images\n */\n\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport os from \"os\";\n\n/**\n * Get the base directory for storing images\n * Uses SILICONFLOW_IMAGE_DIR env var if set, otherwise defaults to system temp dir\n */\nfunction getImageBaseDir(): string {\n const customDir = process.env.SILICONFLOW_IMAGE_DIR;\n if (customDir) {\n return customDir;\n }\n return path.join(os.tmpdir(), \"siliconflow-images\");\n}\n\n/**\n * Save base64 image data to a temporary file\n * @param base64Data - Base64 encoded image data\n * @param prefix - Prefix for the filename\n * @param mimeType - MIME type to determine file extension\n * @returns Path to the saved file\n */\nexport async function saveImageToFile(\n base64Data: string,\n prefix: string,\n mimeType: string,\n): Promise<string> {\n const tempDir = getImageBaseDir();\n await fs.mkdir(tempDir, { recursive: true });\n\n const extension = mimeType === \"image/jpeg\" ? \"jpg\" : \"png\";\n const timestamp = Date.now();\n const filename = `${prefix}_${timestamp}.${extension}`;\n const filepath = path.join(tempDir, filename);\n\n const buffer = Buffer.from(base64Data, \"base64\");\n await fs.writeFile(filepath, buffer);\n\n return filepath;\n}\n\n/**\n * Get the temporary directory path for siliconflow images\n * Uses SILICONFLOW_IMAGE_DIR env var if set, otherwise defaults to system temp dir\n * @returns The temporary directory path\n */\nexport function getTempDir(): string {\n return getImageBaseDir();\n}\n", "/**\n * Image generation tool implementation for SiliconFlow\n */\n\nimport { SiliconFlowService } from \"../services/siliconflow.js\";\nimport { GenerateImageInputSchema, ToolResponse } from \"../types/index.js\";\nimport { saveImageToFile, getTempDir } from \"../utils/file.js\";\n\nexport function createGenerateImageTool(service: SiliconFlowService) {\n return {\n name: \"generate_image\",\n description:\n \"Generate images using SiliconFlow's AI models. Supports various aspect ratios, image sizes, negative prompts, and seeds for reproducible results. Images are saved to temporary files and paths are returned.\",\n inputSchema: GenerateImageInputSchema,\n\n handler: async (input: unknown): Promise<ToolResponse> => {\n const parsed = GenerateImageInputSchema.safeParse(input);\n\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.errors.map((e) => e.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n const { prompt, model, aspectRatio, imageSize, count, negativePrompt, seed } = parsed.data;\n\n try {\n const images = await service.generateImage(\n prompt,\n model || \"black-forest-labs/FLUX.1-dev\",\n aspectRatio,\n imageSize,\n count,\n negativePrompt,\n seed,\n );\n\n if (images.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No images were generated. Please try a different prompt.\",\n },\n ],\n isError: true,\n };\n }\n\n // Save images to files and return file paths\n const savedFiles: string[] = [];\n\n for (let i = 0; i < images.length; i++) {\n const img = images[i];\n const filepath = await saveImageToFile(img.data, `generated_${i + 1}`, img.mimeType);\n savedFiles.push(filepath);\n }\n\n // Create response with file paths\n const tempDir = getTempDir();\n const response: ToolResponse = {\n content: [\n {\n type: \"text\",\n text:\n `Successfully generated ${images.length} image${images.length > 1 ? \"s\" : \"\"} for prompt: \"${prompt}\"\\n` +\n `Saved to:\\n${savedFiles.map((f) => `- ${f}`).join(\"\\n\")}\\n\\n` +\n `Temporary directory: ${tempDir}\\n` +\n `Note: These are temporary files. Use the file paths to access the images.`,\n },\n ],\n };\n\n return response;\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Image generation failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n },\n ],\n isError: true,\n };\n }\n },\n };\n}\n", "/**\n * Image editing tool implementation for SiliconFlow\n */\n\nimport { SiliconFlowService } from \"../services/siliconflow.js\";\nimport { EditImageInputSchema, ToolResponse } from \"../types/index.js\";\nimport { saveImageToFile, getTempDir } from \"../utils/file.js\";\n\nexport function createEditImageTool(service: SiliconFlowService) {\n return {\n name: \"edit_image\",\n description:\n \"Edit existing images using SiliconFlow's AI models. Accepts base64 encoded image data, image URLs, or local file paths. Provide instructions for modifications. Uses Qwen/Qwen-Image-Edit-2509 by default. Images are saved to temporary files and paths are returned.\",\n inputSchema: EditImageInputSchema,\n\n handler: async (input: unknown): Promise<ToolResponse> => {\n const parsed = EditImageInputSchema.safeParse(input);\n\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.errors.map((e) => e.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n const { image, prompt, model } = parsed.data;\n\n try {\n const editedImage = await service.editImage(\n image,\n prompt,\n model || \"Qwen/Qwen-Image-Edit-2509\",\n );\n\n // Save edited image to file\n const filepath = await saveImageToFile(editedImage.data, \"edited\", editedImage.mimeType);\n\n // Create response with file path\n const tempDir = getTempDir();\n const response: ToolResponse = {\n content: [\n {\n type: \"text\",\n text:\n `Successfully edited image with prompt: \"${prompt}\"\\n` +\n `Saved to: ${filepath}\\n\\n` +\n `Temporary directory: ${tempDir}\\n` +\n `Note: This is a temporary file. Use the file path to access the image.`,\n },\n ],\n };\n\n return response;\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Image editing failed: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n },\n ],\n isError: true,\n };\n }\n },\n };\n}\n", "/**\n * List image models tool implementation for SiliconFlow\n */\n\nimport { SiliconFlowService } from \"../services/siliconflow.js\";\nimport { ListModelsInputSchema, ToolResponse } from \"../types/index.js\";\n\nexport function createListModelsTool(service: SiliconFlowService) {\n return {\n name: \"list_image_models\",\n description:\n \"List all available image generation models from SiliconFlow. Shows model IDs and capabilities.\",\n inputSchema: ListModelsInputSchema,\n\n handler: async (input: unknown): Promise<ToolResponse> => {\n const parsed = ListModelsInputSchema.safeParse(input);\n\n if (!parsed.success) {\n return {\n content: [\n {\n type: \"text\",\n text: `Invalid input: ${parsed.error.errors.map((e) => e.message).join(\", \")}`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n const models = await service.listImageModels();\n\n if (models.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No image generation models found. This might be a temporary issue with the API.\",\n },\n ],\n isError: true,\n };\n }\n\n // Format the response for readability\n const modelList = models\n .map((model, index) => {\n const parts = [\n `${index + 1}. **${model.name}** (\\`${model.id}\\`)`,\n model.description ? ` - ${model.description}` : null,\n model.output_modalities\n ? ` - Capabilities: ${model.output_modalities.join(\", \")}`\n : null,\n ].filter(Boolean);\n\n return parts.join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n // Add SiliconFlow-specific usage tips\n const usageTips = `\\n\\n---\\n\\n**Usage:** Use the \\`generate_image\\` tool with the model ID to generate images.\\n\\n**SiliconFlow Tips:**\\n- Recommended models: \\`black-forest-labs/FLUX.1-dev\\` (generation), \\`Qwen/Qwen-Image-Edit-2509\\` (editing)\\n- Supports advanced options: negative prompts, seeds, CFG values\\n- Image sizes: Use aspect ratios like \"1:1\", \"16:9\", \"9:16\"\\n- Optimized for China users with fast local network access`;\n\n return {\n content: [\n {\n type: \"text\",\n text: `## Available Image Generation Models (SiliconFlow)\\n\\nFound ${models.length} model${models.length > 1 ? \"s\" : \"\"} that support image generation:\\n\\n${modelList}${usageTips}`,\n },\n ],\n };\n } catch (error) {\n return {\n content: [\n {\n type: \"text\",\n text: `Failed to list models: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n },\n ],\n isError: true,\n };\n }\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["imageBuffer", "base64Data", "mimeType", "fs", "path", "path", "fs"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "siliconflow-image-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "MCP server for image generation and editing using SiliconFlow - Optimized for China users",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"siliconflow-image-mcp": "
|
|
8
|
+
"siliconflow-image-mcp": "dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
12
|
"src",
|
|
13
|
-
"bin",
|
|
14
13
|
"README.md",
|
|
15
14
|
"LICENSE"
|
|
16
15
|
],
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,12 @@ if (process.argv.includes('--build')) {
|
|
|
13
13
|
process.exit(0);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
// Handle version flag
|
|
17
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
18
|
+
console.log('1.0.8');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
17
23
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
18
24
|
import { SiliconFlowService } from "./services/siliconflow.js";
|
package/dist/package.json
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "siliconflow-image-mcp",
|
|
3
|
-
"version": "1.0.7",
|
|
4
|
-
"description": "MCP server for image generation and editing using SiliconFlow - Optimized for China users",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "index.js",
|
|
7
|
-
"bin": "index.js",
|
|
8
|
-
"dependencies": {
|
|
9
|
-
"@modelcontextprotocol/sdk": "^1.0.3",
|
|
10
|
-
"tsx": "^4.7.0",
|
|
11
|
-
"zod": "^3.22.4"
|
|
12
|
-
},
|
|
13
|
-
"engines": {
|
|
14
|
-
"node": ">=18.0.0"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"mcp",
|
|
18
|
-
"siliconflow",
|
|
19
|
-
"image-generation",
|
|
20
|
-
"ai",
|
|
21
|
-
"claude",
|
|
22
|
-
"model-context-protocol",
|
|
23
|
-
"china",
|
|
24
|
-
"image-editing",
|
|
25
|
-
"flux",
|
|
26
|
-
"qwen"
|
|
27
|
-
],
|
|
28
|
-
"license": "MIT",
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/martianzhang/siliconflow-image-mcp.git"
|
|
32
|
-
}
|
|
33
|
-
}
|