protogrid

Search / io.github.cyanheads/openfoodfacts-mcp-server

openfoodfacts-mcp-server

R0· no sign-in

Barcode lookup, nutrition search, and product comparison for 3M+ crowd-sourced food products.

v0.3.8 · active · repository · descriptor JSON · versions

An agent can connect right now, no human step.Remote endpoint, no authentication, reachable on the last probe.
Quality81good
Trust94of 100
Uptime, 30 days100%
Latency p50175 ms

Connect

8 clients · secrets stay placeholders
{
  "mcpServers": {
    "openfoodfacts-mcp-server": {
      "type": "http",
      "url": "https://openfoodfacts.caseyjhand.com/mcp"
    }
  }
}
claude mcp add --transport http openfoodfacts-mcp-server https://openfoodfacts.caseyjhand.com/mcp
[mcp_servers.openfoodfacts-mcp-server]
url = "https://openfoodfacts.caseyjhand.com/mcp"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "openfoodfacts-mcp-server": {
      "type": "remote",
      "url": "https://openfoodfacts.caseyjhand.com/mcp",
      "enabled": true
    }
  }
}
{
  "mcpServers": {
    "openfoodfacts-mcp-server": {
      "type": "http",
      "url": "https://openfoodfacts.caseyjhand.com/mcp"
    }
  },
  "deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=openfoodfacts-mcp-server&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vb3BlbmZvb2RmYWN0cy5jYXNleWpoYW5kLmNvbS9tY3AifQ%3D%3D"
}
{
  "servers": {
    "openfoodfacts-mcp-server": {
      "type": "http",
      "url": "https://openfoodfacts.caseyjhand.com/mcp"
    }
  }
}
{
  "mcpServers": {
    "openfoodfacts-mcp-server": {
      "httpUrl": "https://openfoodfacts.caseyjhand.com/mcp"
    }
  }
}
extensions:
  "openfoodfacts-mcp-server":
    enabled: true
    name: "openfoodfacts-mcp-server"
    type: streamable_http
    uri: "https://openfoodfacts.caseyjhand.com/mcp"
    timeout: 300

Quality 81 / 100good

protocol88 · weight 25
  • pass
    protocol.modernsupports 2026-07-28 (server/discover)
  • pass
    protocol.statelessanswers without a session
  • pass
    protocol.transportstreamable HTTP
  • warn
    protocol.list_ttltools/list declares ttlMs 0, so clients re-fetch it on every use
authorizationn/a · weight 15
  • n/a
    auth.prm, auth.as_metadata, auth.cimdno remote uses OAuth
  • n/a
    auth.secret_in_urlno templated URL
tool hygiene79 · weight 30
  • pass
    tools.descriptionsevery tool has a description
  • warn
    tools.description_length1 tools have descriptions over 1,024 characters, which crowds the context
  • pass
    tools.schemasevery tool has an object input schema
  • pass
    tools.annotations4 of 4 tools declare readOnlyHint or destructiveHint
  • fail
    tools.directory_hintsno tool declares all four of readOnlyHint, destructiveHint, idempotentHint and openWorldHint; missing: off_compare_products (destructiveHint); off_search_products (destructiveHint); off_get_product (destructiveHint); …
  • pass
    tools.token_costabout 4,349 tokens to load every tool
  • pass
    tools.api_dumptools are not a one-to-one API dump
stability75 · weight 15
  • warn
    stability.changes7 tool changes in 30 days
  • pass
    stability.rug_pullno tool changed its meaning under the same name
dependenciesn/a · weight 15

4 tools, about 4,349 tokens to load them all · tool set 27eb30f1a79f · tools last changed 2026-10-13 · checked 2026-10-19 10:52 UTC

