Skip to main content
Glama
caleb-conner

Open Food Facts MCP Server

by caleb-conner

get_product_suggestions

Find food products matching dietary preferences like vegan, gluten-free, or organic within specific categories using nutritional scoring.

Instructions

Get product suggestions based on dietary preferences or restrictions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
categoryYesProduct category to search within
dietary_preferencesNoDietary preferences or restrictions
max_resultsNoMaximum number of suggestions (default: 10)
min_nutriscoreNoMinimum Nutri-Score grade (a, b, c, d, e)

Implementation Reference

  • Main handler function executing the tool: destructures params, builds search query for category and nutriscore, calls client.searchProducts, filters by dietary preferences, formats suggestions, returns formatted text response.
    async handleGetProductSuggestions(params: any) {
      const { category, dietary_preferences = [], max_results = 10, min_nutriscore } = params;
      
      const searchParams: any = {
        categories: category,
        page_size: Math.min(max_results * 2, 100), // Get extra to filter
        sort_by: 'popularity',
      };
    
      if (min_nutriscore) {
        const validGrades = ['a', 'b', 'c', 'd', 'e'];
        const minIndex = validGrades.indexOf(min_nutriscore);
        const allowedGrades = validGrades.slice(0, minIndex + 1);
        searchParams.nutrition_grades = allowedGrades.join(',');
      }
    
      const response = await this.client.searchProducts(searchParams);
      
      let filteredProducts = response.products;
    
      // Filter by dietary preferences
      if (dietary_preferences.length > 0) {
        filteredProducts = this.filterByDietaryPreferences(filteredProducts, dietary_preferences);
      }
    
      const suggestions = filteredProducts
        .slice(0, max_results)
        .map((product, index) => `${index + 1}. ${this.formatProductSuggestion(product)}`)
        .join('\n\n');
    
      return {
        content: [
          {
            type: "text" as const,
            text: `Product suggestions in ${category}:\n\n${suggestions}`,
          },
        ],
      };
    }
  • Tool schema definition including input schema with parameters: category (required), dietary_preferences, max_results, min_nutriscore.
    {
      name: "get_product_suggestions",
      description: "Get product suggestions based on dietary preferences or restrictions",
      inputSchema: {
        type: "object",
        properties: {
          category: {
            type: "string",
            description: "Product category to search within",
          },
          dietary_preferences: {
            type: "array",
            items: {
              type: "string",
              enum: ["vegan", "vegetarian", "gluten-free", "organic", "low-fat", "low-sugar", "high-protein"],
            },
            description: "Dietary preferences or restrictions",
          },
          max_results: {
            type: "number",
            description: "Maximum number of suggestions (default: 10)",
            minimum: 1,
            maximum: 50,
          },
          min_nutriscore: {
            type: "string",
            description: "Minimum Nutri-Score grade (a, b, c, d, e)",
            enum: ["a", "b", "c", "d", "e"],
          },
        },
        required: ["category"],
      },
    },
  • src/index.ts:57-58 (registration)
    Registration in the MCP server request handler switch statement, dispatching to the handler function.
    case 'get_product_suggestions':
      return await handlers.handleGetProductSuggestions(args);
  • Helper method to filter products based on dietary preferences by checking labels, categories, and ingredients.
    private filterByDietaryPreferences(products: Product[], preferences: string[]): Product[] {
      return products.filter(product => {
        const labels = (product.labels || '').toLowerCase();
        const categories = (product.categories || '').toLowerCase();
        const ingredients = (product.ingredients_text || '').toLowerCase();
        
        return preferences.every(pref => {
          switch (pref) {
            case 'vegan':
              return labels.includes('vegan') || categories.includes('vegan');
            case 'vegetarian':
              return labels.includes('vegetarian') || categories.includes('vegetarian');
            case 'gluten-free':
              return labels.includes('gluten') && labels.includes('free');
            case 'organic':
              return labels.includes('organic') || labels.includes('bio');
            case 'low-fat':
              return labels.includes('low-fat') || labels.includes('light');
            case 'low-sugar':
              return labels.includes('sugar-free') || labels.includes('no-sugar');
            case 'high-protein':
              return labels.includes('high-protein') || labels.includes('protein');
            default:
              return true;
          }
        });
      });
    }
  • Helper method to format individual product suggestions including summary and scores.
    private formatProductSuggestion(product: Product): string {
      const summary = this.formatProductSummary(product);
      const scores = [];
      if (product.nutriscore_grade) scores.push(`Nutri-Score: ${product.nutriscore_grade.toUpperCase()}`);
      if (product.nova_group) scores.push(`Processing: NOVA ${product.nova_group}`);
      if (product.ecoscore_grade) scores.push(`Eco: ${product.ecoscore_grade.toUpperCase()}`);
      
      return summary + (scores.length > 0 ? `\nScores: ${scores.join(' | ')}` : '');
    }

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/caleb-conner/open-food-facts-mcp'

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