Skip to content

Building a Personal Nutrition Agent on Claude and MCP

Published September 7, 2026

Every post in this series so far has described one interaction: log a meal, total a recipe, plan a week. This one assembles them into a thing that runs continuously, and is specific about which parts are genuinely an agent and which parts are a text file doing the heavy lifting.

The short version: the tools give you lookups, and the file gives you memory. Neither is impressive alone. Together they are most of what a nutrition app does, in something you own.

What is actually doing the work

Be clear about the architecture, because the word "agent" gets used to mean almost anything.

The MCP server provides eight stateless lookups. It remembers nothing between calls. It has no idea who you are beyond which plan your key is on. Everything about you lives on your side.

The client, Claude Code or Cursor, supplies the loop: it reads your files, decides which tool to call, calls it, reads the result, and writes.

The memory file is the part people skip, and it is the part that turns a chat into an agent. Without it you re-explain yourself every session. With it the assistant starts every conversation already knowing your targets, your foods, your recipes and your history.

The server is the small piece. The file is the product.

The file layout

One file is fine to start; split it when it gets unwieldy. In Claude Code, a markdown file in the working directory is read automatically, which is the least friction available. Cursor's project rules work the same way.

# Nutrition agent

## Standing instructions
- Always call search_foods before quoting a macro. Never estimate from memory.
- If a lookup misses, say so and ask for the label. Do not substitute a
  similar generic row.
- Cross-check every row with the 4/4/9 rule. Flag a gap over 20%.
- State the gram weight you assumed for anything I described without one.
- Append to the Log, never rewrite it. Mark estimated entries.

## Profile
- 34, male, 82 kg, 180 cm. Lifts 4x/week, desk job.
- Goal: fat loss. Target 2,150 kcal, 175 g protein.
- Allergy: shellfish. Vegetarian on weekdays.
- Dislikes: cottage cheese, tuna.

## Core foods (per 100 g)
| Food | kcal | P | F | C | food_id |

## Recipes (per serving)
| Name | servings | basis | kcal | P | F | C |

## Pantry (per 100 g, by barcode)
| Barcode | Item | kcal | P | F | C |

## Restaurant estimates
| Place | Order | basis | kcal | P |

## Log

Each of those sections has a post behind it: core foods and the twenty-item list in the grocery list post, recipes in recipe macros without a spreadsheet, pantry rows in barcode lookup inside Claude, restaurant estimates in estimating restaurant meal macros, and the log itself in calorie tracking in Claude.

Standing instructions are the interesting part

The five lines at the top of that file are what stop the agent from being confidently wrong, and each one exists because of a specific failure.

Always search first. Without this the assistant will sometimes answer a food question directly, because it is faster and it feels helpful. That is the entire failure mode this product exists to fix, and it comes back the moment you stop asking for a lookup.

Say when a lookup misses. The unhelpful behaviour is substituting a plausible generic row for the specific product you asked about. You end up with a number and no idea it was a substitution.

Cross-check with 4/4/9. Protein and carbohydrate at roughly 4 kcal per gram, fat at roughly 9, compared against the stated calories. Catches transcription errors in crowd-contributed rows, which is where the barcode fallback's bad data lives.

State assumed weights. "One medium banana" becomes a gram figure somewhere. If the assumption is not stated, the estimate cannot be corrected, and portion estimation is where nearly all of the error lives.

Append, never rewrite. An assistant asked to tidy a log will sometimes helpfully reformat history. That is data loss. Say append.

The honest caveat: these are instructions in a prompt, not enforcement. Compliance is high and it is not total. For preferences that is fine. For an allergy it is not. Read the ingredient list on anything unfamiliar yourself, every time, regardless of what the file says.

The daily and weekly rhythm

Morning, one line: what am I eating today? The agent reads profile, core foods, recipes and yesterday's log, and proposes a day that hits the targets.

After each meal, one line: what you ate. Mostly this costs nothing, because most of what you eat is already in the core foods, recipes and pantry tables. Only genuinely new food triggers a lookup. This is the property that makes the whole thing cheap to run.

Evening: totals against target and one observation.

Weekly: the review. Days logged, average calories, average protein, weekly average weight. Zero tool calls, because it is text processing on a file. The order in which to read those four numbers is in the cut post.

Monthly: ask it to re-resolve the core food list, because a maintained catalog does correct rows, and to prune recipes you have stopped making.

Splitting the file when it outgrows one page

One file works until it does not. The tables that grow are core foods, recipes and the log, and they grow at very different rates.

The natural split is by how often a section changes:

  • nutrition.md: standing instructions and profile. Changes monthly at most. This is the one the client must always read.
  • foods.md: core foods, pantry rows, restaurant estimates. Changes weekly.
  • recipes.md: one heading per recipe with its ingredients, serving basis and per-serving row. Grows slowly and permanently.
  • log-2026.md: the log, one file per year. Append-only.