Tool changes

  • off_browse_taxonomychangedinput schema, output schema
  • off_compare_productschangeddescription, input schema, output schema
    before

    Side-by-side nutrition and scoring comparison for 2–10 products by barcode. Returns a normalized table of energy (kcal/100g), fat, saturated fat, sugars, salt, protein, fiber, Nutri-Score, NOVA group, and Green-Score. Designed for "which of these cereals is healthiest?" or "compare these pasta brands" workflows. Missing nutrition data for any product is preserved as absent — comparisons are not imputed. A batch is not all-or-nothing: barcodes that resolve are returned even when others fail, with confirmed-missing barcodes listed in not_found and failed fetches listed separately in failed. Scores carry regional formula caveats. Data under ODbL 1.0 — cite Open Food Facts in downstream use.

    after · 77% of words in common

    Side-by-side nutrition and scoring comparison for 2–10 products per call by barcode; a repeated barcode is compared once, so two identical barcodes yield one row, and barcodes past the 10th distinct one are listed in unprocessed rather than fetched. Returns a normalized table of energy (kcal), fat, saturated fat, sugars, salt, protein, and fiber per 100 g, or per 100 ml for liquids, plus Nutri-Score, NOVA group, and Green-Score. Designed for "which of these cereals is healthiest?" or "compare these pasta brands" workflows. Missing nutrition data for any product is preserved as absent — comparisons are not imputed. A batch is not all-or-nothing: barcodes that resolve are returned even when others fail, with confirmed-missing barcodes listed in not_found and failed fetches listed separately in failed. Scores carry regional formula caveats. Data under ODbL 1.0 — cite Open Food Facts in downstream use.

  • off_search_productschangeddescription, input schema, output schema
    before

    Search Open Food Facts by full-text query, structured tag filters, or both at once. Returns a summary list with barcodes, product names, brands, Nutri-Score, NOVA group, and categories — enough for triage and selection, not full label data. Use off_get_product on the returned barcodes for complete details. A text query and tag filters combine: every word of the query must match the product name, generic name, categories, labels, or brand, and every filter provided must hold (e.g. query "dark chocolate" with labels_tag "en:organic" and countries_tag "en:france" returns organic chocolate sold in France); numeric nutrient_filters express per-100 g thresholds such as sugars below 8 g and combine the same way; additives_tag is the one exception, filtering only on searches carrying neither query nor nutrient_filters. Tag filter values are canonical tag IDs (e.g. "en:organic", "en:no-gluten") — use off_browse_taxonomy to resolve human terms to tag IDs. A case variant, synonym, or singular of a tag is resolved to its canonical ID where Open Food Facts recognizes it; anything else is matched exactly. exclude_allergens and exclude_traces drop products that declare an allergen or a "may contain" trace, but a product with no allergen or trace data entered passes them, so confirm a candidate with off_get_product before relying on it. At least one search parameter is required. The two paths read different indexes: a search carrying query is answered by the text index, a snapshot that lags the live database, while a tag-only search reads the live database and is current — so a recently contributed product can be missing from a text search and present in the same search without query. Data is crowd-sourced; result count reflects contributed products, not all products in the market. Data under ODbL 1.0 — cite Open Food Facts in downstream use.

    after · 95% of words in common

    Search Open Food Facts by full-text query, structured tag filters, or both at once. Returns a summary list with barcodes, product names, brands, Nutri-Score, NOVA group, and categories — enough for triage and selection, not full label data. Use off_get_product on the returned barcodes for complete details. A text query and tag filters combine: every word of the query must match the product name, generic name, categories, labels, or brand, and every filter provided must hold (e.g. query "dark chocolate" with labels_tag "en:organic" and countries_tag "en:france" returns organic chocolate sold in France); numeric nutrient_filters express thresholds per 100 g, or per 100 ml for liquids, such as sugars below 8 g, and combine the same way, and each row then carries the indexed values the thresholds were checked against; additives_tag is the one exception, filtering only on searches carrying neither query nor nutrient_filters. Tag filter values are canonical tag IDs (e.g. "en:organic", "en:no-gluten") — use off_browse_taxonomy to resolve human terms to tag IDs. A case variant, synonym, or singular of a tag is resolved to its canonical ID where Open Food Facts recognizes it; anything else is matched exactly. exclude_allergens and exclude_traces drop products that declare an allergen or a "may contain" trace, but a product with no allergen or trace data entered passes them, so confirm a candidate with off_get_product before relying on it. At least one search parameter is required. The two paths read different indexes: a search carrying query is answered by the text index, a snapshot that lags the live database, while a tag-only search reads the live database and is current — so a recently contributed product can be missing from a text search and present in the same search without query. Data is crowd-sourced; result count reflects contributed products, not all products in the market. Data under ODbL 1.0 — cite Open Food Facts in downstream use.

  • off_get_productchangeddescription, output schema
    before

    Fetch a packaged food product by barcode (4–40 digits: EAN-13, EAN-8, UPC, and the shorter and longer codes Open Food Facts also holds) from Open Food Facts. Returns the product name, brand, quantity, ingredients (raw text and parsed list), declared allergens, trace allergens the label warns about, additives, the product-level vegan/vegetarian/palm-oil analysis, computed scores (Nutri-Score a–e, NOVA 1–4, Green-Score), nutrition per 100g and per serving, categories, labels, packaging, origins, countries of sale, image URL, and data completeness. Open Food Facts is a crowd-sourced database — a missing field means "not yet entered by contributors," not that the attribute is absent from the actual product. Computed scores carry regional formula caveats and are indicators, not absolute rankings. Data is under ODbL 1.0 — cite Open Food Facts in downstream use.

    after · 93% of words in common

    Fetch a packaged food product by barcode (4–40 digits: EAN-13, EAN-8, UPC, and the shorter and longer codes Open Food Facts also holds) from Open Food Facts. Returns the product name, brand, quantity, ingredients (raw text and parsed list), declared allergens, trace allergens the label warns about, additives, the product-level vegan/vegetarian/palm-oil analysis, computed scores (Nutri-Score a–e, NOVA 1–4, Green-Score), nutrition per serving and per 100 g, or per 100 ml for liquids, categories, labels, packaging, origins, countries of sale, image URL, and data completeness. Open Food Facts is a crowd-sourced database — a missing field means "not yet entered by contributors," not that the attribute is absent from the actual product. Computed scores carry regional formula caveats and are indicators, not absolute rankings. Data is under ODbL 1.0 — cite Open Food Facts in downstream use.

  • off_compare_productschangedoutput schema
  • off_search_productschangedoutput schema
  • off_get_productchangedoutput schema

