UNPKG

christmas-mcp-image-describe

Version:

MCP server that analyzes images and provides structured metadata for website placement decisions using OpenAI GPT-4o Vision API

189 lines (166 loc) 6.17 kB
#!/usr/bin/env node // Christmas MCP Image Describe - Main Entry Point // This file serves as both library export and MCP server entry point // Export the core functionality for library usage export { analyzeImage, analyzeImages } from './src/imageAnalyzer.js'; // Check if this file is being executed directly import { fileURLToPath } from 'url'; import path from 'path'; const __filename = fileURLToPath(import.meta.url); const isDirectExecution = process.argv[1] && path.resolve(process.argv[1]) === path.resolve(__filename); if (isDirectExecution) { // If executed directly, start the MCP server console.error('Starting Christmas MCP Image Describe server...'); // Import and start MCP server const { Server } = await import('@modelcontextprotocol/sdk/server/index.js'); const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); const { CallToolRequestSchema, ListToolsRequestSchema } = await import('@modelcontextprotocol/sdk/types.js'); const { analyzeImage, analyzeImages } = await import('./src/imageAnalyzer.js'); class ImageAnalysisMCPServer { constructor() { this.server = new Server( { name: 'christmas-mcp-image-describe', version: '1.0.2', }, { capabilities: { tools: {}, }, } ); this.setupToolHandlers(); this.setupErrorHandling(); } setupErrorHandling() { this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'analyze_image', description: 'Analyze an image and provide structured metadata for website placement decisions', inputSchema: { type: 'object', properties: { imagePath: { type: 'string', description: 'Path to the local image file' }, context: { type: 'string', description: 'Optional context like "about section" or "homepage hero"' }, apiKey: { type: 'string', description: 'OpenAI API key' }, project: { type: 'string', description: 'OpenAI project ID (optional)' } }, required: ['imagePath', 'apiKey'] } }, { name: 'analyze_images_batch', description: 'Analyze multiple images in batch and provide structured metadata', inputSchema: { type: 'object', properties: { images: { type: 'array', items: { type: 'object', properties: { path: { type: 'string', description: 'Path to the image file' }, context: { type: 'string', description: 'Optional context for this image' } }, required: ['path'] }, description: 'Array of image objects to analyze' }, apiKey: { type: 'string', description: 'OpenAI API key' }, project: { type: 'string', description: 'OpenAI project ID (optional)' } }, required: ['images', 'apiKey'] } } ] }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { if (name === 'analyze_image') { const { imagePath, context = '', apiKey, project } = args; if (!imagePath || !apiKey) { throw new Error('imagePath and apiKey are required'); } const result = await analyzeImage(imagePath, context, apiKey, project); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } if (name === 'analyze_images_batch') { const { images, apiKey, project } = args; if (!images || !Array.isArray(images) || !apiKey) { throw new Error('images array and apiKey are required'); } const results = await analyzeImages(images, apiKey, project); return { content: [ { type: 'text', text: JSON.stringify(results, null, 2) } ] }; } throw new Error(`Unknown tool: ${name}`); } catch (error) { return { content: [ { type: 'text', text: `Error: ${error.message}` } ], isError: true }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Christmas MCP Image Describe server running on stdio'); } } const server = new ImageAnalysisMCPServer(); server.run().catch(console.error); }