openfoodfacts-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openfoodfacts-mcpHow many calories in a Sainsbury's buffalo chicken wrap?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openfoodfacts-mcp
MCP server for the Open Food Facts API - search, read, and contribute to the world's largest open food database.
Use Cases
Look up a product by name: "How many calories in a Sainsbury's buffalo chicken wrap?" -> searches by name, finds the product, and returns nutrition data.
Look up a product by barcode: "What's in this product with barcode 3017620422003?" -> fetches Nutella's ingredients, Nutri-Score, and nutrition data.
Find healthy options: "Search for breakfast cereals with Nutri-Score A" -> searches with category and nutrition grade filters.
Contribute data: "Add the product name and brand for barcode 12345678" -> creates or updates a product entry on Open Food Facts.
Explore the database: "What brands of organic chocolate are in the database?" -> uses autocomplete and search to explore.
Related MCP server: Meals MCP Server
Setup
Follow the instructions on install-mcp, which generates the right config for your MCP client (Claude Code, Claude Desktop, Cursor, Cline, VS Code, and more).
Set OFF_USER_AGENT to identify your app (e.g. openfoodfacts-mcp/1.2.0 (you@example.com)). For write operations (adding/editing products, uploading images), also set OFF_USER_ID and OFF_PASSWORD.
Environment Variables
Variable | Required | Description |
| Yes | User-Agent string, e.g. |
| No | Open Food Facts username (for write operations) |
| No | Open Food Facts password (for write operations) |
| No | Country subdomain (default: |
Tools
Tool | Description | Auth |
| Get product info by barcode | No |
| Search with structured filters (brand, category, Nutri-Score) | No |
| Search with Lucene syntax, negation, and boolean logic | No |
| Autocomplete brands, categories, labels, etc. | No |
| Add or update a product | Yes |
| Upload a product image | Yes |
| Select, crop, and rotate an image | Yes |
| Call any OFF API endpoint directly | Depends |
| Get OFF API documentation | No |
Contributing
Pull requests are welcomed on GitHub! To get started:
Install Git and Node.js
Clone the repository
Install dependencies with
npm installRun
npm run testto run testsBuild with
npm run build
Releases
Versions follow the semantic versioning spec.
To release:
Use
npm version <major | minor | patch>to bump the versionRun
git push --follow-tagsto push with tagsWait for GitHub Actions to publish to the NPM registry.
Available Tools
10 toolsadd_or_edit_productAdd or edit productA
Add a new product or edit an existing one on Open Food Facts. Requires OFF_USER_ID and OFF_PASSWORD.
The more fields you fill, the more useful the entry. At minimum provide product_name, brands, and categories — these feed the search index, and a sparse entry won't be findable. If you have a photo of the pack, transcribe everything you can read: ingredients, nutrition, origins, traceability stamps, recycling icons, certifications.
Fields that drive derived data:
ingredients_text → allergens, additives, NOVA group, fruit/veg %
nutrition + categories → Nutri-Score
packagings + origins → Eco-Score
product_name + brands + categories + labels → search _keywords
Pitfalls learned the hard way:
Free-text packaging shapes get fuzzy-matched against the taxonomy. "Pouch" resolves to "en:pouch-flask" (a stand-up spouted pouch). Use taxonomy IDs like "en:bag" or "en:individual-bag" instead.
OFF has no generic "pouch" shape in its taxonomy. For vacuum-sealed individual portions use "en:individual-bag"; for plastic film wrap use "en:film".
Recommended workflow for adding a product from photos:
Check if product exists with get_product first to avoid overwriting good data
Upload photos with upload_image. Prefer more photos over fewer — panels with text (ingredients, nutrition, certifications, recycling instructions) are highest value as OFF can OCR them. Plain sides with just a colour or logo are lowest value but still worth uploading if you have them. Use the most appropriate imagefield (front, ingredients, nutrition, packaging) and "other" for the rest.
Call this tool with all fields you can read from the photos. Set both quantity and serving_size.
Set packagings_complete: true only when all packaging components are listed
For products with only prepared nutrition (jelly mixes, powdered drinks, etc.), use nutrition_prepared instead of nutrition. For values printed as "< 0.5g" on the packet, pass the string "< 0.5" — the less-than modifier will be preserved.
Nutrition fields mirror the label columns: nutrition (per 100g as sold), nutrition_per_serving (per serving as sold), nutrition_prepared (per 100g prepared), nutrition_prepared_per_serving (per serving prepared). OFF auto-derives per-serving from per-100g + serving_size, so nutrition_per_serving is only needed when the label shows explicit per-serving values you want to preserve.
| Name | Required | Description | Default |
|---|---|---|---|
| brands | No | Brand name(s), comma-separated. For supermarket own-brands include both the sub-brand and the retailer, e.g. "The Fishmonger, Aldi" — this makes the product findable by either brand tag. Feeds search keywords. | |
| labels | No | Certifications, claims, and dietary marks, comma-separated, e.g. "Sustainable Seafood MSC, Vegan, High protein, No added sugar, Made in Scotland". OFF canonicalises these against its taxonomy. | |
| stores | No | Retailers where sold, comma-separated, e.g. "Aldi, Iceland". | |
| traces | No | "May contain" allergens, comma-separated, e.g. "en:nuts, en:peanuts, en:milk, en:sesame-seeds, en:soybeans". | |
| barcode | Yes | Product barcode (EAN-13, UPC-A, EAN-8, etc.). Required. If the product doesn't exist yet, it will be created. | |
| comment | No | Edit comment explaining what was changed, shown in product edit history. E.g. "Add nutrition data from packaging photo". | |
| origins | No | Where the ingredients come from, e.g. "Scotland" or "Northeast Pacific (FAO 67), Northwest Pacific (FAO 61)". Affects Eco-Score. | |
| language | No | Language code for language-dependent fields (product_name, generic_name, ingredients_text). Defaults to "en". Set to "fr" for French products, etc. This determines which language version of these fields is written. | en |
| quantity | No | Net quantity as printed, e.g. "400g", "6 x 330ml", "1L". OFF parses this into product_quantity automatically. Always set this — it is separate from serving_size and OFF will warn "quantity undefined" without it. | |
| allergens | No | Allergens, comma-separated, e.g. "en:gluten, en:milk". Usually auto-detected from ingredients_text underscores, so only set this if ingredients are unavailable. | |
| countries | No | Countries where sold, comma-separated, e.g. "United Kingdom, Ireland". | |
| emb_codes | No | Traceability/health marks — the oval stamp with a country code, e.g. "CN 2100/02398 EC" or "UK MD047 EC". Comma-separated if multiple. | |
| nutrition | No | Nutrition facts as sold, per 100g (or per 100ml for beverages). Transcribe per-100g values exactly as printed — don't back-calculate from per-serving. For values printed as "< 0.5g" on the packet, pass the string "< 0.5" — the less-than modifier will be preserved. | |
| categories | No | Categories, comma-separated, most general first, e.g. "Seafood, Fishes, Salmons, Frozen fishes". Feeds search keywords and enables category browsing. | |
| packagings | No | Structured packaging components. Each item describes one physical part of the packaging (outer box, inner bag, lid, etc.). This populates the packagings array the UI displays and feeds the Eco-Score. Use taxonomy IDs ("en:box") not free text. | |
| extra_fields | No | Raw form fields for anything else. Useful for less common nutriments (nutriment_sodium, nutriment_calcium, nutriment_vitamin-c) or fields not exposed above. Values are strings. | |
| generic_name | No | Legal name / product description, often found near the ingredients, e.g. "Carbonated no added sugar pineapple and grapefruit flavoured soft drink with sweeteners". Feeds search keywords. | |
| product_name | No | Product name as it should appear in search results. Start from what's printed on the front of pack, but include the product type if it's not in the headline but is integral to the product — e.g. pack says "Fajita Halloumi" but it's a wrap, so use "High Protein Fajita Halloumi Wrap". Feeds search keywords. | |
| serving_size | No | Serving size as printed, e.g. "30g", "100g (1 fillet)", "330ml (1 can)". OFF uses this to derive per-serving values from per-100g when per-serving values are not provided explicitly. | |
| packaging_text | No | Recycling instructions and/or packaging information as printed on the pack, e.g. "Tray - Plastic - Recycle\nFilm - Plastic - Do Not Recycle". This is the human-readable text, separate from the structured packagings array. | |
| ingredients_text | No | Full ingredients list verbatim from the pack. Mark allergens with underscores, e.g. "Wholegrain _Wheat_ (53%), _Wheat_ Protein, Sugar, _Barley_ Malt Extract". OFF parses this to detect allergens, additives, and compute NOVA group. Percentages matter for Nutri-Score fruit/veg estimation. | |
| nutrition_prepared | No | Nutrition facts as prepared, per 100g (or per 100ml). For products like jelly mixes, powdered drinks, instant noodles — anything where the packet shows separate "as prepared" nutrition values. | |
| packagings_complete | No | Set to true to mark that all packaging components have been listed. Only set this when you are confident the packagings array is complete. | |
| manufacturing_places | No | Where the product was made/packed, e.g. "Grimsby, United Kingdom". | |
| nutrition_per_serving | No | Nutrition facts as sold, per serving. Use this when the label shows a separate per-serving column alongside per-100g. If omitted and serving_size is set, OFF auto-derives per-serving from per-100g values. | |
| nutrition_prepared_per_serving | No | Nutrition facts as prepared, per serving. Use this when the label shows a separate per-serving column for prepared values. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors beyond the readOnlyHint annotation: it requires authentication, triggers derived data (allergens, NOVA, Nutri-Score, Eco-Score), handles fuzzy matching for packaging shapes, and auto-derives per-serving nutrition. No contradiction with annotations (readOnlyHint: false matches write operation).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with headers and bullet points, front-loading core purpose and requirements. However, it is lengthy and contains some repetition (e.g., packaging shape warning in pitfalls and schema field). Given the tool's complexity (26 params, nested objects), the length is mostly justified, but slight trimming could improve conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers prerequisites, workflow with siblings, pitfalls, field-level details, derived data, and special cases (prepared nutrition, '<' values). It lacks explicit mention of the response format (e.g., success/failure, product URL), but with no output schema, this is acceptable. Overall, it provides comprehensive context for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 100% schema coverage, the description adds significant value: explains why brands should include sub-brand/retailer, warns about quantity causing warnings, gives examples for nutrition '< 0.5' strings, and details packaging shape taxonomy pitfalls. It enriches understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Add a new product or edit an existing one on Open Food Facts,' clearly specifying the verb (add/edit), resource (product), and platform. This distinguishes it from sibling tools like get_product (read-only) and upload_image (photo upload).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive usage guidance: prerequisites (OFF_USER_ID, OFF_PASSWORD), recommended workflow (step 1: check with get_product, step 2: upload photos with upload_image, step 3: call this tool), and explicit when-to-use vs. when-not-to-use (e.g., only set packagings_complete when all components are listed). It also contrasts with siblings like get_product for checking existence.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
autocompleteAutocompleteARead-only
Get autocomplete suggestions for Open Food Facts taxonomy entries (brands, categories, labels, etc.).
| Name | Required | Description | Default |
|---|---|---|---|
| lc | No | Language code (default: en) | en |
| limit | No | Max results (default: 10, max: 100) | |
| query | Yes | Search prefix | |
| tagtype | Yes | Type of taxonomy to search |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only operation. Description adds no extra behavioral details like rate limits or error handling. Adequate for a simple read operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with purpose, no wasted words. Highly efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool is low complexity with no output schema. Description fully explains what it does. All critical info present. Minor gap: no mention of response format, but not required due to simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters are well-described in schema. Description adds only examples of tagtype values, no new semantic meaning beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'Get', resource 'autocomplete suggestions', and domain 'Open Food Facts taxonomy entries' with examples. Distinguishes from sibling search tools by focusing on taxonomy autocomplete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implied usage for autocomplete during input, but no explicit when-to-use or when-not-to-use compared to sibling search tools. No alternatives mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
call_apiCall APIA
Make a direct call to any Open Food Facts API endpoint. Use get_api_docs to see available endpoints. Auth credentials are included automatically for write operations if configured.
Two body modes for writes:
params: form-encoded (for /cgi/.pl and /api/v2/ legacy endpoints)
json_body: raw JSON (for /api/v3/* endpoints — required for structured fields like packagings)
Example v3 packagings write: method: PATCH endpoint: /api/v3/product/0123456789012 json_body: {"fields":"packagings","product":{"packagings":[{"number_of_units":1,"shape":{"id":"en:bag"},"material":{"id":"en:plastic"},"recycling":{"id":"en:recycle"}}]}}
WARNING: Do NOT use old-style prepared nutrition params like nutriment_fat_prepared — they have a known server bug that stores data incorrectly. Use new-style params instead: nutrition_input_sets_prepared_100g_nutrients_fat_value_string=0.5
| Name | Required | Description | Default |
|---|---|---|---|
| method | No | HTTP method (default: GET) | GET |
| params | No | Query parameters (for GET) or form-encoded body fields (for POST/PUT/PATCH to v1/v2 endpoints like /cgi/product_jqm2.pl). Auth fields are added automatically. | |
| endpoint | Yes | API endpoint path (e.g. "/api/v2/product/3017620422003.json") | |
| json_body | No | Raw JSON body for v3 endpoints (e.g. PATCH /api/v3/product/{code}). When set, params is ignored and Content-Type is application/json. Auth fields are injected at the top level. Use this for structured writes like packagings. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond annotations (which only indicate readOnlyHint=false) by detailing that auth credentials are included automatically for writes, explaining the two body modes with their respective endpoint types, and flagging a server bug. This provides rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: it starts with the main purpose, then provides usage details, a code example, and a warning. It is informative without being overly verbose, though the example could be slightly shortened. Overall, it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (generic API caller), the description covers essential aspects: endpoint usage, authentication, body modes, and a bug warning. No output schema exists, but for a general-purpose tool, the description is sufficiently complete for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, but the description adds significant value by clarifying the conditions for using params vs json_body (e.g., params for /cgi/*.pl and json_body for /api/v3/*), and including a concrete example for v3 packagings writes. This enhances understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Make a direct call to any Open Food Facts API endpoint', specifying the verb (call) and resource (any API endpoint). It differentiates from sibling tools like get_product or search_products, which are more specialized, making the tool's general-purpose nature obvious.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description advises to 'Use get_api_docs to see available endpoints' and explains two body modes for writes (params vs json_body). It also warns about a known server bug. While it doesn't explicitly state when to use alternative tools, the context is clear enough for an agent to decide.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_api_docsGet API docsARead-only
Get Open Food Facts API documentation. Useful for understanding available endpoints before using call_api.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, indicating read-only operation. The description adds that the tool provides documentation, which is consistent and adds context but no new behavioral traits beyond what annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence that is front-loaded and efficient, conveying purpose and usage context without extraneous words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, no output schema, and clear purpose tied to a sibling tool, the description provides complete context for an agent to select and invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters in input schema, so schema description coverage is 100%. Baseline score of 4 for zero parameters, no additional detail needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it gets Open Food Facts API documentation. The verb 'Get' and resource are specific. It distinguishes from sibling 'call_api' by noting its usefulness before using call_api.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Useful for understanding available endpoints before using call_api', providing clear context for when to use the tool. No exclusion criteria but enough guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_productGet productARead-only
Get product information from Open Food Facts by barcode. Reads the primary database directly (no sync lag), so this is always current even when search_products returns stale results. Prefer this over search whenever you have a barcode. If this returns "product not found", the product genuinely isn't in the database — you can add it with add_or_edit_product.
| Name | Required | Description | Default |
|---|---|---|---|
| fields | No | Fields to return. By default ALL fields are returned — nothing is omitted, so a field is never misleadingly null/absent just because it wasn't requested (e.g. `images` is always populated when the product has images). Pass an explicit list only to narrow the otherwise-verbose response. | |
| barcode | Yes | Product barcode (EAN-13, UPC-A, etc.) | |
| language | No | Language code for language-dependent fields (product_name, generic_name, ingredients_text). Defaults to "en". When a product has a different primary language, the unsuffixed field names return that language's data — this param ensures you get the language you want. | en |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true. Description adds valuable context: reads primary database (no sync lag), always current, and explains behavior on 'product not found'. Only lacks detail on exact return format.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each essential. Front-loaded with purpose, then usage guidance, then edge-case handling. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers key aspects: what the tool does, when to use, behavior on missing product, and parameter nuances. Lacks specification of return fields beyond examples in parameters, but overall adequate for tool usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%. Description enhances understanding: explains default behavior for 'fields' (all returned by default) and clarifies 'language' parameter's role in handling primary language. Adds value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves product information by barcode from Open Food Facts. It distinguishes itself from sibling tools like search_products and add_or_edit_product by emphasizing direct database reads and freshness.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance: 'Prefer this over search whenever you have a barcode' and explains fallback to add_or_edit_product if not found. No ambiguity about when to use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_skillGet skillARead-only
Get the OFF upload skill document. This describes the recommended process for bulk uploading food packaging photos to Open Food Facts.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true. The description adds that the result is a document describing a process, providing some behavioral context beyond the annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with the purpose. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, no output schema, and readOnly annotation, the description adequately explains the tool's purpose and the nature of the document for a simple retrieval operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has zero parameters, so baseline is 4. No additional parameter semantics needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves the OFF upload skill document, a specific resource. It distinguishes itself from sibling tools that deal with products, search, or images, as this focuses on a process document.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives like upload_image or add_or_edit_product. The description only defines what the tool does without context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_products_luceneSearch products (Lucene)ARead-only
Search Open Food Facts using the Search-a-licious Elasticsearch backend. Powered by Lucene query syntax with full boolean logic and negation support.
Use this instead of search_products_standard when you need:
Negation queries: find gluten-free cereals with allergens_tags_without="en:gluten"
Filter-only browsing: categories_tags without any text query (standard API times out on this)
Combined text + filter with relevance scoring: text matches are ranked by relevance within filter results
Boolean logic in raw Lucene: brands:"kellogg*" OR brands:"nestle"
Trade-offs vs search_products_standard:
Counts are approximate (capped at 10,000 for large result sets)
Brand tag matching may be narrower (less normalization than standard)
Data has a short sync delay (hours) from the primary database
popularity sort uses scan counts rather than the standard popularity algorithm
Response format matches search_products_standard: { count, page, page_size, page_count, products: [...] }
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (default: 1) | |
| query | No | Free-text search terms. Combined with any filter params using AND logic. Omit to browse by filters alone (unlike search_products_standard, filter-only queries work here without timeouts). | |
| fields | No | Fields to return per product. Defaults to: code, product_name, brands, categories, nutriscore_grade, nova_group, image_url, quantity | |
| sort_by | No | Sort order. Note: uses different underlying fields than search_products_standard. | |
| page_size | No | Results per page (default: 24, max: 100) | |
| brands_tags | No | Filter by brand tag (e.g. "nutella"). Added as brands_tags:"value" in the Lucene query. | |
| labels_tags | No | Filter by label tag (e.g. "en:organic", "en:fair-trade"). Added as labels_tags:"value". | |
| lucene_query | No | Raw Lucene query string for full control. If provided, all other filter params are ignored. Supports field:value, negation (-field:value), quoted phrases, wildcards. Examples: 'categories_tags:"en:beverages" nutriscore_grade:a -allergens_tags:"en:gluten"', 'brands:"kellogg*"' | |
| countries_tags | No | Filter by country tag (e.g. "en:united-kingdom", "en:france"). Added as countries_tags:"value". | |
| categories_tags | No | Filter by category tag (e.g. "en:breakfast-cereals"). Added as categories_tags:"value" in the Lucene query. | |
| sort_descending | No | Sort in descending order (default: true). Set false for ascending (e.g. lowest nutriscore_score first). | |
| nutrition_grades_tags | No | Filter by Nutri-Score grade (a, b, c, d, e). Added as nutriscore_grade:"value". | |
| allergens_tags_without | No | EXCLUDE products containing this allergen (e.g. "en:gluten", "en:milk"). This is negation — a capability unique to this tool. Added as -allergens_tags:"value". Use for allergen-free searches. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true. The description adds valuable behavioral details including approximate counts, sync delay, narrower brand matching, and sort differences, though does not mention pagination behavior explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with bullet points and a clear front-loaded purpose, but it is somewhat lengthy. Every sentence adds value, but slight trimming could improve conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 13 parameters with full schema coverage, no output schema, and simple annotations, the description sufficiently covers usage, trade-offs, and parameter details. It provides enough context for correct tool selection and use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%. The description adds meaningful context beyond the schema, such as explaining that allergens_tags_without performs negation and that lucene_query overrides other parameters, though the baseline is already high.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it searches Open Food Facts using Lucene query syntax with full boolean logic. It distinguishes from the sibling tool 'search_products_standard' by highlighting unique capabilities like negation and filter-only browsing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly lists four scenarios where this tool should be used instead of the standard alternative, and also details trade-offs such as approximate counts and sync delay, providing clear decision guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_products_standardSearch products (standard)ARead-only
Search Open Food Facts with structured filters. Best for simple keyword queries and brand/category filtering. Returns exact result counts and well-populated products. If you have a barcode, use get_product instead.
How search works: strict AND against a keyword index built from product_name, generic_name, brands, categories, origins, labels. One unmatched query word → zero results.
Tips:
Prefer 2-3 distinctive words over the full product name
Put brand names in brands_tags, not the query text
Brand normalization is generous: "sainsburys", "sainsbury's", "sainsbury-s" all match
For fresh produce, use brands_tags + categories_tags rather than text search
sort_by=popularity works well here (not supported in search_products_lucene)
If you get zero results, try dropping words or using search_products_lucene which has more flexible text matching.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (default: 1) | |
| query | No | Search terms. Strict AND: every word must exist in the product's indexed keywords, so prefer 2-3 distinctive words over the full product name. Use words as they appear on the pack (don't strip plurals or possessives — the search normalizes both sides). Put brand names in brands_tags instead of here. | |
| fields | No | Fields to return per product. Defaults to: code, product_name, brands, categories, nutriscore_grade, nova_group, image_url, quantity | |
| sort_by | No | Sort order | |
| page_size | No | Results per page (default: 24, max: 100) | |
| brands_tags | No | Filter by brand. Input is normalized, so "sainsburys", "sainsbury's", "sainsbury-s" all match the same brand — no need to know the exact tag slug. More reliable than putting the brand in the query text. | |
| categories_tags | No | Filter by category tag (e.g. "en:breakfast-cereals", "en:tomatoes"). Best way to find fresh produce: text-searching "banana" matches thousands of banana-flavoured products, but categories_tags "en:bananas" finds actual bananas. | |
| nutrition_grades_tags | No | Filter by Nutri-Score grade (a, b, c, d, e) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint annotation, the description details the strict AND search behavior, the index fields, normalization specifics, and tips for fresh produce. It fully discloses the query mechanics and potential pitfalls, giving the agent a thorough understanding of what to expect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (purpose, how search works, tips) and bullet points for clarity. While somewhat lengthy, every part adds useful information, and the structure makes it easy to scan. A minor deduction for length, but justified by the need to cover complex behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 8 parameters, no output schema, and multiple siblings, the description is thorough. It explains search mechanics, tips, and sibling differentiation. It could briefly note the pagination structure in the response, but the input schema covers page/page_size, and the focus is on usage optimization. Overall, it provides sufficient context for effective tool invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All parameters have schema descriptions (100% coverage), so baseline is 3. The description adds significant value by explaining the strict AND behavior for 'query', giving concrete examples for 'categories_tags' (en:bananas vs text search) and 'brands_tags' (normalization examples), and noting default fields. This enriches the schema's meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Search Open Food Facts with structured filters' and distinguishes from sibling tools like get_product (for barcode) and search_products_lucene (for flexible text matching). It provides a specific verb and resource along with use case differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises when to use: 'Best for simple keyword queries and brand/category filtering' and when not: 'If you have a barcode, use get_product instead'. Also includes fallback guidance: 'If you get zero results, try using search_products_lucene'. This provides clear context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
select_imageSelect/crop product imageA
Select, crop, and rotate a previously uploaded product image on Open Food Facts. Requires OFF_USER_ID and OFF_PASSWORD.
| Name | Required | Description | Default |
|---|---|---|---|
| lc | No | Language code (default: en) | en |
| x1 | No | Crop: left coordinate | |
| x2 | No | Crop: right coordinate | |
| y1 | No | Crop: top coordinate | |
| y2 | No | Crop: bottom coordinate | |
| angle | No | Rotation angle in degrees | |
| imgid | Yes | Image ID (from upload_image response or product data) | |
| barcode | Yes | Product barcode | |
| imagefield | Yes | Image type to assign this image to |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, confirming this is a write operation. The description adds actions (select, crop, rotate) but does not disclose additional behavioral traits such as whether it overwrites existing images or if the operation is reversible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, consisting of two sentences that convey the core actions and a requirement. It is front-loaded and contains no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 9 parameters, no output schema, and is a mutation, the description lacks details on the outcome (e.g., what is returned) and the prerequisite that a product with the given barcode must exist. However, the context of being used after upload_image is implied.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 9 parameters are fully described in the input schema with descriptions, so the description does not add extra meaning; it merely summarizes actions that map loosely to parameters. Baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's action (select, crop, rotate) and resource (previously uploaded product image) on Open Food Facts, distinguishing it from siblings such as upload_image for uploading and get_product for retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions requirement of authentication (OFF_USER_ID, OFF_PASSWORD) and implies the image must be previously uploaded, but lacks explicit guidance on when to choose this tool over alternatives like upload_image or crop functions in other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_imageUpload product imageA
Upload a product image to Open Food Facts. Requires OFF_USER_ID and OFF_PASSWORD.
Prefer more photos over fewer. Panels with text (ingredients, nutrition, certifications, recycling instructions) are highest value as OFF can OCR them. Plain sides with just a colour or logo are lowest value but still worth uploading if you have them.
Use the most appropriate imagefield (front, ingredients, nutrition, packaging). Use "other" for additional photos — this uploads without selecting the image as a display image, which is useful when a good display image already exists or for supplementary angles.
The OFF server auto-selects images for front/nutrition/ingredients/packaging on upload unless one is already selected. If you get "status not ok" but a positive imgid, the image uploaded successfully but was not selected (e.g. a display image already exists).
For images on disk, base64-encode them first (e.g. via shell: base64 -i photo.jpg).
| Name | Required | Description | Default |
|---|---|---|---|
| lc | No | Language code for the image (default: en) | en |
| barcode | Yes | Product barcode | |
| image_data | Yes | Base64-encoded image data (JPEG or PNG) | |
| imagefield | Yes | Image type |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses key behaviors beyond annotations: authentication requirements, auto-selection of images by the server, and handling of 'status not ok' with positive imgid. No contradiction with readOnlyHint=false, as upload is a write operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear paragraphs, each sentence contributing value. Slightly verbose but appropriate given the complexity; could be more concise but still effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description adequately covers authentication, parameter usage, server behaviors, and error handling. Leaves no significant gaps for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for all parameters. The description adds valuable context for 'imagefield' (usage guidance) and 'image_data' (encoding instruction), exceeding baseline expectations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool uploads a product image to Open Food Facts, with specific verb and resource. However, it does not explicitly distinguish from the sibling tool 'select_image', though it hints at image selection behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit prerequisites (OFF_USER_ID/OFF_PASSWORD), guidance on image quality and type prioritization, instruction on selecting the appropriate imagefield, and handling of auto-selection and error responses. This covers when and how to use the tool comprehensively.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v2.6.0- Changed
get_product1 field changed- changed
Input schema / properties / fields / descriptionPrevious value: -"Fields to return. Defaults to: product_name, brands, categories, nutriscore_grade, nova_group, ingredients_text, nutriments, serving_size, image_url, quantity, code"New value: +"Fields to return. By default ALL fields are returned — nothing is omitted, so a field is never misleadingly null/absent just because it wasn't requested (e.g. `images` is always populated when the product has images). Pass an explicit list only to narrow the otherwise-verbose response."
10 tool updates
v2.5.1- First observed
add_or_edit_product - First observed
autocomplete - First observed
call_api - First observed
get_api_docs - First observed
get_product - First observed
get_skill - First observed
search_products_lucene - First observed
search_products_standard - First observed
select_image - First observed
upload_image
TDQS
Scored across 10 tools
Most tools are clearly distinct (get vs search vs upload vs select), and the two search tools are explicitly differentiated by use case. However, add_or_edit_product vs upload_image and select_image overlap in the product-editing workflow, and call_api could be confused with get_api_docs or even the search tools for advanced users. Minor ambiguity but generally resolvable.
There's a reasonable pattern with verb_noun names (add_or_edit_product, get_product, upload_image, select_image), but 'autocomplete' and 'call_api' break the convention. Also search_products_standard vs search_products_lucene are verbose while others are concise.
10 tools for a food database MCP server is well-scoped, covering search, product management, and image handling. Though the list provided shows 8 tools, the count of 10 is still reasonable. Some tools like get_api_docs and get_skill are meta/helper tools but not excessive.
Core workflows are covered: search, get, add/edit, image upload/selection, plus a generic API escape hatch. Missing delete/obsolete operations and more granular taxonomy lookups, but the call_api and get_api_docs tools mitigate most gaps.
Maintenance
Related MCP Connectors
Unlock the power of food transparency with our Open Food Facts MCP server. Easily look up any food
MCP server for real-time product search by barcode (EAN, UPC, GTIN) or keyword on ean-search.org
Nutrition MCP — wraps Open Food Facts API (free, no auth)
USDA FoodData Central nutrient lookup, FDA recall watch, EU FMCG labelling via remote MCP
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for Open Food Facts, enabling food product lookup by barcode, search, nutrition facts, allergen checks, and eco-scores without an API key.8MIT
- FlicenseNot gradedqualityBmaintenanceMCP server for discovering and retrieving meal recipes from TheMealDB API, enabling search, random meals, category/ingredient filtering, and full recipe details.-
- AlicenseNot gradedqualityBmaintenanceAn MCP server for food-related queries powered by MiniMax AI, enabling natural language interaction via a chat API.30 npmMIT
- AlicenseNot gradedqualityAmaintenanceLook up food products by barcode, search by ingredient or nutrition filter, compare products side-by-side, and browse the canonical tag vocabulary via MCP.60 npm1Apache 2.0