Full history: list_changes · trend: quality JSON.

Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.

Trust 94 / 100

provenance80
liveness100
freshness100
hygiene100

+repository +namespace-matches-repo +reachable +uptime-100% +updated-6d-ago

Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.

Dependencies

@cyanheads/[email protected] npmthis version is not known to the dependency resolver

@cyanheads/[email protected] npmthis version is not known to the dependency resolver

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0. The graph is what a clean install of this version resolves today; nothing was installed or run. How it is checked.

Endpoints

remoteauthreachableuptime 30dp50protocollast ok
https://openfoodfacts.caseyjhand.com/mcp streamable-httpnoneyes100%175 ms2026-07-282026-10-19
packageregistryversionruntimesecrets
@cyanheads/openfoodfacts-mcp-servernpm0.3.8npx
@cyanheads/openfoodfacts-mcp-servernpm0.3.8npx

Tools (4)

off_browse_taxonomyread-onlyResolve 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.
off_compare_productsread-onlySide-by-side nutrition and scoring comparison for 2–10 products per call by barcode; a repeated barcode is compared once, so two identical barcodes yield one row, and barcodes past the 10th distinct one are listed in unprocessed rather than fetched. Returns a normalized table of energy (kcal), fat, saturated fat, sugars, salt, protein, and fiber per 100 g, or per 100 ml for liquids, plus Nutri-Score, NOVA group, and Green-Score. Designed for "which of these cereals is healthiest?" or "compare these pasta brands" workflows. Missing nutrition data for any product is preserved as absent — comparisons are not imputed. A batch is not all-or-nothing: barcodes that resolve are returned even when others fail, with confirmed-missing barcodes listed in not_found and failed fetches listed separately in failed. Scores carry regional formula caveats. Data under ODbL 1.0 — cite Open Food Facts in downstream use.
off_get_productread-onlyFetch a packaged food product by barcode (4–40 digits: EAN-13, EAN-8, UPC, and the shorter and longer codes Open Food Facts also holds) from Open Food Facts. Returns the product name, brand, quantity, ingredients (raw text and parsed list), declared allergens, trace allergens the label warns about, additives, the product-level vegan/vegetarian/palm-oil analysis, computed scores (Nutri-Score a–e, NOVA 1–4, Green-Score), nutrition per serving and per 100 g, or per 100 ml for liquids, categories, labels, packaging, origins, countries of sale, image URL, and data completeness. Open Food Facts is a crowd-sourced database — a missing field means "not yet entered by contributors," not that the attribute is absent from the actual product. Computed scores carry regional formula caveats and are indicators, not absolute rankings. Data is under ODbL 1.0 — cite Open Food Facts in downstream use.
off_search_productsread-onlySearch Open Food Facts by full-text query, structured tag filters, or both at once. Returns a summary list with barcodes, product names, brands, Nutri-Score, NOVA group, and categories — enough for triage and selection, not full label data. Use off_get_product on the returned barcodes for complete details. A text query and tag filters combine: every word of the query must match the product name, generic name, categories, labels, or brand, and every filter provided must hold (e.g. query "dark chocolate" with labels_tag "en:organic" and countries_tag "en:france" returns organic chocolate sold in France); numeric nutrient_filters express thresholds per 100 g, or per 100 ml for liquids, such as sugars below 8 g, and combine the same way, and each row then carries the indexed values the thresholds were checked against; additives_tag is the one exception, filtering only on searches carrying neither query nor nutrient_filters. Tag filter values are canonical tag IDs (e.g. "en:organic", "en:no-gluten") — use off_browse_taxonomy to resolve human terms to tag IDs. A case variant, synonym, or singular of a tag is resolved to its canonical ID where Open Food Facts recognizes it; anything else is matched exactly. exclude_allergens and exclude_traces drop products that declare an allergen or a "may contain" trace, but a product with no allergen or trace data entered passes them, so confirm a candidate with off_get_product before relying on it. At least one search parameter is required. The two paths read different indexes: a search carrying query is answered by the text index, a snapshot that lags the live database, while a tag-only search reads the live database and is current — so a recently contributed product can be missing from a text search and present in the same search without query. Data is crowd-sourced; result count reflects contributed products, not all products in the market. Data under ODbL 1.0 — cite Open Food Facts in downstream use.

