Skip to main content
Glama

openfoodfacts-mcp-server

Browse Food Facts Taxonomy

off_browse_taxonomy
Read-onlyIdempotent

Resolve a human term to the canonical Open Food Facts tag ID that off_search_products filters on. Covers categories, labels/certifications, allergens, additives, countries, NOVA groups, and Nutri-Score grades. Pass a search term to resolve against the Open Food Facts vocabulary, which holds tens of thousands of tags; omitting it returns only a small reference list for each facet except NOVA groups and Nutri-Score grades, which are complete. Most tag IDs use the "en:" prefix (e.g. "en:organic", "en:no-gluten", "en:crustaceans"); NOVA groups return bare digits "1"-"4" and Nutri-Score grades bare letters "a"-"e". Pass the id through to off_search_products exactly as returned. Category tags are frequently plural ("kombucha" resolves to "en:kombuchas"), so use the returned id rather than constructing one.

Input Schema

NameRequiredDescriptionDefault
facetYes"categories" covers food categories (en:cheeses, en:breakfast-cereals). "labels" covers certifications (en:organic, en:fair-trade). "allergens" covers declared allergens (en:milk, en:gluten). "additives" covers E-numbers (en:e322). "countries" covers country-of-sale tags (en:france). "nova_groups" and "nutrition_grades" are closed vocabularies returned complete; the other five are resolved against the Open Food Facts taxonomy.
limitNoMaximum entries to return (default 20). One call returns at most 200: a larger value returns the first 200 and, when more matched, says how many did. There is no offset or page input: Open Food Facts offers no cursor for this lookup, so narrow the search term rather than paging. The tag spelling the term itself (e.g. "lentil" → en:lentils) is listed first among the live matches, so it is not the one a small limit cuts.
searchNoTerm to resolve. Matched case-insensitively as a substring of the tag ID, the display name, or a common synonym of either ("shellfish" resolves to en:crustaceans, "gluten free" to en:no-gluten). A single word works best ("hummus", not "hummus dip"). Omit only to see a small reference list — Open Food Facts cannot list the full vocabulary without a term, so an unfiltered call is not a view of the full facet.

Output Schema

