Open Food Facts MCP
A read-only MCP server for looking up and comparing Open Food Facts product, search, and taxonomy data.
Look up a product by barcode (4–32 digits), with an optional language for localized results.
Search products by taxonomy filters — country, category, brand tags — plus Nutri-Score (a–e), with paging (page 1–1000, page_size 1–20).
Full-text search products with a query (up to 120 characters), also pageable.
Autocomplete taxonomies (categories, brands, countries, ingredients, additives, allergens, labels) with an optional result limit (1–20).
Compare 2–5 products at once by barcode, only when normalized nutrition basis and preparation state match.
Get provenance with every result: source URLs, retrieval time, cache status, missing fields, and warnings; nutrition keeps v3 aggregated values with basis and provenance separate from legacy
nutriments.Safe by design: read-only, non-destructive, idempotent — no editing records, uploading images, or health claims, and it respects Open Food Facts rate limits via built-in request limits and short-lived caches.
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., "@Open Food Facts MCPlook up the product with barcode 3017620422003"
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.
Open Food Facts MCP
Four tools are available. search_products is disabled and absent from MCP discovery. Filtered search by category, country, brand or Nutri-Score is unavailable. search_text provides text search and does not replace those filters.
A read-only Model Context Protocol server for querying Open Food Facts from MCP clients. This is an independent third-party project and is not affiliated with or endorsed by Open Food Facts.
The server requires Node.js 22.23 or newer, uses TypeScript and @modelcontextprotocol/server 2.0.0 with Zod 4, and communicates over MCP STDIO. It reads public product, search, and taxonomy data. It does not edit product records, upload images, or provide health claims.
Tools
Tool | Arguments |
|
|
|
|
|
|
|
|
See examples/tool-calls.json for argument examples and docs/architecture.md for the response contract, endpoints, nutrition handling, and request limits.
Related MCP server: @cyanheads/openfoodfacts-mcp-server
Run locally
This repository is not published as an npm package. Clone it, install dependencies, and run these checks from the checkout:
npm install
npm run typecheck
npm testBefore starting the server, set OFF_USER_AGENT to an application name and version followed by a monitored contact email:
export OFF_USER_AGENT='open-food-facts-mcp/0.1.0 (you@example.org)'
npm startReplace the example address with your contact. Open Food Facts requires a descriptive User-Agent that identifies the application and provides contact information. These read operations do not use an API key.
MCP client configuration
The server uses STDIO. Add an entry like this to your MCP client's configuration, replacing the checkout path and contact address:
{
"mcpServers": {
"open-food-facts": {
"command": "node",
"args": [
"--experimental-strip-types",
"/absolute/path/to/open-food-facts-mcp/src/index.ts"
],
"env": {
"OFF_USER_AGENT": "open-food-facts-mcp/0.1.0 (you@example.org)"
}
}
}
}Do not write logs to stdout in an MCP STDIO process; stdout carries protocol messages.
Data and responsible use
Open Food Facts is a community-built database. Its API documentation notes that product data can be incomplete or inaccurate. A missing field is not zero. An absent allergen entry does not establish that a product is allergen-free. Nutrition values can refer to 100 g, 100 ml, a portion, or a preparation state, so compare values only when their basis and preparation match.
Each successful response includes source URLs, retrieval time, cache status, missing fields, and warnings. Nutrition output keeps the v3 aggregated set and its basis alongside available input sets and provenance; legacy nutriments values remain separate. See the architecture notes for comparison behavior and limits.
Open Food Facts currently documents limits of 15 product reads and 10 search requests per minute per IP address. This server also applies in-process request limits and short-lived caches. Separate server processes sharing an IP do not coordinate their counters or caches. Avoid rapid repeated searches. For bulk, analytical, or offline access, follow Open Food Facts' guidance to use its data exports or a suitable local cache instead of repeatedly querying the API.
This software is licensed under MIT; see LICENSE. Open Food Facts data reuse has separate terms: the database is under ODbL, individual database contents under DbCL, and product images under CC BY-SA. These software and data licenses are independent. Read Open Food Facts' reuse terms before redistributing data or images.
Related projects
Other community projects in this area include domdomegg/openfoodfacts-mcp, cyanheads/openfoodfacts-mcp-server, and noot-app/openfoodfacts-mcp-server. This project's design focus is a compact read-only tool set with explicit v3.6 nutrition bases and provenance.
References
Apify Actor
An additional Streamable HTTP entry point is available for Apify Standby. See the Actor setup and English documentation for /mcp, authentication, deployment, local HTTP use, and operating limits. The original STDIO entry point remains available.
Available Tools
5 toolscompare_productsBRead-onlyIdempotent
Compare 2–5 products only when normalized nutrition basis and preparation match.
| Name | Required | Description | Default |
|---|---|---|---|
| barcodes | Yes | ||
| language | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | |
| source | Yes | |
| warnings | Yes | |
| cache_hit | Yes | |
| retrieved_at | Yes | |
| missing_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so the safety profile is covered. The description adds a useful domain constraint about comparability (basis/preparation must match), but says nothing about failure behavior when products are incomparable, rate limits, or scope.
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?
A single front-loaded sentence with the verb and cardinality first and the conditional constraint second — no filler. It is arguably too terse for a two-parameter tool with no schema documentation, which keeps it from a 5.
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?
An output schema exists, so return values need not be explained, and the comparability precondition is stated. But with 0% parameter coverage and two undocumented params, an agent still lacks enough to invoke confidently — the language parameter and barcode input format are unexplained.
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 description coverage is 0%, so the description carries the full burden, yet it only echoes the 2–5 count constraint already encoded in minItems/maxItems. It never states that the input is barcodes (the required array) or what the optional language parameter controls.
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 names a specific verb and resource ("Compare 2–5 products") and scopes the operation with a validity condition. It does not differentiate itself from siblings like get_product or search_products, so an agent must infer when comparison beats a simple lookup.
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?
It supplies a real precondition — only compare when normalized nutrition basis and preparation match — which is genuine usage guidance. However, it never names an alternative or says when not to use this tool versus search_products or get_product, leaving the sibling choice to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_productBRead-onlyIdempotent
Read one Open Food Facts product by barcode. Nutrition and allergen data are informational.
| Name | Required | Description | Default |
|---|---|---|---|
| barcode | Yes | ||
| language | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | |
| source | Yes | |
| warnings | Yes | |
| cache_hit | Yes | |
| retrieved_at | Yes | |
| missing_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds one genuinely new behavioral note — that nutrition/allergen data is informational — but says nothing about miss behavior for an unknown barcode or about the external-service nature beyond the openWorld hint.
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 tight sentences with the core action and key front-loaded and no filler. Slightly thin rather than padded, but 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?
An output schema exists, so return values need not be described, and annotations cover safety. What remains missing is the language parameter's effect and the not-found case, which is a modest gap for a simple single-record read.
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 description coverage is 0%, so the description carries the full burden. It hints that barcode is the lookup key but gives no format constraints, and the 'language' parameter is never mentioned anywhere, leaving half the parameters semantically undocumented.
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?
States a specific verb and resource ('Read one Open Food Facts product') and the lookup key ('by barcode'), which cleanly separates it from search_products and compare_products. It does not explicitly name those siblings, so it stops short of a 5.
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?
'Read one ... by barcode' implies the usage condition (you already have a barcode), but there is no explicit when-to-use/when-not statement and no routing to search_products for name or category lookups. Usage must be inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_taxonomyCRead-onlyIdempotent
Autocomplete an Open Food Facts taxonomy.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| language | No | ||
| taxonomy | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | |
| source | Yes | |
| warnings | Yes | |
| cache_hit | Yes | |
| retrieved_at | Yes | |
| missing_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds nothing beyond the verb: no result format, no behavior for unmatched queries, no note on the limit default or language fallback, so it earns little credit even against the lower annotated bar.
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?
A single front-loaded sentence with no waste, but it is terse to the point of under-specification for a four-parameter tool. Brevity here reflects omission rather than efficient editing.
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?
An output schema exists, so return values need not be explained, but with 0% schema coverage and no usage guidance the definition is not complete enough to call the tool confidently. Language handling and the meaning of the limit cap are left entirely to inference.
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 description coverage is 0%, so all four parameters (query, taxonomy, language, limit) rely on names alone. The description hints at the query/taxonomy pairing but adds no meaning for language matching rules or limit semantics, leaving the coverage gap uncompensated.
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?
States a specific verb (autocomplete) and resource (Open Food Facts taxonomy), which is clear enough to distinguish it from get_product and compare_products. However, it does not clearly separate itself from search_text, which could also be read as a text-autocomplete tool, so it falls short of full sibling 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?
There is no guidance on when to use this tool versus search_text or search_products, no mention of prerequisites, and no exclusions. The agent must infer the use case entirely from the one-line purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_productsCRead-onlyIdempotent
Search Open Food Facts products with documented taxonomy filters.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| brand | No | ||
| country | No | ||
| category | No | ||
| language | No | ||
| page_size | No | ||
| nutriscore | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | |
| source | Yes | |
| warnings | Yes | |
| cache_hit | Yes | |
| retrieved_at | Yes | |
| missing_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds nothing beyond that: no note on pagination behavior, result caps (page_size max 20, page max 1000), or that taxonomy values must be resolved first.
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?
A single short sentence with no padding and a clear front-loaded verb, but the brevity is under-specification rather than efficiency given the 7-parameter surface. It is structurally fine but leaves too much unsaid.
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?
An output schema and annotations exist, so return values and safety need not be described, but for a 7-parameter search with zero schema descriptions and no sibling differentiation the definition is materially incomplete. It omits filter semantics, pagination behavior, and the relationship to get_taxonomy.
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 description coverage is 0% across 7 parameters, so the description carries the full burden, yet it only alludes to 'taxonomy filters' generically. It never maps that phrase to brand/country/category, nor explains the regex/format constraints, page/page_size limits, or the nutriscore enum, leaving most parameters undocumented anywhere.
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 verb and resource are clear ('Search Open Food Facts products'), which is better than a tautology, but 'with documented taxonomy filters' is vague and does not distinguish this tool from the sibling search_text or get_taxonomy. An agent cannot tell from the description which search entry point to pick.
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?
There is no when-to-use guidance, no exclusions, and no mention of the sibling tools (search_text, get_product, compare_products). The phrase 'documented taxonomy filters' hints that filters must come from a taxonomy, but never says to call get_taxonomy first to obtain valid values.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_textCRead-onlyIdempotent
Full text product search via Search-a-licious.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| query | Yes | ||
| language | No | ||
| page_size | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | |
| source | Yes | |
| warnings | Yes | |
| cache_hit | Yes | |
| retrieved_at | Yes | |
| missing_fields | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered elsewhere. The description adds nothing beyond that — no pagination behavior, result caps (page_size max 20), rate limits, or what the search backend actually matches on.
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?
It is a single short, front-loaded clause with zero padding, which is structurally fine. But the brevity here is under-specification rather than discipline — the sentence is too thin for a 4-parameter search tool with siblings to disambiguate.
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?
An output schema exists, so return values need not be described. Still, for a tool with four undocumented parameters, an ambiguous sibling, and no stated scope or limits, the one-clause description leaves essential selection and invocation context missing.
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 description coverage is 0% across all four parameters (query, page, page_size, language), so the description carries the full burden and fails to explain any of them. "Full text" only loosely hints that query is free-text; page, page_size, and language get no mention at all.
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 gives a specific verb+resource ("Full text product search") and names the backing engine, so the basic operation is clear. However, it does nothing to distinguish this from the sibling tool search_products, which sounds like it does the same thing, leaving the agent to guess which one to call.
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?
There is no statement of when to use this tool versus search_products, get_product, or compare_products, and no prerequisites or exclusions. The presence of a near-identical sibling makes the absence of routing guidance a real gap.
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.
5 tool updates
v0.1.0- First observed
compare_products - First observed
get_product - First observed
get_taxonomy - First observed
search_products - First observed
search_text
TDQS
Scored across 5 tools
search_products (taxonomy filters) and search_text (full-text) overlap in that both search products, but the descriptions clearly delineate structured vs. free-text search; the other tools are distinct.
All tools use snake_case with a verb_noun structure (get_, search_, compare_), consistent throughout.
Five tools for a read-only product database API is well-scoped; each tool covers a distinct operation and none feel redundant.
The surface covers lookup, structured search, full-text search, taxonomy autocomplete, and comparison, which meets core read-only needs. Minor gaps might include batch retrieval or more taxonomy exploration, but no dead ends for typical queries.
Maintenance
Related MCP Connectors
Open Beauty Facts MCP — Open Beauty Facts API (free, no auth, keyless).
USDA FoodData Central nutrient lookup, FDA recall watch, EU FMCG labelling via remote MCP
Unlock the power of food transparency with our Open Food Facts MCP server. Easily look up any food
Look up a packaged food by barcode, search and compare products, and check listed allergens.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceProvides LLM agents with read-only access to FatSecret's food and recipe database through MCP tools for searching foods and retrieving detailed nutritional information.39 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.118 npm1Apache 2.0
- AlicenseAqualityBmaintenanceProvides read-only access to iFixit repair guides, device information, repairability scores, categories, search, media, and contributor profiles via MCP tools.8BSD Zero Clause
- AlicenseBqualityBmaintenanceEnables querying a global food nutrition database of generic and branded products, including search by name, lookup by barcode, and retrieval of resolved nutrient values pinned to a dated snapshot. Coverage spans USDA FoodData Central and Open Food Facts sources, with freshness health checks available.9AGPL 3.0