@cyanheads/openfoodfacts-mcp-server 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +12 -9
  4. package/changelog/0.4.x/0.4.1.md +30 -0
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.d.ts.map +1 -1
  8. package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.js +12 -7
  9. package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.js.map +1 -1
  10. package/dist/mcp-server/tools/definitions/compare-products.tool.d.ts +17 -6
  11. package/dist/mcp-server/tools/definitions/compare-products.tool.d.ts.map +1 -1
  12. package/dist/mcp-server/tools/definitions/compare-products.tool.js +96 -61
  13. package/dist/mcp-server/tools/definitions/compare-products.tool.js.map +1 -1
  14. package/dist/mcp-server/tools/definitions/get-product.tool.d.ts +2 -2
  15. package/dist/mcp-server/tools/definitions/get-product.tool.d.ts.map +1 -1
  16. package/dist/mcp-server/tools/definitions/get-product.tool.js +73 -28
  17. package/dist/mcp-server/tools/definitions/get-product.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/definitions/index.d.ts +22 -10
  19. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/search-products.tool.d.ts +3 -2
  21. package/dist/mcp-server/tools/definitions/search-products.tool.d.ts.map +1 -1
  22. package/dist/mcp-server/tools/definitions/search-products.tool.js +104 -43
  23. package/dist/mcp-server/tools/definitions/search-products.tool.js.map +1 -1
  24. package/dist/services/openfoodfacts/openfoodfacts-service.d.ts +14 -14
  25. package/dist/services/openfoodfacts/openfoodfacts-service.d.ts.map +1 -1
  26. package/dist/services/openfoodfacts/openfoodfacts-service.js +205 -78
  27. package/dist/services/openfoodfacts/openfoodfacts-service.js.map +1 -1
  28. package/dist/services/openfoodfacts/types.d.ts +27 -4
  29. package/dist/services/openfoodfacts/types.d.ts.map +1 -1
  30. package/dist/services/openfoodfacts/types.js +15 -0
  31. package/dist/services/openfoodfacts/types.js.map +1 -1
  32. package/dist/services/taxonomy/taxonomy-service.d.ts.map +1 -1
  33. package/dist/services/taxonomy/taxonomy-service.js +12 -10
  34. package/dist/services/taxonomy/taxonomy-service.js.map +1 -1
  35. package/package.json +3 -3
  36. package/server.json +3 -3
  37. package/skills/openfoodfacts-guide/SKILL.md +2 -2
package/AGENTS.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** openfoodfacts-mcp-server
4
- **Version:** 0.4.0
4
+ **Version:** 0.4.1
5
5
  **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.4.0
