Nutrition data for people and agents.

A read-only JSON API, a CLI, an MCP server, and an agent skill over about 1.9 million packaged foods from Open Food Facts. There are no API keys or accounts, and every call is a plain GET.

Install

curl -sSL https://nutrition.sh/install | bash

Linux on x86_64 or arm64 gets a static binary, verified by checksum. Anything else builds from source if cargo is installed. The binary is called food and lands in /usr/local/bin or ~/.local/bin.

food

A CLI that prints JSON when piped and a table when you are looking.

food mcp

The same binary as an MCP server, so agents get typed tools.

skill

One file that teaches agents the workflow and how to read the numbers.

CLI

Search first, then fetch one product by its code. Search returns summaries; the detail call returns the nutrients, ingredients, and tags.

# text search, ranked by relevance
food search "dark chocolate"

# filters combine with AND; tags use Open Food Facts form
food search chocolate --category en:snacks --nutriscore a --limit 5

# nutrient ranges are per 100 g
food search --nutrient sugars --max 5

# one product, everything the dataset knows
food get 0081014090553

# which nutrient names exist
food nutrients vitamin

Output is the raw API JSON whenever stdout is a pipe or a file, so food get 0081014090553 | jq .nutrients needs no flag. On a terminal you get a readable table instead. --json and --table force either. --pages 3 follows the cursor and merges three pages.

food search "greek yogurt" --nutriscore a --limit 2 | jq -c '.data[] | {code, name, brands}'
{"code":"5051898781057","name":"Tesco Fat Free Greek Yogurt 200G","brands":"Tesco"}
{"code":"4088600073321","name":"Brooklea Greek 0% Fat Yogurt with Raspberry","brands":"Brooklea, Aldi"}

MCP

The same binary runs a Model Context Protocol server over stdio. Register it with Claude Code in one line:

claude mcp add food -- food mcp

Or add it to any MCP client configuration:

{ "mcpServers": { "food": { "command": "food", "args": ["mcp"] } } }
ToolWhat it does
search_productsText search plus every filter as an optional typed argument. Returns summaries and a cursor.
get_productFull detail for one code: nutrients, ingredients, localized names, tags, scores.
list_nutrientsValid nutrient identifiers with unit, product count, and observed range.
get_dataset_statusProduct count, schema version, and whether the import is complete.

Tool results are the API's JSON. API errors come back as tool errors carrying the API's code and message, which lets the model recover. The server's own instructions cover tag formats, units, and paging, so agents need no extra prompting.

Skill

A skill teaches an agent when to use the CLI and how to read the data: the search-then-get workflow, tag formats, paging, and the unit rules below. It installs into Claude Code, Cursor, Codex, and most other agents with one command:

npx skills add https://nutrition.sh/skill.tar.gz

Add -g to install it globally instead of into the current project. The skill prefers the MCP tools when they are present and falls back to the CLI, so you can install both. Read it at skills/food/SKILL.md.

HTTP API

Base URL https://nutrition.sh. Every endpoint is a GET that returns JSON. The full contract is in openapi.yaml.

PathPurpose
/api/v1/productsBrowse, search, and filter products
/api/v1/products/{code}One complete product
/api/v1/nutrientsThe nutrient catalog
/api/v1Dataset and schema metadata
/healthReadiness and product count
curl 'https://nutrition.sh/api/v1/products?q=peanut%20butter&nutriscore_grade=a&limit=2'
{
  "data": [
    {
      "code": "0068100084665",
      "name": "PEANUT BUTTER",
      "brands": "ONLY PEANUTS Kraft",
      "nutriscore_grade": "a",
      "nova_group": 2,
      ...
    }
  ],
  "page": { "limit": 2, "next_cursor": "fts:2" }
}

Filters

All parameters are optional and combine with AND.

ParameterMeaning
qPrefix search over names, brands, and ingredients. Every word must match.
brand, category, country, label, allergenExact normalized tags such as en:snacks, en:organic, en:milk
nutriscore_gradea through e
nova_group1 through 4
nutrient, min_per_100g, max_per_100gInclusive range on one nutrient, for example sugars or energy-kcal
limit, cursorPage size 1 to 100, and the opaque next_cursor from the previous page

Units

Each nutrient record carries two units. unit belongs to value, the number as printed on the package. per_100g_unit belongs to per_100g and per_serving, normalized the way Open Food Facts stores them: grams for mass nutrients, kJ for energy, kcal for energy-kcal.

{ "name": "cholesterol", "unit": "mg", "value": 70, "per_100g_unit": "g", "per_100g": 0.0625, "per_serving": 0.07 }

Errors

Errors share one envelope. 400 for a bad parameter or cursor, 404 for an unknown code, 500 if the database or search fails.

{ "error": { "code": "bad_request", "message": "min_per_100g and max_per_100g require nutrient" } }