call_api
Make direct API calls to Open Food Facts endpoints to retrieve food data or update product information using structured JSON or form-encoded parameters.
Instructions
Make a direct call to any Open Food Facts API endpoint. Use get_api_docs to see available endpoints. Auth credentials are included automatically for write operations if configured.
Two body modes for writes:
params: form-encoded (for /cgi/.pl and /api/v2/ legacy endpoints)
json_body: raw JSON (for /api/v3/* endpoints — required for structured fields like packagings)
Example v3 packagings write: method: PATCH endpoint: /api/v3/product/0123456789012 json_body: {"fields":"packagings","product":{"packagings":[{"number_of_units":1,"shape":{"id":"en:bag"},"material":{"id":"en:plastic"},"recycling":{"id":"en:recycle"}}]}}
WARNING: Do NOT use old-style prepared nutrition params like nutriment_fat_prepared — they have a known server bug that stores data incorrectly. Use new-style params instead: nutrition_input_sets_prepared_100g_nutrients_fat_value_string=0.5
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| method | No | HTTP method (default: GET) | GET |
| endpoint | Yes | API endpoint path (e.g. "/api/v2/product/3017620422003.json") | |
| params | No | Query parameters (for GET) or form-encoded body fields (for POST/PUT/PATCH to v1/v2 endpoints like /cgi/product_jqm2.pl). Auth fields are added automatically. | |
| json_body | No | Raw JSON body for v3 endpoints (e.g. PATCH /api/v3/product/{code}). When set, params is ignored and Content-Type is application/json. Auth fields are injected at the top level. Use this for structured writes like packagings. |
Implementation Reference
- src/tools/call-api.ts:50-55 (handler)The handler logic for the 'call_api' tool, which uses 'offRequest' to execute the API call and returns a JSON result.
async (args) => { const data = await offRequest(config, args.method, args.endpoint, args.params, args.json_body); return jsonResult(data as Record<string, unknown>); }, ); - src/tools/call-api.ts:8-26 (schema)The Zod input schema defining the parameters for the 'call_api' tool.
const inputSchema = strictSchemaWithAliases( { method: z.enum([ 'GET', 'POST', 'PUT', 'PATCH', 'DELETE', ]).default('GET').describe('HTTP method (default: GET)'), endpoint: z.string().describe('API endpoint path (e.g. "/api/v2/product/3017620422003.json")'), params: z.record(z.string()).optional().describe('Query parameters (for GET) or form-encoded body fields (for POST/PUT/PATCH to v1/v2 endpoints like /cgi/product_jqm2.pl). Auth fields are added automatically.'), json_body: z.record(z.unknown()).optional().describe('Raw JSON body for v3 endpoints (e.g. PATCH /api/v3/product/{code}). When set, params is ignored and Content-Type is application/json. Auth fields are injected at the top level. Use this for structured writes like packagings.'), }, { path: 'endpoint', url: 'endpoint', body: 'json_body', }, ); - src/tools/call-api.ts:28-56 (registration)The function that registers the 'call_api' tool with the MCP server.
export function registerCallApi(server: McpServer, config: Config): void { server.registerTool( 'call_api', { title: 'Call API', description: `Make a direct call to any Open Food Facts API endpoint. Use get_api_docs to see available endpoints. Auth credentials are included automatically for write operations if configured. Two body modes for writes: - params: form-encoded (for /cgi/*.pl and /api/v2/* legacy endpoints) - json_body: raw JSON (for /api/v3/* endpoints — required for structured fields like packagings) Example v3 packagings write: method: PATCH endpoint: /api/v3/product/0123456789012 json_body: {"fields":"packagings","product":{"packagings":[{"number_of_units":1,"shape":{"id":"en:bag"},"material":{"id":"en:plastic"},"recycling":{"id":"en:recycle"}}]}} WARNING: Do NOT use old-style prepared nutrition params like nutriment_fat_prepared — they have a known server bug that stores data incorrectly. Use new-style params instead: nutrition_input_sets_prepared_100g_nutrients_fat_value_string=0.5`, inputSchema, annotations: { readOnlyHint: false, }, }, async (args) => { const data = await offRequest(config, args.method, args.endpoint, args.params, args.json_body); return jsonResult(data as Record<string, unknown>); }, ); }