UNPKG

cook-mcp-windy

Version:

HowToCook MCP Server - Intelligent Chinese recipe management and meal planning for AI assistants

181 lines 5.89 kB
#!/usr/bin/env node /** * Pure MCP Server Entry Point * * This file is specifically for MCP clients and contains no console output * that could interfere with the JSON-RPC communication protocol. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { allTools, toolHandlers } from './tools/index.js'; /** * Pure MCP Server - No console output, only JSON-RPC communication */ class PureMCPServer { server; constructor() { this.server = new Server({ name: 'howtocook-mcp', version: '1.0.0', }, { capabilities: { tools: {}, }, }); this.setupToolHandlers(); this.setupErrorHandling(); } setupToolHandlers() { // Handle tool listing this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: allTools, }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { // Validate tool exists if (!toolHandlers[name]) { throw new Error(`Unknown tool: ${name}`); } // Call the appropriate tool handler const handler = toolHandlers[name]; const result = await handler(args || {}); // Format response for MCP return { content: [ { type: 'text', text: this.formatToolResponse(name, result), }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [ { type: 'text', text: JSON.stringify({ success: false, error: `Tool execution failed: ${errorMessage}`, tool: name, timestamp: new Date().toISOString() }, null, 2), }, ], isError: true, }; } }); } setupErrorHandling() { // Silent error handling - no console output this.server.onerror = () => { // Errors are handled silently in MCP mode }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); process.on('SIGTERM', async () => { await this.server.close(); process.exit(0); }); } formatToolResponse(toolName, response) { const timestamp = new Date().toISOString(); if (response.success) { return JSON.stringify({ success: true, tool: toolName, message: response.message, data: response.data, timestamp, metadata: { toolCategory: this.getToolCategory(toolName), dataType: this.getDataType(response.data), recordCount: this.getRecordCount(response.data) } }, null, 2); } else { return JSON.stringify({ success: false, tool: toolName, error: response.error, details: response.details, timestamp }, null, 2); } } getToolCategory(toolName) { const categories = { 'get_all_recipes': 'Recipe Management', 'get_recipes_by_category': 'Recipe Management', 'get_recipe_details': 'Recipe Management', 'recommend_meal_plan': 'Meal Planning', 'recommend_dish_combination': 'Meal Planning' }; return categories[toolName] || 'Unknown'; } getDataType(data) { if (!data) return 'none'; if (Array.isArray(data)) return 'array'; if (data.items && Array.isArray(data.items)) return 'paginated'; if (data.recipe) return 'recipe'; if (data.mealPlan) return 'meal_plan'; if (data.combination) return 'dish_combination'; return 'object'; } getRecordCount(data) { if (!data) return 0; if (Array.isArray(data)) return data.length; if (data.items && Array.isArray(data.items)) return data.items.length; if (data.totalCount) return data.totalCount; return 1; } async start() { const transport = new StdioServerTransport(); await this.server.connect(transport); // No console output in MCP mode } } // Handle uncaught errors silently process.on('uncaughtException', () => { process.exit(1); }); process.on('unhandledRejection', () => { process.exit(1); }); // Start the pure MCP server async function main() { try { const server = new PureMCPServer(); await server.start(); } catch (error) { process.exit(1); } } // Start the server if this file is run directly if (import.meta.url === `file://${process.argv[1]}`) { main().catch(() => { process.exit(1); }); } //# sourceMappingURL=mcp-server.js.map