<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Busybody</title>
    <description>The latest articles on DEV Community by Busybody (@busybody).</description>
    <link>https://dev.to/busybody</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4169383%2F45c7bb6c-61ad-4605-bc16-23a6c6a4ca1f.png</url>
      <title>DEV Community: Busybody</title>
      <link>https://dev.to/busybody</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/busybody"/>
    <language>en</language>
    <item>
      <title>Your model is inventing macros. Make it look the food up.</title>
      <dc:creator>Busybody</dc:creator>
      <pubDate>Wed, 07 Oct 2026 16:37:18 +0000</pubDate>
      <link>https://dev.to/busybody/your-model-is-inventing-macros-make-it-look-the-food-up-27c9</link>
      <guid>https://dev.to/busybody/your-model-is-inventing-macros-make-it-look-the-food-up-27c9</guid>
      <description>&lt;p&gt;I build &lt;a href="https://calorieapi.com" rel="noopener noreferrer"&gt;Calorie API&lt;/a&gt;. Same food catalog, two doors. A REST API for the app you ship. An MCP server for Claude Code and Cursor.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two jobs, one catalog
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You are shipping a food app.&lt;/strong&gt; You need search, a stable food id, macros per 100 g, and a barcode. The model does not belong in that request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You already live in Claude Code or Cursor.&lt;/strong&gt; You want the assistant to look the food up, do the math, and show its work.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Door 1. The food database, for the app
&lt;/h2&gt;

&lt;p&gt;The REST API has a free tier of 1,000 calls a month. No card.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://calorieapiadmin.com/api/v1/search/foods?q=greek+yogurt&amp;amp;limit=5&amp;amp;verified_only=true"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: YOUR_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Three calls cover a logger:&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The request list, filters, and field names are on the &lt;a href="https://calorieapi.com/food-database-api" rel="noopener noreferrer"&gt;food database API&lt;/a&gt; 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 &lt;code&gt;X-API-Usage-Type: commercial&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Door 2. The MCP server, for the assistant
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://calorieapi.com/mcp" rel="noopener noreferrer"&gt;Calorie MCP&lt;/a&gt; is that catalog behind eight tools. Nothing to install. The assistant writes the answer from the tool result.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The host looks internal. It is the public URL:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://calorieapiadmin.com/mcp/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http calorie-api &lt;span class="se"&gt;\&lt;/span&gt;
  https://calorieapiadmin.com/mcp/ &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: YOUR_KEY"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"calorie-api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://calorieapiadmin.com/mcp/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"X-API-Key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_KEY"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is shown once, in the dashboard. It is not emailed. Leave it out of the repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  The eight tools
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What comes back&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;search_foods&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Matches, macros per 100 g, and a &lt;code&gt;food_id&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_food_nutrition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The full nutrient list for that id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;suggest_foods&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Short name suggestions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lookup_barcode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A UPC or EAN, as macros per 100 g&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calculate_portion&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One food, scaled to a gram weight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calculate_recipe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Totals and per serving, up to 40 foods&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;calculate_macro_targets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A daily target from age, sex, weight, height, activity, and goal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;analyze_food_photo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Foods spotted in a JPEG, PNG, or WebP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  The rule that stops the invention
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;food_id&lt;/code&gt; comes from &lt;code&gt;search_foods&lt;/code&gt;. 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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A meal, with the banana called out so the assumed weight is visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A barcode. A 12-digit code often wants a leading zero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The photo has to ride inside the tool call
&lt;/h3&gt;

&lt;p&gt;A picture pasted into the chat stays with the model. The server never sees it. The bytes have to be an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Raw base64. No &lt;code&gt;data:&lt;/code&gt; prefix. JPEG, PNG, or WebP. Up to 2 MB. A URL is refused.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you still own
&lt;/h2&gt;

&lt;p&gt;The server keeps no food diary. The log stays in your file or your app.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;calculate_macro_targets&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;An MCP key is for your own assistant. An app other people pay for needs the REST plan and a commercial license.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick a door
&lt;/h2&gt;

&lt;p&gt;Shipping the app: start on the free tier and use the &lt;a href="https://calorieapi.com/food-database-api" rel="noopener noreferrer"&gt;food database API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Logging inside Claude Code or Cursor: start the trial on &lt;a href="https://calorieapi.com/mcp" rel="noopener noreferrer"&gt;Calorie MCP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Same foods. The app calls HTTP. The assistant calls tools. The calorie count comes from a row.&lt;/p&gt;

&lt;p&gt;Prices and limits above are for October 2026.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>api</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
