cook-mcp-windy
Version:
HowToCook MCP Server - Intelligent Chinese recipe management and meal planning for AI assistants
234 lines โข 9.14 kB
JavaScript
import { program } from 'commander';
import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { readFileSync } from 'fs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Read package.json for version
const packageJsonPath = join(__dirname, '..', 'package.json');
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
/**
* HowToCook MCP Server CLI
*
* This CLI tool provides easy access to the HowToCook MCP Server
* for Chinese recipe management and meal planning.
*/
program
.name('cook-mcp-windy')
.description('HowToCook MCP Server - Intelligent Chinese recipe management and meal planning')
.version(packageJson.version);
program
.command('start')
.description('Start the HowToCook MCP Server')
.option('-p, --port <port>', 'Port to run the server on (for HTTP mode)', '3000')
.option('-m, --mode <mode>', 'Server mode: stdio (default) or http', 'stdio')
.option('-v, --verbose', 'Enable verbose logging')
.action((options) => {
// Only show output in non-stdio mode to avoid interfering with MCP communication
if (options.mode !== 'stdio') {
console.log('๐ณ Starting HowToCook MCP Server...');
console.log(`๐ Mode: ${options.mode}`);
if (options.verbose) {
console.log('๐ง Verbose logging enabled');
}
}
if (options.mode === 'stdio') {
// In stdio mode, use the direct MCP server without any console output
const serverPath = join(__dirname, 'start-mcp.js');
const server = spawn('node', [serverPath], {
stdio: 'inherit',
env: {
...process.env,
VERBOSE: options.verbose ? 'true' : 'false'
}
});
server.on('error', (error) => {
console.error('โ Failed to start server:', error.message);
process.exit(1);
});
server.on('exit', (code) => {
if (code !== 0) {
console.error(`โ Server exited with code ${code}`);
process.exit(code || 1);
}
});
}
else if (options.mode === 'http') {
console.log(`๐ Starting HTTP server on port ${options.port}`);
console.log('โ ๏ธ HTTP mode is for testing only. Use stdio mode for MCP clients.');
// Start HTTP server (for testing/debugging)
startHttpServer(parseInt(options.port), options.verbose);
}
else {
console.error('โ Invalid mode. Use "stdio" or "http"');
process.exit(1);
}
});
program
.command('test')
.description('Test the HowToCook MCP Server functionality')
.option('-t, --tool <tool>', 'Test specific tool only')
.option('-v, --verbose', 'Enable verbose output')
.action(async (options) => {
console.log('๐งช Testing HowToCook MCP Server...');
try {
const { runTests } = await import('./test/testRunner.js');
await runTests({
specificTool: options.tool,
verbose: options.verbose
});
}
catch (error) {
console.error('โ Test failed:', error instanceof Error ? error.message : 'Unknown error');
process.exit(1);
}
});
program
.command('info')
.description('Show information about available tools and features')
.action(() => {
console.log('๐ณ HowToCook MCP Server Information');
console.log('=====================================\n');
console.log('๐ Available MCP Tools:');
console.log(' โข get_all_recipes - Retrieve all recipes with pagination');
console.log(' โข get_recipes_by_category - Filter recipes by category');
console.log(' โข get_recipe_details - Get detailed recipe information');
console.log(' โข recommend_meal_plan - Generate intelligent meal plans');
console.log(' โข recommend_dish_combination - Suggest dish combinations\n');
console.log('๐ฅ Supported Recipe Categories:');
console.log(' โข ๆฐดไบง (Seafood) โข ๆฉ้ค (Breakfast)');
console.log(' โข ่ฐๅณๆ (Seasonings) โข ็ๅ (Desserts)');
console.log(' โข ้ฅฎๅ (Beverages) โข ่ค่ (Meat Dishes)');
console.log(' โข ๅๆๅ (Semi-prepared) โข ๆฑค็พน (Soups)');
console.log(' โข ไธป้ฃ (Staples) โข ็ด ่ (Vegetarian)\n');
console.log('๐ฏ Key Features:');
console.log(' โข Intelligent meal planning with dietary restrictions');
console.log(' โข Automatic shopping list generation');
console.log(' โข Recipe scaling for different serving sizes');
console.log(' โข Nutritional analysis and cooking guidance');
console.log(' โข Traditional Chinese cuisine focus\n');
console.log('๐ Integration:');
console.log(' โข Compatible with Claude Desktop and other MCP clients');
console.log(' โข Standard Model Context Protocol implementation');
console.log(' โข Easy setup with npx @windy-freedom/cook start\n');
console.log('๐ Documentation:');
console.log(' โข GitHub: https://github.com/windy-freedom/cook');
console.log(' โข Issues: https://github.com/windy-freedom/cook/issues');
});
program
.command('mcp')
.description('Start MCP server directly (for Claude Desktop)')
.action(() => {
// Direct MCP server start - no console output
const serverPath = join(__dirname, 'start-mcp.js');
const server = spawn('node', [serverPath], {
stdio: 'inherit'
});
server.on('error', () => {
process.exit(1);
});
server.on('exit', (code) => {
process.exit(code || 0);
});
});
program
.command('config')
.description('Generate MCP client configuration')
.option('-c, --client <client>', 'Client type: claude-desktop (default)', 'claude-desktop')
.option('-o, --output <file>', 'Output configuration to file')
.action((options) => {
console.log('โ๏ธ Generating MCP Configuration...\n');
const config = generateMCPConfig(options.client);
if (options.output) {
const fs = require('fs');
fs.writeFileSync(options.output, JSON.stringify(config, null, 2));
console.log(`โ
Configuration saved to ${options.output}`);
}
else {
console.log('๐ MCP Configuration:');
console.log(JSON.stringify(config, null, 2));
}
console.log('\n๐ Setup Instructions:');
if (options.client === 'claude-desktop') {
console.log('1. Copy the configuration above');
console.log('2. Add it to your Claude Desktop MCP settings');
console.log('3. Restart Claude Desktop');
console.log('4. The HowToCook tools will be available in Claude');
}
});
// HTTP server for testing
async function startHttpServer(port, _verbose) {
const express = await import('express');
const app = express.default();
app.use(express.json());
app.get('/', (_req, res) => {
res.json({
name: 'HowToCook MCP Server',
version: packageJson.version,
status: 'running',
mode: 'http-test',
tools: [
'get_all_recipes',
'get_recipes_by_category',
'get_recipe_details',
'recommend_meal_plan',
'recommend_dish_combination'
]
});
});
app.post('/tools/:toolName', async (req, res) => {
try {
const { toolHandlers } = await import('./tools/index.js');
const handler = toolHandlers[req.params.toolName];
if (!handler) {
return res.status(404).json({ error: 'Tool not found' });
}
const result = await handler(req.body);
res.json(result);
return;
}
catch (error) {
res.status(500).json({
error: 'Tool execution failed',
details: error instanceof Error ? error.message : 'Unknown error'
});
return;
}
});
app.listen(port, () => {
console.log(`โ
HTTP server running on http://localhost:${port}`);
console.log(`๐ Available endpoints:`);
console.log(` GET / - Server info`);
console.log(` POST /tools/{toolName} - Execute tool`);
});
}
// Generate MCP configuration
function generateMCPConfig(clientType) {
const baseConfig = {
mcpServers: {
"howtocook": {
command: "npx",
args: ["cook-mcp-windy", "mcp"],
env: {}
}
}
};
if (clientType === 'claude-desktop') {
return baseConfig;
}
return baseConfig;
}
// Handle uncaught errors
process.on('uncaughtException', (error) => {
console.error('๐ฅ Uncaught Exception:', error.message);
process.exit(1);
});
process.on('unhandledRejection', (reason) => {
console.error('๐ฅ Unhandled Rejection:', reason);
process.exit(1);
});
// Parse command line arguments
program.parse();
//# sourceMappingURL=cli.js.map