package/CLAUDE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** openfoodfacts-mcp-server
4
- **Version:** 0.4.0
4
+ **Version:** 0.4.1
5
5
  **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.18`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.4.0
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.4.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/openfoodfacts-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.4.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/openfoodfacts-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openfoodfacts-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.4-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.4.1-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/openfoodfacts-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.4.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/openfoodfacts-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openfoodfacts-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.4-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -50,16 +50,18 @@ Packaged-food data from Open Food Facts, a crowd-sourced database of 3M+ product
50
50
 
51
51
  ### `off_get_product` <sub>tool</sub>
52
52
 
53
- - `barcode` is digits only, 4–40 digits after any leading zeros; optional `fields` trims the response and pulls in what a field depends on (`nutriments` brings the serving size), with `requested_fields` echoing what was fetched
53
+ - `barcode` is digits only, 4–40 digits after any leading zeros; optional `fields` trims the response and pulls in what a field depends on (`nutriments` brings the serving size, quantity, and unit, and `serving_quantity` and `serving_quantity_unit` each bring the other plus the serving size), with `requested_fields` echoing what was fetched
54
54
  - Returns ingredients (raw text plus a parsed tree up to three levels deep with `percent_estimate`), `allergens_tags`, `traces_tags`, `additives_tags`, `ingredients_analysis_tags` (vegan, vegetarian, palm-oil verdicts), `nutriscore_grade`, `nova_group`, `ecoscore_grade` (Green-Score), `nutriments` (per serving, and per 100 g, or per 100 ml for liquids), category/label/packaging/origin/country tags, `image_url`, and `completeness` (0–1)
55
55
  - `traces_tags: ["en:none"]` means the label states no traces, while an empty array means none entered yet; a barcode no contributor has recorded fails as `not_found`
56
+ - Open Food Facts returns one preparation state of the nutrition per read. A read of prepared-product figures puts them under keys ending in `_prepared` in `additional_100g` and `additional_serving`, prints them in "as prepared" sections, and leaves the named as-sold nutrient fields absent; the text says the read returned only prepared figures, not that the record holds no as-sold ones
56
57
 
57
58
  ---
58
59
 
59
60
  ### `off_search_products` <sub>tool</sub>
60
61
 
61
62
  - `query` (up to 24 words, all of which must match the name, generic name, categories, labels, or brand; punctuation separates words, so `milk-chocolate` requires both) plus the tag filters `categories_tag`, `brands_tag`, `labels_tag` (up to 10), `allergens_tag`, `traces_tag`, `ingredients_analysis_tag`, `additives_tag`, `nutrition_grade`, `nova_group`, `countries_tag`, the `exclude_allergens` / `exclude_traces` lists (up to 14 each), and up to 18 `nutrient_filters` (per 100 g, or per 100 ml for liquids), all combined as AND; optional `sort_by`
62
- - `page_size` defaults to 20 and is served at up to 50 per call; a larger value (up to 10,000) is served at 50 and flagged in `page_size_capped`, and `page` counts pages of 50. Rows carry `barcode`, `product_name`, `brands`, `nutriscore_grade`, `nova_group`, `ecoscore_grade`, and `categories_tags`, plus `total`, `total_is_lower_bound`, `last_page`, `omitted`, and `truncated` (more matches beyond this page). Exclusions add `exclusion_coverage`, since products with no allergen data entered pass them; `nutrient_filters` add `indexed_nutriments` (the index values the filters checked, which can differ from `off_get_product`)
63
+ - `page_size` defaults to 20 and is served at up to 50 per call; a larger value, with no ceiling, is served at 50 and flagged in `page_size_capped`, and `page` counts pages of 50. Rows carry `barcode`, `product_name`, `brands`, `nutriscore_grade`, `nova_group`, `ecoscore_grade`, and `categories_tags`, plus `total`, `total_is_lower_bound`, `last_page`, `omitted`, and `truncated` (more matches beyond this page). Exclusions add `exclusion_coverage`, since products with no allergen data entered pass them; `nutrient_filters` add `indexed_nutriments` (the index values the filters checked, which can differ from `off_get_product`)
64
+ - The text index compares `energy-kcal`, `fat`, `saturated-fat`, `carbohydrates`, and `sugars` as whole numbers (`sugars lte 3` returns a row at 3.53). A `nutrient_filters` search sends `gt` and `gte` on those five as `[floor(value) TO *]` so no match is lost, then checks every returned row against every constraint at the index's 32-bit precision. Rows that fail leave the page and count in `outside_constraints`, so a page can come back short or empty while later pages hold matches. `total`, `total_is_lower_bound`, and `last_page` describe the index's whole-number answer and still count those rows. A range inside one whole number (`sugars gt 3.9` and `lt 4`) can pass few of the 10,000 reachable rows; add `query` or tag filters to narrow it
63
65
  - `query` or `nutrient_filters` searches a text index that lags the live database (flagged in `text_index_snapshot`), reaches only the first 10,000 results, and rejects `additives_tag` as `additives_filter_needs_tag_search`; tag-only searches read the live database through page 10. A page past either limit fails as `page_out_of_range`
64
66
 
65
67
  ---
@@ -67,14 +69,15 @@ Packaged-food data from Open Food Facts, a crowd-sourced database of 3M+ product
67
69
  ### `off_compare_products` <sub>tool</sub>
68
70
 
69
71
  - 2–100 `barcodes`, one row each in input order; repeated barcodes are compared once, and those past the 10th distinct one are listed in `unprocessed` without being fetched
70
- - Rows carry `found`, `nutriscore_grade`, `nova_group`, `ecoscore_grade`, energy, fat, saturated fat, sugars, salt, protein, and fiber (per 100 g, or per 100 ml for liquids), and `completeness`; missing values stay absent, never imputed
72
+ - Rows carry `found`, `nutriscore_grade`, `nova_group`, `ecoscore_grade`, energy, fat, saturated fat, carbohydrates, sugars, salt, protein, and fiber (per 100 g, or per 100 ml for liquids), and `completeness`; missing values stay absent, never imputed
73
+ - A read of prepared-product figures adds a `prepared` object on the row with the same columns, read from the `*_prepared_100g` keys and never substituted for an as-sold figure. A row with as-sold figures appears in the as-sold table, a row with `prepared` in the "as prepared" table, and a row with both appears in both
71
74
  - `not_found` lists barcodes with no contributor record and `failed` lists fetches that failed, each with a `reason`; a failed barcode gets no row and never blocks the rest
72
75
 
73
76
  ---
74
77
 
75
78
  ### `off_browse_taxonomy` <sub>tool</sub>
76
79
 
77
- - `facet` is one of `categories`, `labels`, `allergens`, `additives`, `countries`, `nova_groups`, `nutrition_grades`; `search` matches a substring of the tag ID, name, or a synonym ("shellfish" → `en:crustaceans`); `limit` (default 20) returns up to 100 per call (a value up to 200 still returns 100); a cut result says how many matched; no paging
80
+ - `facet` is one of `categories`, `labels`, `allergens`, `additives`, `countries`, `nova_groups`, `nutrition_grades`; `search` matches a substring of the tag ID, name, or a synonym ("shellfish" → `en:crustaceans`); `limit` (default 20) returns up to 200 per call, with no input maximum (a larger value returns the first 200); a cut result says how many matched; no paging. Each lookup asks for up to 2,000 suggestions, above the largest answer measured (1,313), so an E-number term such as `e314` resolves to `en:e314` and the match count is exact below that size
78
81
  - Returns `tags[]` of `id` and `name`, where `id` goes to `off_search_products` unchanged; `nova_groups` and `nutrition_grades` come back complete with `total_in_facet`
79
82
  - The five open facets resolve against the live Open Food Facts taxonomy and fall back to a small offline sample, with a `notice`, when it is unavailable; omitting `search` returns only that sample
80
83
 
@@ -85,17 +88,17 @@ Built on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): s
85
88
  Open Food Facts-specific:
86
89
 
87
90
  - No API key; the identifying `User-Agent` Open Food Facts' terms require is built in
88
- - Per-endpoint request budgets (product 15/min, search 10/min, taxonomy 10/min); transient failures retry up to 4 attempts
91
+ - Per-endpoint request budgets (product 15/min, search 10/min, taxonomy 10/min); transient failures retry up to 4 attempts within a total deadline of 35 s for a product or search read and 20 s for a taxonomy lookup (one caller's search that canonicalizes a tag first can spend 55 s), after which the read fails as `upstream_timeout`, or `rate_limited` when its last finished attempt answered 429
89
92
  - Nutriments normalized from hyphenated keys (`energy-kcal_100g` → `energy_kcal_100g`), with `additional_100g` / `additional_serving` maps that label each nutrient with its unit
90
93
  - Tag filters take canonical IDs (`en:organic`, `en:no-gluten`); on text searches a case variant, synonym, or brand name is canonicalized first (`US` → `en:united-states`)
91
- - Every field is contributor-entered, so a missing one means not yet recorded; Nutri-Score, NOVA, and Green-Score are Open Food Facts' own computed grades, returned as-is, and carry regional formula caveats
94
+ - Every field is contributor-entered, so a missing one means not yet recorded, except that a read of prepared-product nutrition omits as-sold figures the record can still hold; Nutri-Score, NOVA, and Green-Score are Open Food Facts' own computed grades, returned as-is, and carry regional formula caveats
92
95
 
93
96
  Agent-friendly output:
94
97
 
95
98
  - Per-serving nutrition carries its denominator: `serving_size`, `serving_quantity`, `serving_quantity_unit`, and a note when none is recorded
96
99
  - Graceful partial failure: `off_compare_products` returns resolved rows alongside `not_found` and `failed`
97
- - Explicit count bounds: `total_is_lower_bound`, `last_page`, and `omitted` on searches
98
- - Typed failures: each carries a declared `reason` (`upstream_error`, `upstream_timeout`, `upstream_rejected`, `rate_limited`, plus per-tool input reasons) and a recovery hint; an incomplete upstream response is a retryable `upstream_error`, never an empty result or a not-found
100
+ - Explicit count bounds: `total_is_lower_bound`, `last_page`, `omitted`, and `outside_constraints` on searches
101
+ - Typed failures: each carries a declared `reason` (`upstream_error`, `upstream_timeout`, `upstream_rejected`, `rate_limited`, plus per-tool input reasons) and a recovery hint; an incomplete upstream response is a retryable `upstream_error`, or `upstream_timeout` when search flags a timeout, never an empty result or a not-found
99
102
 
100
103
  ## Getting started
101
104
 
@@ -0,0 +1,30 @@
1
+ ---
2
+ summary: "Checks every nutrient-filtered row against the caller bounds, caps each read with a total retry deadline, treats a flagged search timeout and a dropped connection as declared failures, labels prepared figures on product reads, adds prepared and carbohydrate figures to comparisons, and returns up to 200 taxonomy tags."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.1 — 2026-10-30
8
+
9
+ ## Changed
10
+
11
+ - **`off_get_product` prepared figures** ([#59](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/59)): Open Food Facts returns one preparation state of the nutrition per read, so a read of prepared-product figures carries `_prepared` keys and no named as-sold field. The text now prints those keys in "as prepared" sections and states that the read returned only prepared figures, not that the record holds no as-sold ones; `structuredContent` values are unchanged and the field descriptions name `_prepared` keys.
12
+ - **`off_compare_products` prepared figures** ([#59](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/59)): a row gains an optional `prepared` object with the same columns, read from `*_prepared_100g` keys and never substituted for an as-sold figure. The text adds an "as prepared" table, and a row with prepared figures only leaves the as-sold table. As-sold figures are not read for prepared products yet ([#73](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/73)).
13
+ - **`off_compare_products` carbohydrates** ([#71](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/71)): rows gain an optional `carbohydrates_100g`, and the text table a Carbohydrates column between saturated fat and sugars.
14
+ - **`off_browse_taxonomy` returns up to 200 tags** ([#70](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/70)), up from 100. `limit` has no maximum: a value above 200 returns the first 200 and, when more matched, says how many did, instead of failing validation. Each lookup now asks for up to 2,000 suggestions, above the largest answer measured (1,313), so the match count is exact below that size; an answer that reached it would be cut with nothing flagging it.
15
+ - **`off_search_products` `page_size`** ([#70](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/70)) has no maximum: a value over 10,000, previously rejected, is served at 50 and reported in `page_size_capped`.
16
+ - **Retry deadlines** ([#72](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/72)): all attempts and backoff of one read share a deadline, 35 s for a product or search read and 20 s for a taxonomy lookup, and the request in flight is cut off at expiry. A read that would have finished later now fails as the retryable `upstream_timeout`, or as `rate_limited` when its last finished attempt answered 429. A taxonomy lookup that expires does not fail its tool by itself: `off_browse_taxonomy` falls back to its offline sample with a notice, a tag filter is sent normalized, and an exclusion ends as the retryable `unrecognized_exclusion`. A search that canonicalizes a tag first can spend 55 s for one caller; one joined to a lookup whose first caller cancels can run longer ([#75](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/75)).
17
+ - **Docs and skill**: tool descriptions, the server instructions, the `openfoodfacts-guide` skill, and the README describe the row check, the deadlines, and prepared figures.
18
+
19
+ ## Fixed
20
+
21
+ - **`off_search_products` `nutrient_filters`** ([#64](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/64)): the text index compares `energy-kcal`, `fat`, `saturated-fat`, `carbohydrates`, and `sugars` as whole numbers, so `sugars lte 3` returned a row at 3.53 and `sugars gt 3` dropped matches. `gt` and `gte` on those five now widen to the whole number below, and every returned row is checked against every constraint at the index's 32-bit precision. Rows 0.4.0 returned outside the constraints are gone.
22
+ - **`outside_constraints`** ([#64](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/64)): new optional count of the rows left off a page by that check. A page can come back short or empty while later pages hold matches, and `total`, `total_is_lower_bound`, and `last_page` still describe the index's whole-number answer, which the text now says.
23
+ - **Flagged search timeouts** ([#68](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/68)): a text-search or autocomplete answer carrying `timed_out: true` was read as complete, reporting a partial page as exact and caching an empty autocomplete as `no_match`. The read now fails as the retryable `upstream_timeout`. A text search reports that reason, which `off_search_products` declares for it. A failed autocomplete is not cached: `off_browse_taxonomy` falls back to its offline sample with a notice, a tag filter is sent normalized, and an exclusion ends as the retryable `unrecognized_exclusion`.
24
+ - **`off_get_product` `serving_quantity`** ([#69](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/69)): requesting `serving_quantity` now also fetches `serving_quantity_unit`, so a unit the record holds is no longer reported as not recorded. A record with no unit still reads "unit not recorded".
25
+ - **Dropped connections** ([#74](https://github.com/cyanheads/openfoodfacts-mcp-server/issues/74)): `off_get_product` and `off_search_products` failed with no `reason` when Open Food Facts closed the connection mid-body. They now fail as the retryable `upstream_error`. `off_compare_products` already listed such a barcode in `failed` as `upstream_error`, and `off_browse_taxonomy` already fell back to its offline sample with a notice; both now name the dropped connection instead of the runtime's message.
26
+
27
+ ## Dependencies
28
+
29
+ - **`@biomejs/biome`** ^2.6.3 → ^2.6.4 (dev).
30
+ - **`@types/node`** ^26.6.5 → ^26.6.6 (dev).
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ await createApp({
12
12
  title: 'openfoodfacts-mcp-server',
13
13
  tools: allToolDefinitions,
14
14
  skills: 'skills',
15
- instructions: 'Query Open Food Facts, a free crowd-sourced database of 3M+ packaged foods: off_get_product looks up one product by barcode (4–40 digits), off_search_products finds products by text or tag filters, off_compare_products puts several side by side on nutrition, and off_browse_taxonomy resolves a human term to the canonical tag ID the other tools filter on — so start there when you have a category or label rather than a barcode. Every field is contributor-entered, so a missing one means "not yet recorded" rather than absent, and the computed Nutri-Score, NOVA, and Green-Score grades carry regional caveats. No API key is required; the data is ODbL 1.0, so cite Open Food Facts wherever you pass it on.',
15
+ instructions: 'Query Open Food Facts, a free crowd-sourced database of 3M+ packaged foods: off_get_product looks up one product by barcode (4–40 digits), off_search_products finds products by text or tag filters, off_compare_products puts several side by side on nutrition, and off_browse_taxonomy resolves a human term to the canonical tag ID the other tools filter on — so start there when you have a category or label rather than a barcode. Every field is contributor-entered, so a missing one means "not yet recorded" rather than absent, except that a read of prepared-product nutrition omits as-sold figures the record can still hold, and the computed Nutri-Score, NOVA, and Green-Score grades carry regional caveats. No API key is required; the data is ODbL 1.0, so cite Open Food Facts wherever you pass it on.',
16
16
  sessionMode: 'stateless',
17
17
  setup() {
18
18
  initOpenFoodFactsService();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,mDAAmD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAE9E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,0BAA0B;IACjC,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,QAAQ;IAChB,YAAY,EACV,ksBAAksB;IACpsB,WAAW,EAAE,WAAW;IACxB,KAAK;QACH,wBAAwB,EAAE,CAAC;QAC3B,mBAAmB,EAAE,CAAC;IACxB,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,wBAAwB,EAAE,MAAM,mDAAmD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAE9E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,0BAA0B;IACjC,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,QAAQ;IAChB,YAAY,EACV,oyBAAoyB;IACtyB,WAAW,EAAE,WAAW;IACxB,KAAK;QACH,wBAAwB,EAAE,CAAC;QAC3B,mBAAmB,EAAE,CAAC;IACxB,CAAC;CACF,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"browse-taxonomy.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-taxonomy.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAWjD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EAuKhC,CAAC"}
1
+ {"version":3,"file":"browse-taxonomy.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-taxonomy.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAUjD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;EA6KhC,CAAC"}
@@ -3,14 +3,13 @@
3
3
  * @module mcp-server/tools/definitions/browse-taxonomy
4
4
  */
5
5
  import { tool, z } from '@cyanheads/mcp-ts-core';
6
- import { MAX_AUTOCOMPLETE_SIZE } from '../../../services/openfoodfacts/openfoodfacts-service.js';
7
6
  import { getTaxonomyService } from '../../../services/taxonomy/taxonomy-service.js';
8
7
  import { mdInline, mdInlineCode } from '../../../utils/markdown.js';
9
8
  /**
10
- * Most tags one call returns. A larger `limit`, up to the suggestions one live lookup reads
11
- * (`MAX_AUTOCOMPLETE_SIZE`), returns this many and discloses the cut when more matched.
9
+ * Most tags one call returns. A larger `limit` returns this many and discloses the cut when more
10
+ * matched.
12
11
  */
13
- const TAXONOMY_LIMIT_CAP = 100;
12
+ const TAXONOMY_LIMIT_CAP = 200;
14
13
  export const offBrowseTaxonomyTool = tool('off_browse_taxonomy', {
15
14
  title: 'Browse Food Facts Taxonomy',
16
15
  description: '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.',
@@ -35,13 +34,19 @@ export const offBrowseTaxonomyTool = tool('off_browse_taxonomy', {
35
34
  .string()
36
35
  .optional()
37
36
  .describe('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.'),
37
+ // `.int()` would advertise a `maximum` of 2^53 - 1 for a value the handler clamps to the cap.
38
38
  limit: z
39
39
  .number()
40
- .int()
40
+ .multipleOf(1, 'Send limit as a whole number, not a fractional one.')
41
+ // multipleOf tolerates float noise (20.000000000000004). It stays for what it advertises; this
42
+ // closes the gap, only where it passed, so 1.5 reports once.
43
+ .refine(Number.isInteger, {
44
+ error: 'Send limit as a whole number, not a fractional one.',
45
+ when: ({ issues }) => issues.length === 0,
46
+ })
41
47
  .min(1)
42
- .max(MAX_AUTOCOMPLETE_SIZE)
43
48
  .default(20)
44
- .describe(`Maximum entries to return (default 20). One call returns at most ${TAXONOMY_LIMIT_CAP}: a larger value, up to ${MAX_AUTOCOMPLETE_SIZE} (the most suggestions one lookup reads), returns the first ${TAXONOMY_LIMIT_CAP} 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.`),
49
+ .describe(`Maximum entries to return (default 20). One call returns at most ${TAXONOMY_LIMIT_CAP}: a larger value returns the first ${TAXONOMY_LIMIT_CAP} 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.`),
45
50
  }),
46
51
  output: z.object({
47
52
  facet: z.string().describe('The facet name that was queried (echoes the input).'),
@@ -1 +1 @@
1
- {"version":3,"file":"browse-taxonomy.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-taxonomy.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browse-taxonomy.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/browse-taxonomy.tool.ts"],"names":[],"mappings":"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"}
@@ -15,14 +15,25 @@ export declare const offCompareProductsTool: import("@cyanheads/mcp-ts-core").To
15
15
  nutriscore_grade: z.ZodOptional<z.ZodString>;
16
16
  nova_group: z.ZodOptional<z.ZodNumber>;
17
17
  ecoscore_grade: z.ZodOptional<z.ZodString>;
18
+ prepared: z.ZodOptional<z.ZodObject<{
19
+ carbohydrates_100g: z.ZodOptional<z.ZodNumber>;
20
+ energy_kcal_100g: z.ZodOptional<z.ZodNumber>;
21
+ fat_100g: z.ZodOptional<z.ZodNumber>;
22
+ fiber_100g: z.ZodOptional<z.ZodNumber>;
23
+ proteins_100g: z.ZodOptional<z.ZodNumber>;
24
+ salt_100g: z.ZodOptional<z.ZodNumber>;
25
+ saturated_fat_100g: z.ZodOptional<z.ZodNumber>;
26
+ sugars_100g: z.ZodOptional<z.ZodNumber>;
27
+ }, z.core.$strip>>;
28
+ completeness: z.ZodOptional<z.ZodNumber>;
29
+ carbohydrates_100g: z.ZodOptional<z.ZodNumber>;
18
30
  energy_kcal_100g: z.ZodOptional<z.ZodNumber>;
19
31
  fat_100g: z.ZodOptional<z.ZodNumber>;
32
+ fiber_100g: z.ZodOptional<z.ZodNumber>;
33
+ proteins_100g: z.ZodOptional<z.ZodNumber>;
34
+ salt_100g: z.ZodOptional<z.ZodNumber>;
20
35
  saturated_fat_100g: z.ZodOptional<z.ZodNumber>;
21
36
  sugars_100g: z.ZodOptional<z.ZodNumber>;
22
- salt_100g: z.ZodOptional<z.ZodNumber>;
23
- proteins_100g: z.ZodOptional<z.ZodNumber>;
24
- fiber_100g: z.ZodOptional<z.ZodNumber>;
25
- completeness: z.ZodOptional<z.ZodNumber>;
26
37
  }, z.core.$strip>>;
27
38
  succeeded: z.ZodNumber;
28
39
  not_found: z.ZodArray<z.ZodString>;
@@ -35,14 +46,14 @@ export declare const offCompareProductsTool: import("@cyanheads/mcp-ts-core").To
35
46
  }, z.core.$strip>, readonly [{
36
47
  readonly reason: "upstream_error";
37
48
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
38
- readonly when: "Open Food Facts returns a 5xx other than 501 or 504, serves an HTML error page with a 2xx or 5xx status, answers 2xx with a malformed envelope, or is unreachable for a barcode — reported in that barcode's failed entry rather than failing the call";
49
+ readonly when: "Open Food Facts returns a 5xx other than 501 or 504, serves an HTML error page with a 2xx or 5xx status, answers 2xx with a malformed envelope, closes the connection before finishing its answer, or is unreachable for a barcode — reported in that barcode's failed entry rather than failing the call";
39
50
  readonly retryable: true;
40
51
  readonly thrownBy: "service";
41
52
  readonly recovery: "Retry the barcodes listed in failed after a brief pause. Rows that already resolved are kept, so only the failures need repeating.";
42
53
  }, {
43
54
  readonly reason: "upstream_timeout";
44
55
  readonly code: JsonRpcErrorCode.Timeout;
45
- readonly when: "Open Food Facts did not answer a barcode within the request deadline, or answered 408, 425, or 504 — reported in that barcode's failed entry rather than failing the call";
56
+ readonly when: "Open Food Facts did not answer a barcode within the request or retry deadline, or answered 408, 425, or 504 — reported in that barcode's failed entry rather than failing the call";
46
57
  readonly retryable: true;
47
58
  readonly thrownBy: "service";
48
59
  readonly recovery: "Retry the barcodes listed in failed, or fetch them one at a time with off_get_product to reduce the load per request.";
@@ -1 +1 @@
1
- {"version":3,"file":"compare-products.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/compare-products.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAiL3E,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+TjC,CAAC"}
1
+ {"version":3,"file":"compare-products.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/compare-products.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAuP3E,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuTjC,CAAC"}
@@ -21,11 +21,76 @@ function unprocessedNextStep(count) {
21
21
  ? 'look it up with off_get_product, or compare it with barcodes from this call in another off_compare_products call.'
22
22
  : `compare them in another off_compare_products call, up to ${COMPARE_BARCODE_CAP} barcodes at a time.`;
23
23
  }
24
+ /**
25
+ * The nutrition columns of a comparison, in table order. This one list drives the row type, the
26
+ * figures read from the raw map, the output schema, and the text tables. `raw` is the Open Food
27
+ * Facts nutrient name, which a suffix turns into a key of its nutriments map.
28
+ */
29
+ const NUTRITION_COLUMNS = [
30
+ {
31
+ key: 'energy_kcal_100g',
32
+ raw: 'energy-kcal',
33
+ header: 'Energy (kcal)',
34
+ measure: 'Energy in kcal',
35
+ },
36
+ { key: 'fat_100g', raw: 'fat', header: 'Fat (g)', measure: 'Total fat in grams' },
37
+ {
38
+ key: 'saturated_fat_100g',
39
+ raw: 'saturated-fat',
40
+ header: 'Sat. Fat (g)',
41
+ measure: 'Saturated fat in grams',
42
+ },
43
+ {
44
+ key: 'carbohydrates_100g',
45
+ raw: 'carbohydrates',
46
+ header: 'Carbohydrates (g)',
47
+ measure: 'Total carbohydrates in grams',
48
+ },
49
+ { key: 'sugars_100g', raw: 'sugars', header: 'Sugars (g)', measure: 'Total sugars in grams' },
50
+ { key: 'salt_100g', raw: 'salt', header: 'Salt (g)', measure: 'Salt in grams' },
51
+ { key: 'proteins_100g', raw: 'proteins', header: 'Protein (g)', measure: 'Protein in grams' },
52
+ { key: 'fiber_100g', raw: 'fiber', header: 'Fiber (g)', measure: 'Dietary fiber in grams' },
53
+ ];
24
54
  /** Extract a numeric value from the raw nutriments map. */
25
55
  function n(raw, key) {
26
56
  const v = raw[key];
27
57
  return typeof v === 'number' ? v : undefined;
28
58
  }
59
+ /** Read every column under `suffix`. One raw key per column, so nothing is derived or converted. */
60
+ function readFigures(raw, suffix) {
61
+ const figures = {};
62
+ for (const { key, raw: nutrient } of NUTRITION_COLUMNS) {
63
+ const value = n(raw, `${nutrient}${suffix}`);
64
+ if (value !== undefined)
65
+ figures[key] = value;
66
+ }
67
+ return figures;
68
+ }
69
+ /**
70
+ * Output fields for a set of figures, one per column. A factory so each use gets its own schema
71
+ * instances. `Object.fromEntries` widens its keys to `string`, so the cast restores the columns.
72
+ */
73
+ const nutritionFields = (describe) => Object.fromEntries(NUTRITION_COLUMNS.map(({ key, measure }) => [
74
+ key,
75
+ z.number().optional().describe(describe(measure)),
76
+ ]));
77
+ /** Whether any column holds a figure. */
78
+ function hasFigure(figures) {
79
+ return NUTRITION_COLUMNS.some(({ key }) => figures[key] !== undefined);
80
+ }
81
+ /** A nutrition table with one row per entry, `N/A` where an entry has no figure for a column. */
82
+ function nutritionTable(heading, rows) {
83
+ const headers = NUTRITION_COLUMNS.map((column) => column.header);
84
+ return [
85
+ heading,
86
+ `| Product | ${headers.join(' | ')} |`,
87
+ `|:--------|${headers.map((header) => `:${'-'.repeat(header.length + 1)}|`).join('')}`,
88
+ ...rows.map(({ label, figures }) => {
89
+ const cells = NUTRITION_COLUMNS.map(({ key }) => figures[key] ?? 'N/A');
90
+ return `| ${label} | ${cells.join(' | ')} |`;
91
+ }),
92
+ ];
93
+ }
29
94
  /** The failure reasons this tool declares — the four the service raises for a product fetch. */
30
95
  const FAILURE_REASONS = [
31
96
  'upstream_error',
@@ -108,34 +173,16 @@ function buildCompareRow(barcode, raw) {
108
173
  if (typeof raw.completeness === 'number')
109
174
  row.completeness = raw.completeness;
110
175
  if (raw.nutriments) {
111
- const nm = raw.nutriments;
112
- const energy = n(nm, 'energy-kcal_100g');
113
- if (energy !== undefined)
114
- row.energy_kcal_100g = energy;
115
- const fat = n(nm, 'fat_100g');
116
- if (fat !== undefined)
117
- row.fat_100g = fat;
118
- const satFat = n(nm, 'saturated-fat_100g');
119
- if (satFat !== undefined)
120
- row.saturated_fat_100g = satFat;
121
- const sugars = n(nm, 'sugars_100g');
122
- if (sugars !== undefined)
123
- row.sugars_100g = sugars;
124
- const salt = n(nm, 'salt_100g');
125
- if (salt !== undefined)
126
- row.salt_100g = salt;
127
- const proteins = n(nm, 'proteins_100g');
128
- if (proteins !== undefined)
129
- row.proteins_100g = proteins;
130
- const fiber = n(nm, 'fiber_100g');
131
- if (fiber !== undefined)
132
- row.fiber_100g = fiber;
176
+ Object.assign(row, readFigures(raw.nutriments, '_100g'));
177
+ const prepared = readFigures(raw.nutriments, '_prepared_100g');
178
+ if (Object.keys(prepared).length > 0)
179
+ row.prepared = prepared;
133
180
  }
134
181
  return row;
135
182
  }
136
183
  export const offCompareProductsTool = tool('off_compare_products', {
137
184
  title: 'Compare Food Products Side-by-Side',
138
- description: '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.',
185
+ description: '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, carbohydrates, sugars, salt, protein, and fiber per 100 g, or per 100 ml for liquids, plus Nutri-Score, NOVA group, and Green-Score. Open Food Facts returns one preparation state per read, so figures for the prepared product arrive in a prepared object on the row, with the same columns and basis, and never fill an as-sold field. 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.',
139
186
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
140
187
  input: z.object({
141
188
  barcodes: z
@@ -173,34 +220,11 @@ export const offCompareProductsTool = tool('off_compare_products', {
173
220
  .string()
174
221
  .optional()
175
222
  .describe('Green-Score (formerly Eco-Score) environmental impact grade: "a-plus" (lowest impact), then "a" through "f"; "unknown" when the data it needs is missing, or "not-applicable" for product categories the score does not cover. Often absent.'),
176
- energy_kcal_100g: z
177
- .number()
178
- .optional()
179
- .describe('Energy in kcal per 100 g, or per 100 ml for liquids. Absent when not entered.'),
180
- fat_100g: z
181
- .number()
182
- .optional()
183
- .describe('Total fat in grams per 100 g, or per 100 ml for liquids. Absent when not entered.'),
184
- saturated_fat_100g: z
185
- .number()
186
- .optional()
187
- .describe('Saturated fat in grams per 100 g, or per 100 ml for liquids. Absent when not entered.'),
188
- sugars_100g: z
189
- .number()
190
- .optional()
191
- .describe('Total sugars in grams per 100 g, or per 100 ml for liquids. Absent when not entered.'),
192
- salt_100g: z
193
- .number()
223
+ ...nutritionFields((measure) => `${measure} per 100 g, or per 100 ml for liquids, as sold. Absent when not entered, or when this read returned only prepared figures (see prepared).`),
224
+ prepared: z
225
+ .object(nutritionFields((measure) => `${measure} per 100 g, or per 100 ml for liquids, as prepared. Absent when this read returned no such figure.`))
194
226
  .optional()
195
- .describe('Salt in grams per 100 g, or per 100 ml for liquids. Absent when not entered.'),
196
- proteins_100g: z
197
- .number()
198
- .optional()
199
- .describe('Protein in grams per 100 g, or per 100 ml for liquids. Absent when not entered.'),
200
- fiber_100g: z
201
- .number()
202
- .optional()
203
- .describe('Dietary fiber in grams per 100 g, or per 100 ml for liquids. Often absent.'),
227
+ .describe("Figures for the prepared product, on the same columns and basis as the as-sold fields, read from Open Food Facts' *_prepared_100g keys and never derived or substituted for an as-sold figure. Open Food Facts returns one preparation state per read, so as-sold fields absent beside this object mean this read returned none, not that the record holds none. Absent when the read carried none of these figures."),
204
228
  completeness: z
205
229
  .number()
206
230
  .optional()
@@ -233,7 +257,7 @@ export const offCompareProductsTool = tool('off_compare_products', {
233
257
  {
234
258
  reason: 'upstream_error',
235
259
  code: JsonRpcErrorCode.ServiceUnavailable,
236
- when: "Open Food Facts returns a 5xx other than 501 or 504, serves an HTML error page with a 2xx or 5xx status, answers 2xx with a malformed envelope, or is unreachable for a barcode — reported in that barcode's failed entry rather than failing the call",
260
+ when: "Open Food Facts returns a 5xx other than 501 or 504, serves an HTML error page with a 2xx or 5xx status, answers 2xx with a malformed envelope, closes the connection before finishing its answer, or is unreachable for a barcode — reported in that barcode's failed entry rather than failing the call",
237
261
  retryable: true,
238
262
  thrownBy: 'service',
239
263
  recovery: 'Retry the barcodes listed in failed after a brief pause. Rows that already resolved are kept, so only the failures need repeating.',
@@ -241,7 +265,7 @@ export const offCompareProductsTool = tool('off_compare_products', {
241
265
  {
242
266
  reason: 'upstream_timeout',
243
267
  code: JsonRpcErrorCode.Timeout,
244
- when: "Open Food Facts did not answer a barcode within the request deadline, or answered 408, 425, or 504 — reported in that barcode's failed entry rather than failing the call",
268
+ when: "Open Food Facts did not answer a barcode within the request or retry deadline, or answered 408, 425, or 504 — reported in that barcode's failed entry rather than failing the call",
245
269
  retryable: true,
246
270
  thrownBy: 'service',
247
271
  recovery: 'Retry the barcodes listed in failed, or fetch them one at a time with off_get_product to reduce the load per request.',
@@ -348,21 +372,32 @@ export const offCompareProductsTool = tool('off_compare_products', {
348
372
  const grade = (value) => (value === undefined ? 'N/A' : mdInline(value));
349
373
  lines.push(`| ${name} | ${p.barcode} | ${p.found} | ${grade(p.nutriscore_grade)} | ${p.nova_group ?? 'N/A'} | ${grade(p.ecoscore_grade)} | ${completeness} |`);
350
374
  }
351
- // Nutrition table
352
- lines.push('\n### Nutrition per 100 g / 100 ml');
353
- lines.push('| Product | Energy (kcal) | Fat (g) | Sat. Fat (g) | Sugars (g) | Salt (g) | Protein (g) | Fiber (g) |');
354
- lines.push('|:--------|:-------------|:--------|:-------------|:-----------|:---------|:------------|:----------|');
355
- for (const p of found) {
356
- const name = rowLabel(p);
357
- const fmt = (v) => (v !== undefined ? String(v) : 'N/A');
358
- lines.push(`| ${name} | ${fmt(p.energy_kcal_100g)} | ${fmt(p.fat_100g)} | ${fmt(p.saturated_fat_100g)} | ${fmt(p.sugars_100g)} | ${fmt(p.salt_100g)} | ${fmt(p.proteins_100g)} | ${fmt(p.fiber_100g)} |`);
375
+ // Nutrition tables. Each block stands alone, since a batch can fall entirely to one side. A row
376
+ // with prepared figures and no as-sold one leaves the as-sold table: its N/As would sit under a
377
+ // footer reading "not yet entered", which is false of a record that holds those figures on a
378
+ // preparation state this read did not return.
379
+ const asSold = found.filter((p) => !p.prepared || hasFigure(p));
380
+ const asPrepared = found.flatMap((p) => p.prepared ? [{ label: rowLabel(p), figures: p.prepared }] : []);
381
+ const preparedOnly = found.filter((p) => p.prepared && !hasFigure(p));
382
+ if (asSold.length > 0) {
383
+ lines.push(...nutritionTable('\n### Nutrition per 100 g / 100 ml', asSold.map((p) => ({ label: rowLabel(p), figures: p }))));
384
+ }
385
+ if (asPrepared.length > 0) {
386
+ lines.push(...nutritionTable('\n### Nutrition per 100 g / 100 ml, as prepared', asPrepared));
387
+ lines.push('\n*In this table, "N/A" = no prepared figure in this read.*');
388
+ }
389
+ if (preparedOnly.length > 0) {
390
+ lines.push(`*This read returned no as-sold figures for ${preparedOnly.map(rowLabel).join(', ')}. Open Food Facts returns one preparation state per read, so the record can still hold them.*`);
359
391
  }
360
392
  // Completeness notices
361
393
  const lowCompleteness = found.filter((p) => p.completeness !== undefined && p.completeness < 0.5);
362
394
  if (lowCompleteness.length > 0) {
363
395
  lines.push(`\n*Low completeness (< 50%): ${lowCompleteness.map(rowLabel).join(', ')} — many fields may be missing.*`);
364
396
  }
365
- lines.push('\n*Data: Open Food Facts (ODbL 1.0) — crowd-sourced. "N/A" = not yet entered.*');
397
+ // Scoped rather than dropped when an "as prepared" table prints: Scores keeps its N/As even
398
+ // when no as-sold table does.
399
+ const naScope = asPrepared.length > 0 ? ' outside the "as prepared" table' : '';
400
+ lines.push(`\n*Data: Open Food Facts (ODbL 1.0) — crowd-sourced. "N/A"${naScope} = not yet entered.*`);
366
401
  return [{ type: 'text', text: lines.join('\n') }];
367
402
  },
368
403
  });
@@ -1 +1 @@
1
- {"version":3,"file":"compare-products.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/compare-products.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compare-products.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/compare-products.tool.ts"],"names":[],"mappings":"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"}
@@ -111,14 +111,14 @@ export declare const offGetProductTool: import("@cyanheads/mcp-ts-core").ToolDef
111
111
  }, {
112
112
  readonly reason: "upstream_error";
113
113
  readonly code: JsonRpcErrorCode.ServiceUnavailable;
114
- readonly when: "Open Food Facts returns a 5xx other than 501 or 504, serves an HTML error page with a 2xx or 5xx status, answers 2xx with a malformed envelope, or is unreachable";
114
+ readonly when: "Open Food Facts returns a 5xx other than 501 or 504, serves an HTML error page with a 2xx or 5xx status, answers 2xx with a malformed envelope, closes the connection before finishing its answer, or is unreachable";
115
115
  readonly retryable: true;
116
116
  readonly thrownBy: "service";
117
117
  readonly recovery: "Retry after a brief pause. If it keeps failing, Open Food Facts is degraded — check the barcode again later.";
118
118
  }, {
119
119
  readonly reason: "upstream_timeout";
120
120
  readonly code: JsonRpcErrorCode.Timeout;
121
- readonly when: "Open Food Facts did not answer within the request deadline, or answered 408, 425, or 504";
121
+ readonly when: "Open Food Facts did not answer within the request or retry deadline, or answered 408, 425, or 504";
122
122
  readonly retryable: true;
123
123
  readonly thrownBy: "service";
124
124
  readonly recovery: "Retry once. If it times out again, pass a narrower fields subset so Open Food Facts assembles less per request.";
@@ -1 +1 @@
1
- {"version":3,"file":"get-product.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-product.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA6UjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgiB5B,CAAC"}
1
+ {"version":3,"file":"get-product.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-product.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAqYjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmjB5B,CAAC"}