The reason to split on change frequency rather than on topic is that it keeps what the assistant must read every session small. A three-year log in the file the client loads on startup is a lot of context spent on history you are not asking about. Keep the log separate and ask for it by name when you want a review.

Version control is worth the two minutes it takes to set up. A nutrition log in git gives you a diff for every correction, which turns "did I change that entry?" from a memory question into a command.

A worked week

To make the rhythm concrete, a normal week for a running agent:

Monday. Plan from the core foods and three saved recipes. Mostly no tool calls, because everything is already resolved. One shopping list falls out, as in the grocery list post.

Tuesday to Thursday. Log as you eat. New food appears perhaps twice: a lookup each, saved into foods.md on the spot so it never costs a call again.

Friday. Dinner out. One reconstruction, marked as estimated, saved to the restaurant table if it is somewhere you go regularly.

Saturday. Batch cook. One recipe call, saved per-serving row, four meals covered.

Sunday. The review. Zero tool calls. Four numbers in order: days logged, average calories, average protein, weekly average weight.

Total tool spend for the week: somewhere around a dozen calls, nearly all of them on Tuesday to Thursday's genuinely new foods. Against 20 a minute and 10,000 successful calls a month, that is nothing, which is the point. A mature agent is cheap. It is the first fortnight, resolving the core list and the pantry, that costs anything.

What it gets wrong

It drifts on long threads. Instructions given twenty messages ago compete with everything since. The fix is the file, not a longer reminder, and starting a fresh session more often than feels necessary.

It is agreeable. Ask whether your plan is good and it will tend to find it good. Ask what is wrong with this plan and you get something useful. Phrase reviews adversarially.

It rationalises. Given a day that missed target, it will explain why that is fine. Sometimes true. Ask for the number, not the interpretation.

It cannot see you. No labs, no medication, no sleep, no menstrual cycle, no training log unless you put one in the file. It is working from what you wrote down.

It is not clinical. A therapeutic diet (renal, coeliac, insulin-dosed diabetes, an eating-disorder history, pregnancy) needs a qualified human reviewing the plan. This is not a formality; those diets are managing things a calorie total does not represent.

Why a file rather than an app

The trade is worth stating plainly, because for many people the app is the better answer.

What you get from the file: your data in a format that opens anywhere, in ten years, with no export step. Corrections are edits. You can grep it, chart it, hand it to a dietitian, or move it to a different assistant entirely. The server keeps no history, so there is nothing to be locked into.

What you give up: a barcode scanner, a phone app, graphs, reminders, streaks, and anything social. The server holds no history, which means no cross-device sync and no recovery if you lose the file. Back it up. Put it in version control if that is natural for you. A nutrition log in git is a genuinely nice thing, since every correction is visible.

Connect it

Claude Code:

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

Cursor:

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

Browser sign-in for Claude apps is off on this server until OAuth is enabled, so those two clients with the header. The MCP page has the overview, the docs the full argument reference, and MCP pricing the plan and the 7-day trial. Between the two clients Claude Code has the edge for this specific setup, because file reading and writing is the whole mechanism.

A mature agent costs very few calls, because the file absorbs the repetition, and most days are a handful of lookups for genuinely new foods. Which means the practical limit on this setup is not the plan, it is whether you keep the file up to date.

What we have not measured

We have not run this agent for a quarter and published what it got wrong, how often the standing instructions were ignored, or how the file degraded. We have not measured tool-selection accuracy, meaning how often the assistant picks the right tool with the right arguments on the first attempt, which is the number that would tell you how good the agent actually is.

The failure modes listed above are observations about how assistants behave in general, not counted rates from a logged trial. When we measure tool-selection accuracy, the prompt set and the scoring method will be published with it.

Frequently Asked Questions

What makes this an agent rather than a chat?

The memory file. The MCP server is eight stateless lookups that remember nothing, and the client supplies the loop. A markdown file the client reads automatically is what carries your targets, foods, recipes and history between sessions, so you stop re-explaining yourself.

What should the standing instructions say?

Always search before quoting a macro; say so when a lookup misses instead of substituting a generic row; cross-check rows with the 4/4/9 rule; state assumed gram weights; append to the log rather than rewriting it. Each one exists because of a specific observed failure.

Are those instructions actually enforced?

No. They are instructions in a prompt. Compliance is high and not total, which is fine for preferences and not good enough for an allergy. Read the ingredient list on anything unfamiliar yourself, every time, regardless of what the file says.

Why keep a file instead of using an app?

Your data opens anywhere with no export step, corrections are edits, and nothing is locked in because the server keeps no history. What you give up is a barcode scanner, a phone app, graphs, reminders and sync. Back the file up, or keep it in version control.

Does running an agent use a lot of tool calls?

Less over time, not more. Once core foods, recipes and pantry items are saved in the file, most entries cost nothing and only genuinely new foods trigger a lookup. The practical limit is whether you keep the file current, not the plan limits.

← Back to all articles

Start building with the Calorie API

Get a free API key and access 4M+ foods with search, barcode lookup, and full macro data.