@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.
- package/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/README.md +12 -9
- package/changelog/0.4.x/0.4.1.md +30 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.js +12 -7
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/compare-products.tool.d.ts +17 -6
- package/dist/mcp-server/tools/definitions/compare-products.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/compare-products.tool.js +96 -61
- package/dist/mcp-server/tools/definitions/compare-products.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/get-product.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/get-product.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/get-product.tool.js +73 -28
- package/dist/mcp-server/tools/definitions/get-product.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +22 -10
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-products.tool.d.ts +3 -2
- package/dist/mcp-server/tools/definitions/search-products.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/search-products.tool.js +104 -43
- package/dist/mcp-server/tools/definitions/search-products.tool.js.map +1 -1
- package/dist/services/openfoodfacts/openfoodfacts-service.d.ts +14 -14
- package/dist/services/openfoodfacts/openfoodfacts-service.d.ts.map +1 -1
- package/dist/services/openfoodfacts/openfoodfacts-service.js +205 -78
- package/dist/services/openfoodfacts/openfoodfacts-service.js.map +1 -1
- package/dist/services/openfoodfacts/types.d.ts +27 -4
- package/dist/services/openfoodfacts/types.d.ts.map +1 -1
- package/dist/services/openfoodfacts/types.js +15 -0
- package/dist/services/openfoodfacts/types.js.map +1 -1
- package/dist/services/taxonomy/taxonomy-service.d.ts.map +1 -1
- package/dist/services/taxonomy/taxonomy-service.js +12 -10
- package/dist/services/taxonomy/taxonomy-service.js.map +1 -1
- package/package.json +3 -3
- package/server.json +3 -3
- 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.
|
|
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.
|
|
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
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/openfoodfacts-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/openfoodfacts-mcp-server) [](https://www.typescriptlang.org/) [](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
|
|
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
|
|
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 `
|
|
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,
|
|
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;
|
|
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
|
|
11
|
-
*
|
|
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 =
|
|
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
|
-
.
|
|
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
|
|
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":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,
|
|
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;
|
|
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
|
-
|
|
112
|
-
const
|
|
113
|
-
if (
|
|
114
|
-
row.
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
.
|
|
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(
|
|
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
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
|
|
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;
|
|
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"}
|