Skip to main content
Glama
WhenYouAreStrange

goodbook-mcp

tools.js14 kB
import PDFParser from './pdf-parser.js'; class GoodbookTools { constructor() { this.pdfParser = new PDFParser(); this.initialized = false; } async initialize() { if (!this.initialized) { this.initialized = await this.pdfParser.initialize(); } return this.initialized; } getToolDefinitions() { return [ { name: "search_food_standards", description: "Search for specific food preparation standards, recipes, or cooking guidelines in the food service literature", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search term or phrase to look for in the food standards document" }, section: { type: "string", description: "Optional: specific section to search within (use list_sections to see available sections)" } }, required: ["query"] } }, { name: "get_cooking_guidelines", description: "Get cooking guidelines and standards for specific dishes or cooking methods", inputSchema: { type: "object", properties: { dish_type: { type: "string", description: "Type of dish or cooking method to get guidelines for" }, section: { type: "string", description: "Optional: specific section to look in" } }, required: ["dish_type"] } }, { name: "list_sections", description: "List all available sections in the food service standards document", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "get_section_content", description: "Get content from a specific section of the food standards document", inputSchema: { type: "object", properties: { section_name: { type: "string", description: "Name of the section to retrieve content from" }, limit: { type: "number", description: "Maximum number of characters to return (default: 1000)" } }, required: ["section_name"] } }, { name: "get_food_safety_info", description: "Get food safety information and hygiene standards", inputSchema: { type: "object", properties: { topic: { type: "string", description: "Specific food safety topic (temperature, storage, hygiene, etc.)" } }, required: ["topic"] } }, { name: "find_recipe_standards", description: "Find standardized recipes and preparation methods for specific dishes", inputSchema: { type: "object", properties: { dish_name: { type: "string", description: "Name of the dish to find recipe standards for" }, cuisine_type: { type: "string", description: "Optional: type of cuisine or cooking style" } }, required: ["dish_name"] } } ]; } async handleTool(name, arguments_) { if (!this.initialized) { await this.initialize(); } if (!this.initialized) { return { content: [{ type: "text", text: "Error: Could not initialize PDF parser. Please check if the menu.pdf file exists." }] }; } try { switch (name) { case "search_food_standards": return await this.searchFoodStandards(arguments_.query, arguments_.section); case "get_cooking_guidelines": return await this.getCookingGuidelines(arguments_.dish_type, arguments_.section); case "list_sections": return await this.listSections(); case "get_section_content": return await this.getSectionContent(arguments_.section_name, arguments_.limit); case "get_food_safety_info": return await this.getFoodSafetyInfo(arguments_.topic); case "find_recipe_standards": return await this.findRecipeStandards(arguments_.dish_name, arguments_.cuisine_type); default: return { content: [{ type: "text", text: `Unknown tool: ${name}` }] }; } } catch (error) { return { content: [{ type: "text", text: `Error executing tool ${name}: ${error.message}` }] }; } } async searchFoodStandards(query, section = null) { // Расширенный поиск с синонимами const expandedQueries = this.expandSearchQuery(query); let allResults = []; for (const searchQuery of expandedQueries) { const results = this.pdfParser.searchContent(searchQuery, section); if (results.results) { allResults.push(...results.results); } } // Удаляем дубликаты const uniqueResults = allResults.filter((result, index, self) => index === self.findIndex(r => r.content === result.content) ); let response = `Search results for "${query}"`; if (section) { response += ` in section "${section}"`; } response += `:\n\nFound ${uniqueResults.length} matches\n\n`; if (uniqueResults.length === 0) { response += "No matching content found."; } else { uniqueResults.slice(0, 15).forEach((result, index) => { response += `Result ${index + 1}:\n`; if (result.before) response += `Context: ${result.before}\n`; response += `> ${result.content}\n`; if (result.after) response += `Context: ${result.after}\n`; response += "\n"; }); } return { content: [{ type: "text", text: response }] }; } // Новый метод для расширения поисковых запросов expandSearchQuery(query) { const synonyms = { // Синонимы для блюд 'котлеты': ['котлеты', 'биточки', 'зразы'], 'картофельные': ['картофельные', 'картофель', 'из картофеля'], 'морковные': ['морковные', 'морковь', 'из моркови', 'морковочные'], 'творог': ['творог', 'творожный', 'сыр творожный', 'кварк'], 'суп': ['суп', 'похлебка', 'бульон', 'борщ', 'щи', 'солянка'], 'пиво': ['пиво', 'пивной', 'с пивом', 'на пиве'], 'сладкий': ['сладкий', 'десертный', 'фруктовый'], 'плов': ['плов', 'рис с мясом', 'узбекский плов'], 'борщ': ['борщ', 'свекольный суп', 'украинский борщ'], 'паста': ['паста', 'макароны', 'спагетти', 'лапша'], 'тирамису': ['тирамису', 'итальянский десерт', 'маскарпоне'], 'пельмени': ['пельмени', 'вареники', 'манты', 'хинкали'], 'салат': ['салат', 'оливье', 'овощной'], 'десерт': ['десерт', 'сладкое', 'торт', 'пирог', 'выпечка'], // Синонимы для процессов 'приготовление': ['приготовление', 'готовка', 'варка', 'жарка', 'тушение'], 'температура': ['температура', 'градус', 'нагрев', 'охлаждение'], 'безопасность': ['безопасность', 'гигиена', 'санитария', 'чистота'], 'хранение': ['хранение', 'консервация', 'сохранность'], // Синонимы для ингредиентов 'мясо': ['мясо', 'говядина', 'свинина', 'баранина', 'курица'], 'овощи': ['овощи', 'морковь', 'лук', 'капуста', 'картофель'], 'специи': ['специи', 'приправы', 'пряности', 'соль', 'перец'] }; const queryWords = query.toLowerCase().split(/\s+/); const expandedQueries = [query]; // Включаем оригинальный запрос // Добавляем варианты с синонимами for (const word of queryWords) { if (synonyms[word]) { for (const synonym of synonyms[word]) { if (synonym !== word) { const newQuery = query.replace(new RegExp(word, 'gi'), synonym); if (!expandedQueries.includes(newQuery)) { expandedQueries.push(newQuery); } } } } } return expandedQueries; } async getCookingGuidelines(dishType, section = null) { // Search for cooking-related terms const cookingTerms = [ dishType, `приготовление ${dishType}`, `готовка ${dishType}`, `рецепт ${dishType}`, `preparation ${dishType}`, `cooking ${dishType}`, `recipe ${dishType}` ]; let allResults = []; for (const term of cookingTerms) { const results = this.pdfParser.searchContent(term, section); if (results.results) { allResults.push(...results.results); } } // Remove duplicates const uniqueResults = allResults.filter((result, index, self) => index === self.findIndex(r => r.content === result.content) ); let response = `Cooking guidelines for "${dishType}":\n\n`; if (uniqueResults.length === 0) { response += "No specific cooking guidelines found for this dish type."; } else { uniqueResults.slice(0, 10).forEach((result, index) => { response += `Guideline ${index + 1}:\n`; response += `${result.content}\n\n`; }); } return { content: [{ type: "text", text: response }] }; } async listSections() { const sections = this.pdfParser.getSections(); let response = "Available sections in the food standards document:\n\n"; sections.forEach((section, index) => { response += `${index + 1}. ${section.name}\n`; response += ` Content length: ${section.contentLength} items\n`; response += ` Preview: ${section.preview}\n\n`; }); return { content: [{ type: "text", text: response }] }; } async getSectionContent(sectionName, limit = 1000) { const content = this.pdfParser.getContent(sectionName, limit); if (content.error) { return { content: [{ type: "text", text: `Error: ${content.error}` }] }; } return { content: [{ type: "text", text: `Content from section "${content.section}":\n\n${content.content}` }] }; } async getFoodSafetyInfo(topic) { const safetyTerms = [ topic, `безопасность ${topic}`, `гигиена ${topic}`, `санитария ${topic}`, `температура ${topic}`, `хранение ${topic}`, `safety ${topic}`, `hygiene ${topic}`, `sanitation ${topic}`, `temperature ${topic}`, `storage ${topic}` ]; let allResults = []; for (const term of safetyTerms) { const results = this.pdfParser.searchContent(term); if (results.results) { allResults.push(...results.results); } } const uniqueResults = allResults.filter((result, index, self) => index === self.findIndex(r => r.content === result.content) ); let response = `Food safety information for "${topic}":\n\n`; if (uniqueResults.length === 0) { response += "No specific food safety information found for this topic."; } else { uniqueResults.slice(0, 8).forEach((result, index) => { response += `Safety guideline ${index + 1}:\n`; response += `${result.content}\n\n`; }); } return { content: [{ type: "text", text: response }] }; } async findRecipeStandards(dishName, cuisineType = null) { const recipeTerms = [ dishName, `рецепт ${dishName}`, `стандарт ${dishName}`, `приготовление ${dishName}`, `recipe ${dishName}`, `standard ${dishName}`, `preparation ${dishName}` ]; if (cuisineType) { recipeTerms.push(`${cuisineType} ${dishName}`); } let allResults = []; for (const term of recipeTerms) { const results = this.pdfParser.searchContent(term); if (results.results) { allResults.push(...results.results); } } const uniqueResults = allResults.filter((result, index, self) => index === self.findIndex(r => r.content === result.content) ); let response = `Recipe standards for "${dishName}"`; if (cuisineType) response += ` (${cuisineType} cuisine)`; response += ":\n\n"; if (uniqueResults.length === 0) { response += "No specific recipe standards found for this dish."; } else { uniqueResults.slice(0, 8).forEach((result, index) => { response += `Standard ${index + 1}:\n`; response += `${result.content}\n\n`; }); } return { content: [{ type: "text", text: response }] }; } } export default GoodbookTools;

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/WhenYouAreStrange/goodbook-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server