NameRequiredDescriptionDefault
capNoThe limit that was applied — at most 200.
tagsNoMatching tag entries.
errorNoPresent when the call failed. Absent on success.
facetNoThe facet name that was queried (echoes the input).
shownNoNumber of tags returned.
noticeNoCaveat about the answer — that the listing is a limited reference list rather than the full vocabulary, that the live vocabulary could not be reached or gave no usable answer, that nothing matched and why, or that the limit cut matches, naming how many matched and the next call: a larger limit while one would list more, otherwise a narrower term, which is the only route past the first 200 (a limit above 200 is named too).
truncatedNoTrue when more tags exist beyond the limit.
total_in_facetNoTotal entries in this facet. Present only for nova_groups and nutrition_grades, whose vocabularies are closed and complete. Absent for the other facets: Open Food Facts reports no match total and cannot enumerate them, so no figure would be a real one.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum entries to return (default 20). One call returns at most 100: a larger value, up to 200 (the most suggestions one lookup reads), returns the first 100 and, when more matched, says how many did. There is no offset or page input: Open Food Facts offers no cursor for this lookup, so narrow the search term rather than paging. The tag spelling the term itself (e.g. \"lentil\" → en:lentils) is listed first among the live matches, so it is not the one a small limit cuts."New value: +"Maximum entries to return (default 20). One call returns at most 200: a larger value returns the first 200 and, when more matched, says how many did. There is no offset or page input: Open Food Facts offers no cursor for this lookup, so narrow the search term rather than paging. The tag spelling the term itself (e.g. \"lentil\" → en:lentils) is listed first among the live matches, so it is not the one a small limit cuts."
    • removedInput schema / properties / limit / maximum
      Removed value: -200
    • addedInput schema / properties / limit / multipleOf
      Added value: +1
    • changedInput schema / properties / limit / type
      Previous value: -"integer"New value: +"number"
    • changedOutput schema / properties / cap / description
      Previous value: -"The limit that was applied — at most 100."New value: +"The limit that was applied — at most 200."
    • changedOutput schema / properties / notice / description
      Previous value: -"Caveat about the answer — that the listing is a limited reference list rather than the full vocabulary, that the live vocabulary could not be reached or gave no usable answer, that nothing matched and why, or that the limit cut matches, naming how many matched and the next call: a larger limit while one would list more, otherwise a narrower term, which is the only route past the first 100 (a limit above 100 is named too)."New value: +"Caveat about the answer — that the listing is a limited reference list rather than the full vocabulary, that the live vocabulary could not be reached or gave no usable answer, that nothing matched and why, or that the limit cut matches, naming how many matched and the next call: a larger limit while one would list more, otherwise a narrower term, which is the only route past the first 200 (a limit above 200 is named too)."
  2. Changed4 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum entries to return (1–100, default 20). There is no offset or page input: Open Food Facts offers no cursor for this lookup, so narrow the search term rather than paging. The tag spelling the term itself (e.g. \"lentil\" → en:lentils) is listed first among the live matches, so it is not the one a small limit cuts."New value: +"Maximum entries to return (default 20). One call returns at most 100: a larger value, up to 200 (the most suggestions one lookup reads), returns the first 100 and, when more matched, says how many did. There is no offset or page input: Open Food Facts offers no cursor for this lookup, so narrow the search term rather than paging. The tag spelling the term itself (e.g. \"lentil\" → en:lentils) is listed first among the live matches, so it is not the one a small limit cuts."
    • changedInput schema / properties / limit / maximum
      Previous value: -100New value: +200
    • changedOutput schema / properties / cap / description
      Previous value: -"The limit that was applied."New value: +"The limit that was applied — at most 100."
    • changedOutput schema / properties / notice / description
      Previous value: -"Caveat about the answer — that the listing is a limited reference list rather than the full vocabulary, that Open Food Facts was unreachable, or that nothing matched and why."New value: +"Caveat about the answer — that the listing is a limited reference list rather than the full vocabulary, that the live vocabulary could not be reached or gave no usable answer, that nothing matched and why, or that the limit cut matches, naming how many matched and the next call: a larger limit while one would list more, otherwise a narrower term, which is the only route past the first 100 (a limit above 100 is named too)."
  3. Changed2 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum entries to return (1–100, default 20). There is no offset or page input: Open Food Facts returns only the first `limit` matches for a term and offers no cursor, so narrow the search term rather than paging."New value: +"Maximum entries to return (1–100, default 20). There is no offset or page input: Open Food Facts offers no cursor for this lookup, so narrow the search term rather than paging. The tag spelling the term itself (e.g. \"lentil\" → en:lentils) is listed first among the live matches, so it is not the one a small limit cuts."
    • removedOutput schema / properties / tags / items / properties / products
      Removed value: -{
      -  "description": "Approximate count of products with this tag. Not available for all facets.",
      -  "type": "number"
      -}
  4. Changed1 schema field changed
    • changedInput schema / properties / search / description
      Previous value: -"Term to resolve. Matched case-insensitively as a substring of the tag ID or display name. A single word works best (\"hummus\", not \"hummus dip\"). Omit only to see a small reference list — Open Food Facts cannot list the full vocabulary without a term, so an unfiltered call is not a view of the full facet."New value: +"Term to resolve. Matched case-insensitively as a substring of the tag ID, the display name, or a common synonym of either (\"shellfish\" resolves to en:crustaceans, \"gluten free\" to en:no-gluten). A single word works best (\"hummus\", not \"hummus dip\"). Omit only to see a small reference list — Open Food Facts cannot list the full vocabulary without a term, so an unfiltered call is not a view of the full facet."
  5. Changed11 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedInput schema / properties / facet / description
      Previous value: -"\"categories\" covers food categories (en:cheeses, en:breakfast-cereals). \"labels\" covers certifications (en:organic, en:fair-trade). \"allergens\" covers declared allergens (en:milk, en:gluten). \"additives\" covers E-numbers (en:e322). \"countries\" covers country-of-sale tags (en:france). \"nova_groups\" and \"nutrition_grades\" are closed vocabularies answered offline and returned complete; the other five are resolved against the live Open Food Facts taxonomy."New value: +"\"categories\" covers food categories (en:cheeses, en:breakfast-cereals). \"labels\" covers certifications (en:organic, en:fair-trade). \"allergens\" covers declared allergens (en:milk, en:gluten). \"additives\" covers E-numbers (en:e322). \"countries\" covers country-of-sale tags (en:france). \"nova_groups\" and \"nutrition_grades\" are closed vocabularies returned complete; the other five are resolved against the Open Food Facts taxonomy."
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum entries to return (1–100, default 20). There is no offset or page input: the upstream taxonomy endpoint serves only the first `limit` matches for a term and offers no cursor, so narrow the search term rather than paging."New value: +"Maximum entries to return (1–100, default 20). There is no offset or page input: Open Food Facts returns only the first `limit` matches for a term and offers no cursor, so narrow the search term rather than paging."
    • changedInput schema / properties / search / description
      Previous value: -"Term to resolve. Matched case-insensitively as a substring of the tag ID or display name, against both the live Open Food Facts vocabulary and this server's offline sample. A single word works best (\"hummus\", not \"hummus dip\"). Omit only to see the offline sample — the live vocabulary cannot be listed without a term, so an unfiltered call is not a view of the full facet."New value: +"Term to resolve. Matched case-insensitively as a substring of the tag ID or display name. A single word works best (\"hummus\", not \"hummus dip\"). Omit only to see a small reference list — Open Food Facts cannot list the full vocabulary without a term, so an unfiltered call is not a view of the full facet."
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "facet",
      +      "tags"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode.",
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / properties / notice / description
      Previous value: -"Caveat about how this answer was produced — that the listing is the offline sample rather than the live vocabulary, that the live vocabulary was unreachable, or that nothing matched and why."New value: +"Caveat about the answer — that the listing is a limited reference list rather than the full vocabulary, that Open Food Facts was unreachable, or that nothing matched and why."
    • changedOutput schema / properties / total_in_facet / description
      Previous value: -"Total entries in this facet. Present only for nova_groups and nutrition_grades, whose vocabularies are closed and complete here. Absent for the live facets: the Open Food Facts taxonomy endpoint reports no match total and cannot be enumerated, so no figure would be a real one."New value: +"Total entries in this facet. Present only for nova_groups and nutrition_grades, whose vocabularies are closed and complete. Absent for the other facets: Open Food Facts reports no match total and cannot enumerate them, so no figure would be a real one."
    • removedOutput schema / required
      Removed value: -[
      -  "facet",
      -  "tags"
      -]
  6. Changed6 schema fields changed
    • changedInput schema / properties / facet / description
      Previous value: -"\"categories\" covers food categories (en:cheeses, en:breakfast-cereals). \"labels\" covers certifications (en:organic, en:fair-trade). \"allergens\" covers declared allergens (en:milk, en:gluten). \"additives\" covers E-numbers (en:e322). \"countries\" covers country-of-sale tags (en:france). \"nova_groups\" and \"nutrition_grades\" return the complete fixed vocabularies."New value: +"\"categories\" covers food categories (en:cheeses, en:breakfast-cereals). \"labels\" covers certifications (en:organic, en:fair-trade). \"allergens\" covers declared allergens (en:milk, en:gluten). \"additives\" covers E-numbers (en:e322). \"countries\" covers country-of-sale tags (en:france). \"nova_groups\" and \"nutrition_grades\" are closed vocabularies answered offline and returned complete; the other five are resolved against the live Open Food Facts taxonomy."
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum entries to return (1–100, default 20). The categories facet is broad; a search term narrows it to the relevant tags."New value: +"Maximum entries to return (1–100, default 20). There is no offset or page input: the upstream taxonomy endpoint serves only the first `limit` matches for a term and offers no cursor, so narrow the search term rather than paging."
    • changedInput schema / properties / search / description
      Previous value: -"Case-insensitive substring filter against tag ID or display name. Example: \"gluten\" returns en:gluten, en:no-gluten. Omit to list all entries for the facet (may be large for categories)."New value: +"Term to resolve. Matched case-insensitively as a substring of the tag ID or display name, against both the live Open Food Facts vocabulary and this server's offline sample. A single word works best (\"hummus\", not \"hummus dip\"). Omit only to see the offline sample — the live vocabulary cannot be listed without a term, so an unfiltered call is not a view of the full facet."
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Caveat about how this answer was produced — that the listing is the offline sample rather than the live vocabulary, that the live vocabulary was unreachable, or that nothing matched and why.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / tags / items / properties / id / description
      Previous value: -"Canonical tag ID (e.g. \"en:organic\"). Use this value in off_search_products filter parameters."New value: +"Canonical tag ID (e.g. \"en:organic\"; bare \"1\"–\"4\" for NOVA groups, bare \"a\"–\"e\" for Nutri-Score grades). Pass this value through to the matching off_search_products filter parameter unchanged."
    • changedOutput schema / properties / total_in_facet / description
      Previous value: -"Total entries in this facet before search filtering. Large for categories."New value: +"Total entries in this facet. Present only for nova_groups and nutrition_grades, whose vocabularies are closed and complete here. Absent for the live facets: the Open Food Facts taxonomy endpoint reports no match total and cannot be enumerated, so no figure would be a real one."
  7. Changed1 schema field changed
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum entries to return (1–100, default 20). Categories has many entries — always provide a search term when browsing categories."New value: +"Maximum entries to return (1–100, default 20). The categories facet is broad; a search term narrows it to the relevant tags."
  8. Changed3 schema fields changed
    • addedOutput schema / properties / cap
      Added value: +{
      +  "description": "The limit that was applied.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / shown
      Added value: +{
      +  "description": "Number of tags returned.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when more tags exist beyond the limit.",
      +  "type": "boolean"
      +}
  9. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/openWorld, and the description still adds non-obvious behavior: the 200-entry cap with no offset or cursor, the ordering guarantee that the exact tag spelling comes first so a small limit won't cut it, and the split between closed vocabularies (NOVA, Nutri-Score) and the open taxonomy. These are operational traits an agent could not infer from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core resolution purpose and the downstream consumer, then layered with the operational caveats. Dense and mostly waste-free, though the list of covered facets overlaps with the facet enum's own descriptions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter read-only lookup with an output schema and full annotation coverage, the description covers the remaining unknowns: no pagination, the 200-result cap, id format, and how to narrow instead of page. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all three parameters; the description nonetheless adds meaning beyond it — the 'en:' prefix convention, bare digits '1'-'4' for NOVA and bare letters 'a'-'e' for Nutri-Score, and single-word query advice. The facet enumeration is partly restated from the schema, which keeps it from a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Resolve a human term to the canonical Open Food Facts tag ID') and explicitly ties the output to the sibling tool that consumes it ('that off_search_products filters on'). An agent can distinguish this resolver from off_search_products/off_get_product without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('Pass a search term to resolve'), when to omit it and what that yields, and a hard instruction to pass the returned id to off_search_products exactly rather than constructing one. It also anticipates the failure mode ('kombucha' → 'en:kombuchas') and tells the agent to trust the returned id.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.