DEV Community

Busybody
Busybody

Posted on

Your model is inventing macros. Make it look the food up.

I build Calorie API. Same food catalog, two doors. A REST API for the app you ship. An MCP server for Claude Code and Cursor.

You ask for the calories in 180 g of cooked chicken breast. The chat answers in one second. The number looks tidy. The model remembered a textbook row, picked a serving you did not weigh, and never opened a database.

That guess is fine in a chat. It is a bad base for a meal log, a recipe card, or an app a stranger will trust.

Two jobs, one catalog

You are shipping a food app. You need search, a stable food id, macros per 100 g, and a barcode. The model does not belong in that request.

You already live in Claude Code or Cursor. You want the assistant to look the food up, do the math, and show its work.

The catalog is 4M+ foods: generic foods, branded products, and restaurant items. A row is macros per 100 g, so a portion is a scale. I have not published a hit-rate study, and I have not published a photo-accuracy study. If a page quotes a percent for either, that number is not ours. The requests below are things you can run yourself.

Door 1. The food database, for the app

The REST API has a free tier of 1,000 calls a month. No card.

curl "https://calorieapiadmin.com/api/v1/search/foods?q=greek+yogurt&limit=5&verified_only=true" \
  -H "X-API-Key: YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

You get a page of foods. Each one has an id and macros per 100 g. verified_only=true keeps the list to curated rows with complete macros.

Three calls cover a logger:

  1. GET /api/v1/search/suggest?q=oatm while the user types. Debounce it. One request per pause.
  2. GET /api/v1/foods/{id} when they pick a row. That route adds the nutrient list and the serving data.
  3. GET /api/v1/search/barcode/{upc} for a UPC or EAN. A miss falls through to Open Food Facts in the same JSON shape.

Keep the key on your server. A shipped mobile binary can be opened. Store the food id, not the name. Names collide. Ids do not.

The request list, filters, and field names are on the food database API page. The homepage runs a live search before you create a key. Paid plans start at $15 a month for 20,000 calls. An app other people use in production needs Plus or Enterprise, and the header X-API-Usage-Type: commercial.

Door 2. The MCP server, for the assistant

Calorie MCP is that catalog behind eight tools. Nothing to install. The assistant writes the answer from the tool result.

This plan is separate from REST. A REST key is refused by the MCP server. An MCP key gets 403 on the REST routes. Personal use is $29 a month, or $228 a year. The trial is 7 days and needs a card. You are charged when it ends unless you cancel first.

The host looks internal. It is the public URL:

https://calorieapiadmin.com/mcp/

Claude Code and Cursor connect, because they can send a header. Claude.ai, Claude Desktop, and Claude mobile stay closed until OAuth is on. It is not on.

Claude Code

claude mcp add --transport http calorie-api \
  https://calorieapiadmin.com/mcp/ \
  --header "X-API-Key: YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

Cursor

{
  "mcpServers": {
    "calorie-api": {
      "url": "https://calorieapiadmin.com/mcp/",
      "headers": { "X-API-Key": "YOUR_KEY" }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The key is shown once, in the dashboard. It is not emailed. Leave it out of the repo.

The eight tools

Tool What comes back
search_foods Matches, macros per 100 g, and a food_id
get_food_nutrition The full nutrient list for that id
suggest_foods Short name suggestions
lookup_barcode A UPC or EAN, as macros per 100 g
calculate_portion One food, scaled to a gram weight
calculate_recipe Totals and per serving, up to 40 foods
calculate_macro_targets A daily target from age, sex, weight, height, activity, and goal
analyze_food_photo Foods spotted in a JPEG, PNG, or WebP

Paid limits are 20 calls a minute, 10,000 successful calls a month, 25 foods per search, and 150 photos a month. The trial is 5 calls a minute, 200 calls total, 10 results, and 10 photos.

The rule that stops the invention

food_id comes from search_foods. The portion tool, the recipe tool, and the nutrient tool all require that id. An invented id gets an error. That error is the product. Scaling a row that does not exist is worse than a failed call.

How many calories and how much protein are in 180 g of cooked chicken breast?
Search the catalog first, then scale it. Do not answer from memory.
Enter fullscreen mode Exit fullscreen mode

A meal, with the banana called out so the assumed weight is visible:

Log this and give me the totals: 220 g plain skyr, 60 g dry oats, one medium banana.
Search the catalog for each item, tell me the gram weight you assumed for the banana,
and scale each one with the portion tool.
Enter fullscreen mode Exit fullscreen mode

A barcode. A 12-digit code often wants a leading zero.

Look up barcode 5000112637922. If a 12-digit code misses, try it again with a
leading zero before you tell me it is not there.
Enter fullscreen mode Exit fullscreen mode

The photo has to ride inside the tool call

A picture pasted into the chat stays with the model. The server never sees it. The bytes have to be an argument.

Read ./lunch.jpg, encode it as base64, and pass it to the photo tool as image_base64
with content_type image/jpeg. Then search each food it names and scale it to the
weight you estimated.
Enter fullscreen mode Exit fullscreen mode

Raw base64. No data: prefix. JPEG, PNG, or WebP. Up to 2 MB. A URL is refused.

There is no published accuracy figure for that photo tool. Use it as a first pass. Search and scale the foods it names. The catalog row is the number. The photo is the hint.

What you still own

The server keeps no food diary. The log stays in your file or your app.

calculate_macro_targets is a formula. It is not a lab test and it is not medical advice. A pregnancy, a medical condition, or an eating-disorder history needs a qualified person to review any plan the chat writes.

An MCP key is for your own assistant. An app other people pay for needs the REST plan and a commercial license.

Pick a door

Shipping the app: start on the free tier and use the food database API.

Logging inside Claude Code or Cursor: start the trial on Calorie MCP.

Same foods. The app calls HTTP. The assistant calls tools. The calorie count comes from a row.

Prices and limits above are for October 2026.

Top comments (0)