Schemas: list_tools.

Similar MCP servers

More from io.github.cyanheads

And 136 more from this publisher.

Official server.json
{
  "name": "io.github.cyanheads/openfoodfacts-mcp-server",
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "remotes": [
    {
      "url": "https://openfoodfacts.caseyjhand.com/mcp",
      "type": "streamable-http"
    }
  ],
  "version": "0.3.8",
  "packages": [
    {
      "version": "0.3.8",
      "transport": {
        "type": "stdio"
      },
      "identifier": "@cyanheads/openfoodfacts-mcp-server",
      "runtimeHint": "npx",
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "environmentVariables": [
        {
          "name": "OFF_BASE_URL",
          "format": "string",
          "default": "https://world.openfoodfacts.org",
          "description": "Open Food Facts API base URL override. Useful for testing against a mock server."
        },
        {
          "name": "OFF_RATE_LIMIT_PRODUCT",
          "format": "string",
          "default": "15",
          "description": "Product read rate limit (requests/min). Matches the 15 req/min/IP Open Food Facts documents for product reads."
        },
        {
          "name": "OFF_RATE_LIMIT_SEARCH",
          "format": "string",
          "default": "10",
          "description": "Search rate limit (requests/min)."
        },
        {
          "name": "OFF_RATE_LIMIT_TAXONOMY",
          "format": "string",
          "default": "10",
          "description": "Taxonomy resolution rate limit (requests/min). Applies to the live tag-vocabulary lookups off_browse_taxonomy makes, to tag-value resolution on text searches, and to checking allergen and trace exclusions on every search; a spent budget falls back to the offline sample, or to the tag value as normalized, rather than failing, except that an exclusion it could not check is refused as retryable."
        },
        {
          "name": "MCP_LOG_LEVEL",
          "format": "string",
          "default": "info",
          "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn')."
        }
      ]
    },
    {
      "version": "0.3.8",
      "transport": {
        "url": "http://localhost:3010/mcp",
        "type": "streamable-http"
      },
      "identifier": "@cyanheads/openfoodfacts-mcp-server",
      "runtimeHint": "npx",
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "environmentVariables": [
        {
          "name": "MCP_TRANSPORT_TYPE",
          "value": "http",
          "format": "string",
          "description": "Selects the HTTP transport."
        },
        {
          "name": "OFF_BASE_URL",
          "format": "string",
          "default": "https://world.openfoodfacts.org",
          "description": "Open Food Facts API base URL override. Useful for testing against a mock server."
        },
        {
          "name": "OFF_RATE_LIMIT_PRODUCT",
          "format": "string",
          "default": "15",
          "description": "Product read rate limit (requests/min). Matches the 15 req/min/IP Open Food Facts documents for product reads."
        },
        {
          "name": "OFF_RATE_LIMIT_SEARCH",
          "format": "string",
          "default": "10",
          "description": "Search rate limit (requests/min)."
        },
        {
          "name": "OFF_RATE_LIMIT_TAXONOMY",
          "format": "string",
          "default": "10",
          "description": "Taxonomy resolution rate limit (requests/min). Applies to the live tag-vocabulary lookups off_browse_taxonomy makes, to tag-value resolution on text searches, and to checking allergen and trace exclusions on every search; a spent budget falls back to the offline sample, or to the tag value as normalized, rather than failing, except that an exclusion it could not check is refused as retryable."
        },
        {
          "name": "MCP_HTTP_HOST",
          "format": "string",
          "default": "127.0.0.1",
          "description": "The hostname for the HTTP server."
        },
        {
          "name": "MCP_HTTP_PORT",
          "format": "string",
          "default": "3010",
          "description": "The port to run the HTTP server on."
        },
        {
          "name": "MCP_HTTP_ENDPOINT_PATH",
          "format": "string",
          "default": "/mcp",
          "description": "The endpoint path for the MCP server."
        },
        {
          "name": "MCP_AUTH_MODE",
          "format": "string",
          "default": "none",
          "description": "Authentication mode to use: 'none', 'jwt', or 'oauth'."
        },
        {
          "name": "MCP_LOG_LEVEL",
          "format": "string",
          "default": "info",
          "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn')."
        }
      ]
    }
  ],
  "repository": {
    "url": "https://github.com/cyanheads/openfoodfacts-mcp-server",
    "source": "github"
  },
  "description": "Barcode lookup, nutrition search, and product comparison for 3M+ crowd-sourced food products."
}