Skip to main content
Glama
domdomegg

openfoodfacts-mcp

upload_image

Upload product images to Open Food Facts database to enhance food information with visual data like ingredients, nutrition labels, and packaging details.

Instructions

Upload a product image to Open Food Facts. Requires OFF_USER_ID and OFF_PASSWORD.

Prefer more photos over fewer. Panels with text (ingredients, nutrition, certifications, recycling instructions) are highest value as OFF can OCR them. Plain sides with just a colour or logo are lowest value but still worth uploading if you have them.

Use the most appropriate imagefield (front, ingredients, nutrition, packaging). Use "other" for additional photos — this uploads without selecting the image as a display image, which is useful when a good display image already exists or for supplementary angles.

The OFF server auto-selects images for front/nutrition/ingredients/packaging on upload unless one is already selected. If you get "status not ok" but a positive imgid, the image uploaded successfully but was not selected (e.g. a display image already exists).

For images on disk, base64-encode them first (e.g. via shell: base64 -i photo.jpg).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
barcodeYesProduct barcode
imagefieldYesImage type
image_dataYesBase64-encoded image data (JPEG or PNG)
lcNoLanguage code for the image (default: en)en

Implementation Reference

  • The handler function for the upload_image tool. It processes the base64 input, constructs the multipart form data, and submits it to the OFF API.
    async (args) => {
    	const imageBuffer = Buffer.from(args.image_data, 'base64');
    
    	const formData = new FormData();
    	formData.set('code', args.barcode);
    	formData.set('imagefield', `${args.imagefield}_${args.lc}`);
    	formData.set(`imgupload_${args.imagefield}_${args.lc}`, new Blob([imageBuffer]), 'image.jpg');
    
    	const data = await offPostMultipart(config, '/cgi/product_image_upload.pl', formData);
    
    	return jsonResult(data as Record<string, unknown>);
    },
  • The Zod schema defining the input arguments for the upload_image tool.
    const inputSchema = strictSchemaWithAliases(
    	{
    		barcode: z.string().describe('Product barcode'),
    		imagefield: z.enum([
    			'front',
    			'ingredients',
    			'nutrition',
    			'packaging',
    			'other',
    		]).describe('Image type'),
    		image_data: z.string().describe('Base64-encoded image data (JPEG or PNG)'),
    		lc: z.string().default('en').describe('Language code for the image (default: en)'),
    	},
    	{
    		code: 'barcode',
    		type: 'imagefield',
    	},
    );
  • Function to register the 'upload_image' tool with the MCP server.
    export function registerUploadImage(server: McpServer, config: Config): void {
    	server.registerTool(
    		'upload_image',
    		{
    			title: 'Upload product image',
    			description: 'Upload a product image to Open Food Facts. Requires OFF_USER_ID and OFF_PASSWORD.\n\nPrefer more photos over fewer. Panels with text (ingredients, nutrition, certifications, recycling instructions) are highest value as OFF can OCR them. Plain sides with just a colour or logo are lowest value but still worth uploading if you have them.\n\nUse the most appropriate imagefield (front, ingredients, nutrition, packaging). Use "other" for additional photos — this uploads without selecting the image as a display image, which is useful when a good display image already exists or for supplementary angles.\n\nThe OFF server auto-selects images for front/nutrition/ingredients/packaging on upload unless one is already selected. If you get "status not ok" but a positive imgid, the image uploaded successfully but was not selected (e.g. a display image already exists).\n\nFor images on disk, base64-encode them first (e.g. via shell: `base64 -i photo.jpg`).',
    			inputSchema,
    			annotations: {
    				readOnlyHint: false,
    			},
    		},
    		async (args) => {
    			const imageBuffer = Buffer.from(args.image_data, 'base64');
    
    			const formData = new FormData();
    			formData.set('code', args.barcode);
    			formData.set('imagefield', `${args.imagefield}_${args.lc}`);
    			formData.set(`imgupload_${args.imagefield}_${args.lc}`, new Blob([imageBuffer]), 'image.jpg');
    
    			const data = await offPostMultipart(config, '/cgi/product_image_upload.pl', formData);
    
    			return jsonResult(data as Record<string, unknown>);
    		},
    	);
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/domdomegg/openfoodfacts-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server