@cyanheads/openfoodfacts-mcp-server 0.1.0
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 +335 -0
- package/CLAUDE.md +335 -0
- package/Dockerfile +99 -0
- package/LICENSE +201 -0
- package/README.md +290 -0
- package/changelog/0.1.x/0.1.0.md +15 -0
- package/changelog/template.md +127 -0
- package/dist/config/server-config.d.ts +15 -0
- package/dist/config/server-config.d.ts.map +1 -0
- package/dist/config/server-config.js +35 -0
- package/dist/config/server-config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.d.ts +27 -0
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.js +91 -0
- package/dist/mcp-server/tools/definitions/browse-taxonomy.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/compare-products.tool.d.ts +36 -0
- package/dist/mcp-server/tools/definitions/compare-products.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/compare-products.tool.js +228 -0
- package/dist/mcp-server/tools/definitions/compare-products.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/get-product.tool.d.ts +83 -0
- package/dist/mcp-server/tools/definitions/get-product.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/get-product.tool.js +420 -0
- package/dist/mcp-server/tools/definitions/get-product.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/index.d.ts +175 -0
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/index.js +15 -0
- package/dist/mcp-server/tools/definitions/index.js.map +1 -0
- package/dist/mcp-server/tools/definitions/search-products.tool.d.ts +54 -0
- package/dist/mcp-server/tools/definitions/search-products.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/search-products.tool.js +219 -0
- package/dist/mcp-server/tools/definitions/search-products.tool.js.map +1 -0
- package/dist/services/openfoodfacts/openfoodfacts-service.d.ts +54 -0
- package/dist/services/openfoodfacts/openfoodfacts-service.d.ts.map +1 -0
- package/dist/services/openfoodfacts/openfoodfacts-service.js +308 -0
- package/dist/services/openfoodfacts/openfoodfacts-service.js.map +1 -0
- package/dist/services/openfoodfacts/types.d.ts +89 -0
- package/dist/services/openfoodfacts/types.d.ts.map +1 -0
- package/dist/services/openfoodfacts/types.js +7 -0
- package/dist/services/openfoodfacts/types.js.map +1 -0
- package/dist/services/taxonomy/taxonomy-service.d.ts +24 -0
- package/dist/services/taxonomy/taxonomy-service.d.ts.map +1 -0
- package/dist/services/taxonomy/taxonomy-service.js +271 -0
- package/dist/services/taxonomy/taxonomy-service.js.map +1 -0
- package/package.json +102 -0
- package/server.json +141 -0
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tool definition for side-by-side nutrition comparison of multiple food products.
|
|
3
|
+
* @module mcp-server/tools/definitions/compare-products
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
export declare const offCompareProductsTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
+
barcodes: z.ZodArray<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
10
|
+
products: z.ZodArray<z.ZodObject<{
|
|
11
|
+
barcode: z.ZodString;
|
|
12
|
+
product_name: z.ZodOptional<z.ZodString>;
|
|
13
|
+
brands: z.ZodOptional<z.ZodString>;
|
|
14
|
+
found: z.ZodBoolean;
|
|
15
|
+
nutriscore_grade: z.ZodOptional<z.ZodString>;
|
|
16
|
+
nova_group: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
ecoscore_grade: z.ZodOptional<z.ZodString>;
|
|
18
|
+
energy_kcal_100g: z.ZodOptional<z.ZodNumber>;
|
|
19
|
+
fat_100g: z.ZodOptional<z.ZodNumber>;
|
|
20
|
+
saturated_fat_100g: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
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
|
+
}, z.core.$strip>>;
|
|
27
|
+
succeeded: z.ZodNumber;
|
|
28
|
+
not_found: z.ZodArray<z.ZodString>;
|
|
29
|
+
}, z.core.$strip>, readonly [{
|
|
30
|
+
readonly reason: "upstream_error";
|
|
31
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
32
|
+
readonly when: "Open Food Facts API returns 5xx or is unreachable for one or more barcodes";
|
|
33
|
+
readonly retryable: true;
|
|
34
|
+
readonly recovery: "Retry after a brief pause. Partial failures surface individual barcodes in not_found — verify those barcodes with off_get_product.";
|
|
35
|
+
}], undefined>;
|
|
36
|
+
//# sourceMappingURL=compare-products.tool.d.ts.map
|
|
@@ -0,0 +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,EAAsB,MAAM,+BAA+B,CAAC;AAkErF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA0NjC,CAAC"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tool definition for side-by-side nutrition comparison of multiple food products.
|
|
3
|
+
* @module mcp-server/tools/definitions/compare-products
|
|
4
|
+
*/
|
|
5
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
import { getOpenFoodFactsService } from '../../../services/openfoodfacts/openfoodfacts-service.js';
|
|
8
|
+
/** Fields needed for comparison — narrower than full product fetch. */
|
|
9
|
+
const COMPARE_FIELDS = 'product_name,brands,nutriscore_grade,nova_group,ecoscore_grade,nutriments,completeness';
|
|
10
|
+
/** Extract a numeric value from the raw nutriments map. */
|
|
11
|
+
function n(raw, key) {
|
|
12
|
+
const v = raw[key];
|
|
13
|
+
return typeof v === 'number' ? v : undefined;
|
|
14
|
+
}
|
|
15
|
+
/** Build a comparison row from a raw product. */
|
|
16
|
+
function buildCompareRow(barcode, raw) {
|
|
17
|
+
if (!raw)
|
|
18
|
+
return { barcode, found: false };
|
|
19
|
+
const row = { barcode, found: true };
|
|
20
|
+
if (raw.product_name)
|
|
21
|
+
row.product_name = raw.product_name;
|
|
22
|
+
if (raw.brands)
|
|
23
|
+
row.brands = raw.brands;
|
|
24
|
+
if (raw.nutriscore_grade)
|
|
25
|
+
row.nutriscore_grade = raw.nutriscore_grade;
|
|
26
|
+
if (typeof raw.nova_group === 'number')
|
|
27
|
+
row.nova_group = raw.nova_group;
|
|
28
|
+
if (raw.ecoscore_grade)
|
|
29
|
+
row.ecoscore_grade = raw.ecoscore_grade;
|
|
30
|
+
if (typeof raw.completeness === 'number')
|
|
31
|
+
row.completeness = raw.completeness;
|
|
32
|
+
if (raw.nutriments) {
|
|
33
|
+
const nm = raw.nutriments;
|
|
34
|
+
const energy = n(nm, 'energy-kcal_100g');
|
|
35
|
+
if (energy !== undefined)
|
|
36
|
+
row.energy_kcal_100g = energy;
|
|
37
|
+
const fat = n(nm, 'fat_100g');
|
|
38
|
+
if (fat !== undefined)
|
|
39
|
+
row.fat_100g = fat;
|
|
40
|
+
const satFat = n(nm, 'saturated-fat_100g');
|
|
41
|
+
if (satFat !== undefined)
|
|
42
|
+
row.saturated_fat_100g = satFat;
|
|
43
|
+
const sugars = n(nm, 'sugars_100g');
|
|
44
|
+
if (sugars !== undefined)
|
|
45
|
+
row.sugars_100g = sugars;
|
|
46
|
+
const salt = n(nm, 'salt_100g');
|
|
47
|
+
if (salt !== undefined)
|
|
48
|
+
row.salt_100g = salt;
|
|
49
|
+
const proteins = n(nm, 'proteins_100g');
|
|
50
|
+
if (proteins !== undefined)
|
|
51
|
+
row.proteins_100g = proteins;
|
|
52
|
+
const fiber = n(nm, 'fiber_100g');
|
|
53
|
+
if (fiber !== undefined)
|
|
54
|
+
row.fiber_100g = fiber;
|
|
55
|
+
}
|
|
56
|
+
return row;
|
|
57
|
+
}
|
|
58
|
+
export const offCompareProductsTool = tool('off_compare_products', {
|
|
59
|
+
title: 'Compare Food Products Side-by-Side',
|
|
60
|
+
description: 'Side-by-side nutrition and scoring comparison for 2–10 products by barcode. Fetches all products in parallel and returns a normalized table of energy (kcal/100g), fat, saturated fat, sugars, salt, protein, fiber, Nutri-Score, NOVA group, and Green-Score. Designed for "which of these cereals is healthiest?" or "compare these pasta brands" workflows. Missing nutrition data for any product is preserved as absent — comparisons are not imputed. Scores carry regional formula caveats. Data under ODbL 1.0 — cite Open Food Facts in downstream use.',
|
|
61
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
62
|
+
input: z.object({
|
|
63
|
+
barcodes: z
|
|
64
|
+
.array(z
|
|
65
|
+
.string()
|
|
66
|
+
.regex(/^\d{8,14}$/)
|
|
67
|
+
.describe('EAN-13 or UPC barcode (8–14 digits).'))
|
|
68
|
+
.min(2)
|
|
69
|
+
.max(10)
|
|
70
|
+
.describe('2–10 barcodes to compare. All products are fetched in parallel. Example: ["3017620422003", "7622210100146"].'),
|
|
71
|
+
}),
|
|
72
|
+
output: z.object({
|
|
73
|
+
products: z
|
|
74
|
+
.array(z
|
|
75
|
+
.object({
|
|
76
|
+
barcode: z.string().describe('EAN-13 or UPC barcode (same as provided input).'),
|
|
77
|
+
product_name: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe('Product name. Absent when not yet entered by contributors.'),
|
|
81
|
+
brands: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe('Brand name(s), comma-separated. Absent when not yet entered.'),
|
|
85
|
+
found: z.boolean().describe('False if the barcode has no contributor record.'),
|
|
86
|
+
nutriscore_grade: z
|
|
87
|
+
.string()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe('Nutri-Score letter (a–e). Absent when not computed.'),
|
|
90
|
+
nova_group: z
|
|
91
|
+
.number()
|
|
92
|
+
.optional()
|
|
93
|
+
.describe('NOVA processing class (1–4). Absent when not assigned.'),
|
|
94
|
+
ecoscore_grade: z
|
|
95
|
+
.string()
|
|
96
|
+
.optional()
|
|
97
|
+
.describe('Green-Score/Eco-Score (a–e or "unknown"). Often absent.'),
|
|
98
|
+
energy_kcal_100g: z
|
|
99
|
+
.number()
|
|
100
|
+
.optional()
|
|
101
|
+
.describe('Energy per 100g in kcal. Absent when not entered.'),
|
|
102
|
+
fat_100g: z
|
|
103
|
+
.number()
|
|
104
|
+
.optional()
|
|
105
|
+
.describe('Total fat per 100g in grams. Absent when not entered.'),
|
|
106
|
+
saturated_fat_100g: z
|
|
107
|
+
.number()
|
|
108
|
+
.optional()
|
|
109
|
+
.describe('Saturated fat per 100g in grams. Absent when not entered.'),
|
|
110
|
+
sugars_100g: z
|
|
111
|
+
.number()
|
|
112
|
+
.optional()
|
|
113
|
+
.describe('Total sugars per 100g in grams. Absent when not entered.'),
|
|
114
|
+
salt_100g: z
|
|
115
|
+
.number()
|
|
116
|
+
.optional()
|
|
117
|
+
.describe('Salt per 100g in grams. Absent when not entered.'),
|
|
118
|
+
proteins_100g: z
|
|
119
|
+
.number()
|
|
120
|
+
.optional()
|
|
121
|
+
.describe('Protein per 100g in grams. Absent when not entered.'),
|
|
122
|
+
fiber_100g: z
|
|
123
|
+
.number()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe('Dietary fiber per 100g in grams. Often absent.'),
|
|
126
|
+
completeness: z
|
|
127
|
+
.number()
|
|
128
|
+
.optional()
|
|
129
|
+
.describe('Data completeness 0–1. Low values mean many fields are missing.'),
|
|
130
|
+
})
|
|
131
|
+
.describe('A single product comparison row.'))
|
|
132
|
+
.describe('Comparison rows, one per barcode in input order.'),
|
|
133
|
+
succeeded: z.number().describe('Number of barcodes that resolved to a found product.'),
|
|
134
|
+
not_found: z
|
|
135
|
+
.array(z.string().describe('EAN-13 or UPC barcode with no contributor record.'))
|
|
136
|
+
.describe('Barcodes with no contributor record. Not an error — the product may exist but not yet entered in Open Food Facts.'),
|
|
137
|
+
}),
|
|
138
|
+
errors: [
|
|
139
|
+
{
|
|
140
|
+
reason: 'upstream_error',
|
|
141
|
+
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
142
|
+
when: 'Open Food Facts API returns 5xx or is unreachable for one or more barcodes',
|
|
143
|
+
retryable: true,
|
|
144
|
+
recovery: 'Retry after a brief pause. Partial failures surface individual barcodes in not_found — verify those barcodes with off_get_product.',
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
async handler(input, ctx) {
|
|
148
|
+
const svc = getOpenFoodFactsService();
|
|
149
|
+
// Fetch all products in parallel
|
|
150
|
+
const settlements = await Promise.allSettled(input.barcodes.map((barcode) => svc.getProductFields(barcode, COMPARE_FIELDS, ctx)));
|
|
151
|
+
const products = [];
|
|
152
|
+
const not_found = [];
|
|
153
|
+
let succeeded = 0;
|
|
154
|
+
for (let i = 0; i < input.barcodes.length; i++) {
|
|
155
|
+
const barcode = input.barcodes[i];
|
|
156
|
+
const result = settlements[i];
|
|
157
|
+
if (result === undefined || result.status === 'rejected') {
|
|
158
|
+
// If it was an explicit service error (not just not-found), propagate it
|
|
159
|
+
if (result?.status === 'rejected') {
|
|
160
|
+
const err = result.reason;
|
|
161
|
+
// If it looks like an upstream error, throw it
|
|
162
|
+
if (err.message?.includes('Open Food Facts')) {
|
|
163
|
+
throw serviceUnavailable(`Failed to fetch barcode ${barcode}: ${err.message}`, { barcode }, { cause: err });
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
products.push({ barcode, found: false });
|
|
167
|
+
not_found.push(barcode);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const raw = result.value;
|
|
171
|
+
if (!raw) {
|
|
172
|
+
products.push({ barcode, found: false });
|
|
173
|
+
not_found.push(barcode);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
products.push(buildCompareRow(barcode, raw));
|
|
177
|
+
succeeded++;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
ctx.log.info('Product comparison completed', {
|
|
181
|
+
total: input.barcodes.length,
|
|
182
|
+
succeeded,
|
|
183
|
+
not_found: not_found.length,
|
|
184
|
+
});
|
|
185
|
+
return { products, succeeded, not_found };
|
|
186
|
+
},
|
|
187
|
+
format: (result) => {
|
|
188
|
+
const lines = [
|
|
189
|
+
`## Product Comparison (${result.succeeded}/${result.products.length} found)\n`,
|
|
190
|
+
];
|
|
191
|
+
if (result.not_found.length > 0) {
|
|
192
|
+
lines.push(`**Not found:** ${result.not_found.join(', ')} (not yet entered in Open Food Facts)\n`);
|
|
193
|
+
}
|
|
194
|
+
const found = result.products.filter((p) => p.found);
|
|
195
|
+
if (found.length === 0) {
|
|
196
|
+
lines.push('No products found. Try off_get_product on individual barcodes to verify.');
|
|
197
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
198
|
+
}
|
|
199
|
+
// Scores table — includes all products with found status
|
|
200
|
+
lines.push('### Scores');
|
|
201
|
+
lines.push('| Product | Barcode | Found | Nutri-Score | NOVA | Eco-Score | Completeness |');
|
|
202
|
+
lines.push('|:--------|:--------|:------|:------------|:-----|:----------|:-------------|');
|
|
203
|
+
for (const p of result.products) {
|
|
204
|
+
const name = p.product_name
|
|
205
|
+
? `${p.product_name}${p.brands ? ` (${p.brands})` : ''}`
|
|
206
|
+
: `Barcode ${p.barcode}`;
|
|
207
|
+
const completeness = p.completeness !== undefined ? `${Math.round(p.completeness * 100)}%` : 'N/A';
|
|
208
|
+
lines.push(`| ${name} | ${p.barcode} | ${p.found} | ${p.nutriscore_grade ?? 'N/A'} | ${p.nova_group ?? 'N/A'} | ${p.ecoscore_grade ?? 'N/A'} | ${completeness} |`);
|
|
209
|
+
}
|
|
210
|
+
// Nutrition table
|
|
211
|
+
lines.push('\n### Nutrition per 100g');
|
|
212
|
+
lines.push('| Product | Energy (kcal) | Fat (g) | Sat. Fat (g) | Sugars (g) | Salt (g) | Protein (g) | Fiber (g) |');
|
|
213
|
+
lines.push('|:--------|:-------------|:--------|:-------------|:-----------|:---------|:------------|:----------|');
|
|
214
|
+
for (const p of found) {
|
|
215
|
+
const name = p.product_name ?? `Barcode ${p.barcode}`;
|
|
216
|
+
const fmt = (v) => (v !== undefined ? String(v) : 'N/A');
|
|
217
|
+
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)} |`);
|
|
218
|
+
}
|
|
219
|
+
// Completeness notices
|
|
220
|
+
const lowCompleteness = found.filter((p) => p.completeness !== undefined && p.completeness < 0.5);
|
|
221
|
+
if (lowCompleteness.length > 0) {
|
|
222
|
+
lines.push(`\n*Low completeness (< 50%): ${lowCompleteness.map((p) => p.product_name ?? p.barcode).join(', ')} — many fields may be missing.*`);
|
|
223
|
+
}
|
|
224
|
+
lines.push('\n*Data: Open Food Facts (ODbL 1.0) — crowd-sourced. "N/A" = not yet entered.*');
|
|
225
|
+
return [{ type: 'text', text: lines.join('\n') }];
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
//# sourceMappingURL=compare-products.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare-products.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/compare-products.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,mDAAmD,CAAC;AAG5F,uEAAuE;AACvE,MAAM,cAAc,GAClB,wFAAwF,CAAC;AAoB3F,2DAA2D;AAC3D,SAAS,CAAC,CAAC,GAAgD,EAAE,GAAW;IACtE,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,iDAAiD;AACjD,SAAS,eAAe,CAAC,OAAe,EAAE,GAAsB;IAC9D,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAE3C,MAAM,GAAG,GAAe,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAEjD,IAAI,GAAG,CAAC,YAAY;QAAE,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IAC1D,IAAI,GAAG,CAAC,MAAM;QAAE,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IACxC,IAAI,GAAG,CAAC,gBAAgB;QAAE,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC,gBAAgB,CAAC;IACtE,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ;QAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IACxE,IAAI,GAAG,CAAC,cAAc;QAAE,GAAG,CAAC,cAAc,GAAG,GAAG,CAAC,cAAc,CAAC;IAChE,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ;QAAE,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;IAE9E,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACnB,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC;QAC1B,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,gBAAgB,GAAG,MAAM,CAAC;QACxD,MAAM,GAAG,GAAG,CAAC,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9B,IAAI,GAAG,KAAK,SAAS;YAAE,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC;QAC1C,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;QAC3C,IAAI,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,kBAAkB,GAAG,MAAM,CAAC;QAC1D,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACpC,IAAI,MAAM,KAAK,SAAS;YAAE,GAAG,CAAC,WAAW,GAAG,MAAM,CAAC;QACnD,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAChC,IAAI,IAAI,KAAK,SAAS;YAAE,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;QAC7C,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS;YAAE,GAAG,CAAC,aAAa,GAAG,QAAQ,CAAC;QACzD,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS;YAAE,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC;IAClD,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,sBAAsB,EAAE;IACjE,KAAK,EAAE,oCAAoC;IAC3C,WAAW,EACT,kiBAAkiB;IACpiB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IAE9E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC;aACR,KAAK,CACJ,CAAC;aACE,MAAM,EAAE;aACR,KAAK,CAAC,YAAY,CAAC;aACnB,QAAQ,CAAC,sCAAsC,CAAC,CACpD;aACA,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,QAAQ,CACP,8GAA8G,CAC/G;KACJ,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC;aACR,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;YAC/E,YAAY,EAAE,CAAC;iBACZ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,4DAA4D,CAAC;YACzE,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,8DAA8D,CAAC;YAC3E,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;YAC9E,gBAAgB,EAAE,CAAC;iBAChB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,qDAAqD,CAAC;YAClE,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,wDAAwD,CAAC;YACrE,cAAc,EAAE,CAAC;iBACd,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,yDAAyD,CAAC;YACtE,gBAAgB,EAAE,CAAC;iBAChB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,mDAAmD,CAAC;YAChE,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,uDAAuD,CAAC;YACpE,kBAAkB,EAAE,CAAC;iBAClB,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,2DAA2D,CAAC;YACxE,WAAW,EAAE,CAAC;iBACX,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,0DAA0D,CAAC;YACvE,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,kDAAkD,CAAC;YAC/D,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,qDAAqD,CAAC;YAClE,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,gDAAgD,CAAC;YAC7D,YAAY,EAAE,CAAC;iBACZ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,iEAAiE,CAAC;SAC/E,CAAC;aACD,QAAQ,CAAC,kCAAkC,CAAC,CAChD;aACA,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;QACtF,SAAS,EAAE,CAAC;aACT,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC,CAAC;aAC/E,QAAQ,CACP,mHAAmH,CACpH;KACJ,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,gBAAgB;YACxB,IAAI,EAAE,gBAAgB,CAAC,kBAAkB;YACzC,IAAI,EAAE,4EAA4E;YAClF,SAAS,EAAE,IAAI;YACf,QAAQ,EACN,oIAAoI;SACvI;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,MAAM,GAAG,GAAG,uBAAuB,EAAE,CAAC;QAEtC,iCAAiC;QACjC,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,UAAU,CAC1C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,CAAC,CAAC,CACpF,CAAC;QAEF,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAClC,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,IAAI,SAAS,GAAG,CAAC,CAAC;QAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAW,CAAC;YAC5C,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAE9B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACzD,yEAAyE;gBACzE,IAAI,MAAM,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;oBAClC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAe,CAAC;oBACnC,+CAA+C;oBAC/C,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;wBAC7C,MAAM,kBAAkB,CACtB,2BAA2B,OAAO,KAAK,GAAG,CAAC,OAAO,EAAE,EACpD,EAAE,OAAO,EAAE,EACX,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBACzC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACxB,SAAS;YACX,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;YACzB,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBACzC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC7C,SAAS,EAAE,CAAC;YACd,CAAC;QACH,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,8BAA8B,EAAE;YAC3C,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;YAC5B,SAAS;YACT,SAAS,EAAE,SAAS,CAAC,MAAM;SAC5B,CAAC,CAAC;QAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa;YACtB,0BAA0B,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW;SAChF,CAAC;QAEF,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CACR,kBAAkB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,yCAAyC,CACvF,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;YACvF,OAAO,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;QAED,yDAAyD;QACzD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;QAC5F,KAAK,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;QAC5F,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY;gBACzB,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACxD,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;YAC3B,MAAM,YAAY,GAChB,CAAC,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAChF,KAAK,CAAC,IAAI,CACR,KAAK,IAAI,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,gBAAgB,IAAI,KAAK,MAAM,CAAC,CAAC,UAAU,IAAI,KAAK,MAAM,CAAC,CAAC,cAAc,IAAI,KAAK,MAAM,YAAY,IAAI,CACvJ,CAAC;QACJ,CAAC;QAED,kBAAkB;QAClB,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,CACR,wGAAwG,CACzG,CAAC;QACF,KAAK,CAAC,IAAI,CACR,uGAAuG,CACxG,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;YACtD,MAAM,GAAG,GAAG,CAAC,CAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC7E,KAAK,CAAC,IAAI,CACR,KAAK,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAC9L,CAAC;QACJ,CAAC;QAED,uBAAuB;QACvB,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,CAAC,YAAY,GAAG,GAAG,CAC5D,CAAC;QACF,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CACR,gCAAgC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,iCAAiC,CACpI,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAC;QAE7F,OAAO,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tool definition for fetching a food product by barcode from Open Food Facts.
|
|
3
|
+
* @module mcp-server/tools/definitions/get-product
|
|
4
|
+
*/
|
|
5
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
6
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
7
|
+
export declare const offGetProductTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
8
|
+
barcode: z.ZodString;
|
|
9
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
10
|
+
categories_tags: "categories_tags";
|
|
11
|
+
labels_tags: "labels_tags";
|
|
12
|
+
product_name: "product_name";
|
|
13
|
+
brands: "brands";
|
|
14
|
+
quantity: "quantity";
|
|
15
|
+
ingredients_text: "ingredients_text";
|
|
16
|
+
ingredients: "ingredients";
|
|
17
|
+
allergens_tags: "allergens_tags";
|
|
18
|
+
additives_tags: "additives_tags";
|
|
19
|
+
nutriscore_grade: "nutriscore_grade";
|
|
20
|
+
nova_group: "nova_group";
|
|
21
|
+
ecoscore_grade: "ecoscore_grade";
|
|
22
|
+
nutriments: "nutriments";
|
|
23
|
+
packaging_tags: "packaging_tags";
|
|
24
|
+
origins_tags: "origins_tags";
|
|
25
|
+
image_url: "image_url";
|
|
26
|
+
completeness: "completeness";
|
|
27
|
+
data_quality_tags: "data_quality_tags";
|
|
28
|
+
}>>>;
|
|
29
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
30
|
+
barcode: z.ZodString;
|
|
31
|
+
found: z.ZodBoolean;
|
|
32
|
+
product: z.ZodOptional<z.ZodObject<{
|
|
33
|
+
product_name: z.ZodOptional<z.ZodString>;
|
|
34
|
+
brands: z.ZodOptional<z.ZodString>;
|
|
35
|
+
quantity: z.ZodOptional<z.ZodString>;
|
|
36
|
+
ingredients_text: z.ZodOptional<z.ZodString>;
|
|
37
|
+
ingredients: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
38
|
+
id: z.ZodOptional<z.ZodString>;
|
|
39
|
+
text: z.ZodString;
|
|
40
|
+
percent_estimate: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
vegan: z.ZodOptional<z.ZodString>;
|
|
42
|
+
vegetarian: z.ZodOptional<z.ZodString>;
|
|
43
|
+
}, z.core.$strip>>>;
|
|
44
|
+
allergens_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
45
|
+
additives_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
|
+
nutriscore_grade: z.ZodOptional<z.ZodString>;
|
|
47
|
+
nova_group: z.ZodOptional<z.ZodNumber>;
|
|
48
|
+
ecoscore_grade: z.ZodOptional<z.ZodString>;
|
|
49
|
+
nutriments: z.ZodOptional<z.ZodObject<{
|
|
50
|
+
energy_kcal_100g: z.ZodOptional<z.ZodNumber>;
|
|
51
|
+
fat_100g: z.ZodOptional<z.ZodNumber>;
|
|
52
|
+
saturated_fat_100g: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
carbohydrates_100g: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
sugars_100g: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
fiber_100g: z.ZodOptional<z.ZodNumber>;
|
|
56
|
+
proteins_100g: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
salt_100g: z.ZodOptional<z.ZodNumber>;
|
|
58
|
+
sodium_100g: z.ZodOptional<z.ZodNumber>;
|
|
59
|
+
energy_kcal_serving: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
fat_serving: z.ZodOptional<z.ZodNumber>;
|
|
61
|
+
sugars_serving: z.ZodOptional<z.ZodNumber>;
|
|
62
|
+
}, z.core.$strip>>;
|
|
63
|
+
categories_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
64
|
+
labels_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
65
|
+
packaging_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
66
|
+
origins_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
67
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
68
|
+
completeness: z.ZodOptional<z.ZodNumber>;
|
|
69
|
+
data_quality_tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
70
|
+
}, z.core.$strip>>;
|
|
71
|
+
}, z.core.$strip>, readonly [{
|
|
72
|
+
readonly reason: "not_found";
|
|
73
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
74
|
+
readonly when: "Barcode status:0 — not present in any contributor record";
|
|
75
|
+
readonly recovery: "Try off_search_products with the product name or brand to find the correct barcode, or check that the barcode digits are correct.";
|
|
76
|
+
}, {
|
|
77
|
+
readonly reason: "upstream_error";
|
|
78
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
79
|
+
readonly when: "Open Food Facts API returns 5xx or is unreachable";
|
|
80
|
+
readonly retryable: true;
|
|
81
|
+
readonly recovery: "Retry after a brief pause. If persistent, the Open Food Facts service may be experiencing high load.";
|
|
82
|
+
}], undefined>;
|
|
83
|
+
//# sourceMappingURL=get-product.tool.d.ts.map
|
|
@@ -0,0 +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;AAqDjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA0W5B,CAAC"}
|