cook-mcp-windy
Version:
HowToCook MCP Server - Intelligent Chinese recipe management and meal planning for AI assistants
181 lines • 5.89 kB
JavaScript
/**
* 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