Skip to main content
Glama

update_meal

Destructive

Update an existing meal. Use only when the current message explicitly changes, corrects, or adds to a meal already logged. Never infer an update from earlier chat history. A plain food statement ("coffee with milk") is a new entry: use log_meal, even if that meal type already exists today.

FIND THE MEAL: use id if known. Otherwise use date (YYYY-MM-DD, defaults to today) plus name and/or target_meal_type to narrow the existing row. target_meal_type finds the current type and is never written; meal_type sets a new type. If the match is not exactly one row, nothing changes. On multiple matches, ask the user which meal they mean; never select a candidate id yourself. Send only fields that change.

THREE MODES. Picking the wrong one corrupts the meal.

  1. ADD SAVED FOOD -> add_recipe_name. "add my usual kombucha to breakfast", "add the protein shake I saved to lunch". Do NOT use log_meal for this, that logs a second, separate meal. Additive: the recipe's food text is appended to the meal's existing food_items and each of its macros is ADDED to the meal's current value for that field, so the result is both foods together with both foods' calories, not a replacement. Matched the same way as log_meal's recipe_name (case-insensitive exact title, then substring); no match or more than one substring match throws an error naming the candidates or the user's saved titles instead of guessing. If the matched recipe has no stored value for one of calories/protein_g/fat_g/carbs_g, this throws carrying the recipe's food text: estimate just the missing field(s) and call again with the same id (or date+name) and add_recipe_name plus those field(s) set explicitly. An explicit field passed alongside add_recipe_name takes the recipe's place for that one field and is still ADDED to the meal; it does not overwrite the meal's total the way it does without add_recipe_name.

  2. ADD UNSAVED FOOD -> add_food_items. "add a banana to my breakfast", "I also had a small coffee", where the extra food is not one of the user's saved recipes. Pass the new food's own description plus calories/protein_g/fat_g/carbs_g estimated for JUST that new food, not the meal's new total and not the existing food's macros. All four are required whenever add_food_items is set (there is no recipe to fall back on): estimate them from the description, never ask the user. Additive exactly like add_recipe_name: add_food_items is appended to the existing food_items (unless food_items is ALSO passed explicitly, which replaces the description outright instead of appending) and each macro is ADDED to the meal's current value; alcohol_g is optional and adds nothing when omitted. Set both add_recipe_name and add_food_items in one call to add a saved recipe and separate ad-hoc food together; when both are set, calories/protein_g/fat_g/carbs_g/alcohol_g are read as add_food_items's own macros only, and the recipe always contributes its own stored values.

  3. CORRECT A VALUE -> plain fields, both add_* unset. "that was 400 calories, not 600", "actually it was just eggs, no toast", "make it 500 calories": the meal's stored total needs to become a specific NEW number, not grow. Each of food_items/calories/protein_g/fat_g/carbs_g/alcohol_g you pass REPLACES the meal's current value for that field outright, so send the corrected TOTAL for that field, never an amount to add.

Reaching for mode 3 when the meal is GROWING is the exact bug this tool used to have: it silently REPLACES the whole meal with just the new food and throws away what was already logged.

SATURATED FAT / FIBER: saturated_fat_g and fiber_g follow the same REPLACE-vs-ADD rule as the other macros above (REPLACE the meal's total in mode 3, or ADD as the new component's own value in an add_recipe_name/add_food_items fold), but are always optional and never fabricated -- see log_meal's SATURATED FAT / FIBER for when to populate them. A saved recipe never carries these two fields, so folding one in (add_recipe_name, without an explicit override) never changes the meal's own stored value for them; it only marks the meal's existing total as covering less than the whole meal, since food was added without a known contribution.

If add-vs-correct intent is ambiguous, ask before updating.

MOVE TO A DIFFERENT DATE -> move_to_date. "move Tuesday's lunch to Wednesday": date/name/target_meal_type only SELECT which meal to update; they never move it. Set move_to_date to actually change the stored date, keeping the same id.

REMOVE ONE ADDED COMPONENT -> remove_item_name. Only works for a component previously added via add_recipe_name or add_food_items on THIS meal (it needs to know that component's exact recorded macros to subtract). If the meal has no such recorded component, this throws telling you to use mode 3 with corrected totals instead.

DRINKS / HYDRATION WHEN UPDATING: a food update must not silently erase an already-linked hydration event. For changes unrelated to drinks, omit fluids and the existing hydration is preserved. When ADDING a drink with add_food_items/add_recipe_name, fluids contains only the newly added drink(s) and they are appended to the meal's hydration. When CORRECTING the meal's drinks with both add_* fields omitted, fluids is the complete corrected drink list and replaces the linked hydration only after replacement rows have been safely inserted. If the correction removes every drink, explicitly send fluids: [] and the linked hydration is deleted. Whenever a drink volume is known or reasonably inferable, include it.

CAFFEINE / DRINKS WHEN UPDATING: keep the two sidecars explicit in the same update_meal call. fluids is the hydration side and caffeine is the caffeine side; when a drink change affects both, send both. Omit either one when that side is unchanged so existing linked data is preserved. When ADDING caffeinated food/drink with add_food_items/add_recipe_name, caffeine contains only the new dose(s) and they are appended. When CORRECTING the meal's caffeine with both add_* fields omitted, caffeine is the complete corrected dose list and replaces linked caffeine only after replacement rows have been safely inserted. If the correction removes every caffeine dose, explicitly send caffeine: []. Each retained/new dose needs caffeine_mg and may optionally include source_type; its date follows the meal date.

SAVE AS RECIPE: when the user asks to save an already-logged meal as a reusable recipe, set save_as_recipe=true. This may be the only requested action: identify the real meal with id or the normal selectors and do not invent a food or macro edit. A follow-up like "save that as a recipe" after a successful log should use the known meal id plus save_as_recipe=true. Do not tell the user recipes cannot be saved from chat.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idNoMeal ID, if already known. Alternative to date + name/target_meal_type, see FIND THE MEAL above.
dateNoDate the meal was logged. Format: YYYY-MM-DD. Used with name and/or target_meal_type to find the meal when id is omitted; defaults to today if id and date are both omitted. This only SELECTS which meal to update -- see move_to_date below to actually change a meal's stored date.
nameNoSubstring of the food description (case-insensitive) to disambiguate multiple meals on the same date. Only used when id is omitted.
fat_gNoUpdated fat in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items.
fluidsNoOptional drinks consumed in this intake. Omit when no drink amount is known. Hydration is persisted only when the user enabled hydration tracking.
carbs_gNoUpdated carbohydrates in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items.
fiber_gNoUpdated dietary fiber in grams. Optional, see SATURATED FAT / FIBER above.
caffeineNoOptional caffeine doses in this intake. Keep each dose simple: caffeine amount is required and type is optional. The dose date follows the intake/meal date. If the user gave exact milligrams, preserve them exactly; otherwise estimate from the described food or drink.
caloriesNoUpdated total calories (kcal). Optional, omit if not changing (or, with add_recipe_name, if the recipe already has a stored value). REPLACES the current value unless add_recipe_name or add_food_items is also set, in which case this is the AMOUNT BEING ADDED (the new food's own calories, not the meal's new total), added onto the meal's current value. Required whenever add_food_items is set, since there is no saved recipe to fall back on.
alcohol_gNoUpdated alcohol in grams. Same REPLACE-vs-ADD rule as calories above, except this one stays optional even with add_recipe_name or add_food_items set: omitting it just adds nothing.
meal_typeNoUpdated meal type to WRITE onto the meal (e.g. reclassify a Snack as Dinner). Optional, omit if not changing. Never inferred from add_recipe_name. Distinct from target_meal_type above, which FINDS a meal by its current type and is never written.
protein_gNoUpdated protein in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items.
food_itemsNoUpdated food description. Optional, omit if not changing. With add_recipe_name and add_food_items both omitted, this REPLACES the current description outright. With either one present and this omitted, the new food's text (the recipe's stored food_items, or add_food_items itself) is appended instead. Passing this alongside add_recipe_name/add_food_items overrides the append with this exact text.
move_to_dateNoMove this meal to a different date. Format: YYYY-MM-DD. Distinct from date above, which only finds the meal; this is what actually changes it, keeping the same id. Optional, omit if not moving the meal.
add_food_itemsNoOptional. Description of food to ADD to this meal that ISN'T a saved recipe, e.g. "a banana", "small coffee with cream" (see ADD FOOD THAT WASN'T SAVED above). Requires calories/protein_g/fat_g/carbs_g to be set to the estimated macros of just this new food -- never the meal's new total. Appends this text onto the meal's existing food_items and adds the macro fields onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). May be set together with add_recipe_name in one call, see mode 2 above.
save_as_recipeNoTrue only when the user explicitly asks to save this meal as a reusable recipe. The recipe is copied from the final persisted meal. On update_meal, this can be the only requested action; use the real meal id or normal selectors and do not invent an edit.
add_recipe_nameNoOptional. Name (or a close phrase) of one of the user's saved recipes to FOLD INTO this meal, e.g. "kombucha", "protein shake" (see FOLD IN A SAVED RECIPE above). Adds the recipe's food text and macros onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Distinct from log_meal's recipe_name, which SETS a new meal's fields instead of adding to one that already exists. May be set together with add_food_items in one call, see mode 2 above.
saturated_fat_gNoUpdated saturated fat in grams. Optional, see SATURATED FAT / FIBER above.
remove_item_nameNoName or substring of a previously-added component to remove from this meal (see REMOVE ONE ADDED COMPONENT above). Exclusive of every other field below -- only id/date/name/target_meal_type may accompany it, to select the meal.
target_meal_typeNoWhich meal type to FIND on the date, e.g. Breakfast, to disambiguate multiple meals logged that day -- "update today's breakfast" is target_meal_type: "Breakfast". Case-insensitive, only used when id is omitted. This is NEVER written to the meal; it only narrows the search, exactly like name above. Distinct from meal_type below, which SETS the new type to write. If no meal of this type is logged on the date, the call throws naming the meal types that ARE logged that day and changes nothing -- it never falls back to whichever meal the date happens to match.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYesHuman-readable result text returned by the tool.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / id / description
      Previous value: -"Meal ID only if it came from a real meal/tool result; never invent or guess it. Otherwise omit it and use date + name/target_meal_type, see FIND THE MEAL above."New value: +"Meal ID, if already known. Alternative to date + name/target_meal_type, see FIND THE MEAL above."
  2. Changed14 schema fields changed
    • changedInput schema / properties / add_food_items / description
      Previous value: -"Optional. Description of food to ADD to this meal that is not a saved recipe. Requires calories/protein_g/fat_g/carbs_g for just this new food."New value: +"Optional. Description of food to ADD to this meal that ISN'T a saved recipe, e.g. \"a banana\", \"small coffee with cream\" (see ADD FOOD THAT WASN'T SAVED above). Requires calories/protein_g/fat_g/carbs_g to be set to the estimated macros of just this new food -- never the meal's new total. Appends this text onto the meal's existing food_items and adds the macro fields onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). May be set together with add_recipe_name in one call, see mode 2 above."
    • removedInput schema / properties / add_recipe_multiplier
      Removed value: -{
      -  "description": "Positive serving multiplier for add_recipe_name, e.g. 0.5 for half or 2 for double. Omit for one saved serving.",
      -  "type": "number"
      -}
    • changedInput schema / properties / add_recipe_name / description
      Previous value: -"Optional. Name or close phrase for one saved recipe to FOLD INTO this meal. Adds the recipe food and stored macros; distinct from log_meal recipe_name."New value: +"Optional. Name (or a close phrase) of one of the user's saved recipes to FOLD INTO this meal, e.g. \"kombucha\", \"protein shake\" (see FOLD IN A SAVED RECIPE above). Adds the recipe's food text and macros onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Distinct from log_meal's recipe_name, which SETS a new meal's fields instead of adding to one that already exists. May be set together with add_food_items in one call, see mode 2 above."
    • changedInput schema / properties / alcohol_g / description
      Previous value: -"Updated alcohol in grams. Same REPLACE-vs-ADD rule as calories, optional for additions."New value: +"Updated alcohol in grams. Same REPLACE-vs-ADD rule as calories above, except this one stays optional even with add_recipe_name or add_food_items set: omitting it just adds nothing."
    • changedInput schema / properties / calories / description
      Previous value: -"Updated total calories (kcal). REPLACES unless an add_* field is present, then it is the amount for the applicable new contribution."New value: +"Updated total calories (kcal). Optional, omit if not changing (or, with add_recipe_name, if the recipe already has a stored value). REPLACES the current value unless add_recipe_name or add_food_items is also set, in which case this is the AMOUNT BEING ADDED (the new food's own calories, not the meal's new total), added onto the meal's current value. Required whenever add_food_items is set, since there is no saved recipe to fall back on."
    • changedInput schema / properties / carbs_g / description
      Previous value: -"Updated carbohydrates in grams. Same REPLACE-vs-ADD rule as calories."New value: +"Updated carbohydrates in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."
    • changedInput schema / properties / fat_g / description
      Previous value: -"Updated fat in grams. Same REPLACE-vs-ADD rule as calories."New value: +"Updated fat in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."
    • changedInput schema / properties / fiber_g / description
      Previous value: -"Updated dietary fiber in grams. Optional."New value: +"Updated dietary fiber in grams. Optional, see SATURATED FAT / FIBER above."
    • changedInput schema / properties / food_items / description
      Previous value: -"Updated food description. Optional, omit if not changing. Without add_* it REPLACES; with add_* it overrides the appended description."New value: +"Updated food description. Optional, omit if not changing. With add_recipe_name and add_food_items both omitted, this REPLACES the current description outright. With either one present and this omitted, the new food's text (the recipe's stored food_items, or add_food_items itself) is appended instead. Passing this alongside add_recipe_name/add_food_items overrides the append with this exact text."
    • changedInput schema / properties / meal_type / description
      Previous value: -"Updated meal type to WRITE onto the meal. Optional, omit if not changing. Never inferred from add_recipe_name."New value: +"Updated meal type to WRITE onto the meal (e.g. reclassify a Snack as Dinner). Optional, omit if not changing. Never inferred from add_recipe_name. Distinct from target_meal_type above, which FINDS a meal by its current type and is never written."
    • changedInput schema / properties / protein_g / description
      Previous value: -"Updated protein in grams. Same REPLACE-vs-ADD rule as calories."New value: +"Updated protein in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."
    • changedInput schema / properties / remove_item_name / description
      Previous value: -"Name or substring of a previously-added component to remove from this meal. Exclusive of every other field below; only selectors may accompany it."New value: +"Name or substring of a previously-added component to remove from this meal (see REMOVE ONE ADDED COMPONENT above). Exclusive of every other field below -- only id/date/name/target_meal_type may accompany it, to select the meal."
    • changedInput schema / properties / saturated_fat_g / description
      Previous value: -"Updated saturated fat in grams. Optional."New value: +"Updated saturated fat in grams. Optional, see SATURATED FAT / FIBER above."
    • changedInput schema / properties / target_meal_type / description
      Previous value: -"Which meal type to FIND on the date, e.g. Breakfast, to disambiguate multiple meals logged that day. This is NEVER written to the meal; it only narrows the search. Distinct from meal_type below, which SETS the new type."New value: +"Which meal type to FIND on the date, e.g. Breakfast, to disambiguate multiple meals logged that day -- \"update today's breakfast\" is target_meal_type: \"Breakfast\". Case-insensitive, only used when id is omitted. This is NEVER written to the meal; it only narrows the search, exactly like name above. Distinct from meal_type below, which SETS the new type to write. If no meal of this type is logged on the date, the call throws naming the meal types that ARE logged that day and changes nothing -- it never falls back to whichever meal the date happens to match."
  3. Changed14 schema fields changed
    • changedInput schema / properties / add_food_items / description
      Previous value: -"Optional. Description of food to ADD to this meal that ISN'T a saved recipe, e.g. \"a banana\", \"small coffee with cream\" (see ADD FOOD THAT WASN'T SAVED above). Requires calories/protein_g/fat_g/carbs_g to be set to the estimated macros of just this new food -- never the meal's new total. Appends this text onto the meal's existing food_items and adds the macro fields onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). May be set together with add_recipe_name in one call, see mode 2 above."New value: +"Optional. Description of food to ADD to this meal that is not a saved recipe. Requires calories/protein_g/fat_g/carbs_g for just this new food."
    • addedInput schema / properties / add_recipe_multiplier
      Added value: +{
      +  "description": "Positive serving multiplier for add_recipe_name, e.g. 0.5 for half or 2 for double. Omit for one saved serving.",
      +  "type": "number"
      +}
    • changedInput schema / properties / add_recipe_name / description
      Previous value: -"Optional. Name (or a close phrase) of one of the user's saved recipes to FOLD INTO this meal, e.g. \"kombucha\", \"protein shake\" (see FOLD IN A SAVED RECIPE above). Adds the recipe's food text and macros onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Distinct from log_meal's recipe_name, which SETS a new meal's fields instead of adding to one that already exists. May be set together with add_food_items in one call, see mode 2 above."New value: +"Optional. Name or close phrase for one saved recipe to FOLD INTO this meal. Adds the recipe food and stored macros; distinct from log_meal recipe_name."
    • changedInput schema / properties / alcohol_g / description
      Previous value: -"Updated alcohol in grams. Same REPLACE-vs-ADD rule as calories above, except this one stays optional even with add_recipe_name or add_food_items set: omitting it just adds nothing."New value: +"Updated alcohol in grams. Same REPLACE-vs-ADD rule as calories, optional for additions."
    • changedInput schema / properties / calories / description
      Previous value: -"Updated total calories (kcal). Optional, omit if not changing (or, with add_recipe_name, if the recipe already has a stored value). REPLACES the current value unless add_recipe_name or add_food_items is also set, in which case this is the AMOUNT BEING ADDED (the new food's own calories, not the meal's new total), added onto the meal's current value. Required whenever add_food_items is set, since there is no saved recipe to fall back on."New value: +"Updated total calories (kcal). REPLACES unless an add_* field is present, then it is the amount for the applicable new contribution."
    • changedInput schema / properties / carbs_g / description
      Previous value: -"Updated carbohydrates in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."New value: +"Updated carbohydrates in grams. Same REPLACE-vs-ADD rule as calories."
    • changedInput schema / properties / fat_g / description
      Previous value: -"Updated fat in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."New value: +"Updated fat in grams. Same REPLACE-vs-ADD rule as calories."
    • changedInput schema / properties / fiber_g / description
      Previous value: -"Updated dietary fiber in grams. Optional, see SATURATED FAT / FIBER above."New value: +"Updated dietary fiber in grams. Optional."
    • changedInput schema / properties / food_items / description
      Previous value: -"Updated food description. Optional, omit if not changing. With add_recipe_name and add_food_items both omitted, this REPLACES the current description outright. With either one present and this omitted, the new food's text (the recipe's stored food_items, or add_food_items itself) is appended instead. Passing this alongside add_recipe_name/add_food_items overrides the append with this exact text."New value: +"Updated food description. Optional, omit if not changing. Without add_* it REPLACES; with add_* it overrides the appended description."
    • changedInput schema / properties / meal_type / description
      Previous value: -"Updated meal type to WRITE onto the meal (e.g. reclassify a Snack as Dinner). Optional, omit if not changing. Never inferred from add_recipe_name. Distinct from target_meal_type above, which FINDS a meal by its current type and is never written."New value: +"Updated meal type to WRITE onto the meal. Optional, omit if not changing. Never inferred from add_recipe_name."
    • changedInput schema / properties / protein_g / description
      Previous value: -"Updated protein in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."New value: +"Updated protein in grams. Same REPLACE-vs-ADD rule as calories."
    • changedInput schema / properties / remove_item_name / description
      Previous value: -"Name or substring of a previously-added component to remove from this meal (see REMOVE ONE ADDED COMPONENT above). Exclusive of every other field below -- only id/date/name/target_meal_type may accompany it, to select the meal."New value: +"Name or substring of a previously-added component to remove from this meal. Exclusive of every other field below; only selectors may accompany it."
    • changedInput schema / properties / saturated_fat_g / description
      Previous value: -"Updated saturated fat in grams. Optional, see SATURATED FAT / FIBER above."New value: +"Updated saturated fat in grams. Optional."
    • changedInput schema / properties / target_meal_type / description
      Previous value: -"Which meal type to FIND on the date, e.g. Breakfast, to disambiguate multiple meals logged that day -- \"update today's breakfast\" is target_meal_type: \"Breakfast\". Case-insensitive, only used when id is omitted. This is NEVER written to the meal; it only narrows the search, exactly like name above. Distinct from meal_type below, which SETS the new type to write. If no meal of this type is logged on the date, the call throws naming the meal types that ARE logged that day and changes nothing -- it never falls back to whichever meal the date happens to match."New value: +"Which meal type to FIND on the date, e.g. Breakfast, to disambiguate multiple meals logged that day. This is NEVER written to the meal; it only narrows the search. Distinct from meal_type below, which SETS the new type."
  4. Changed2 schema fields changed
    • addedInput schema / properties / fiber_g
      Added value: +{
      +  "description": "Updated dietary fiber in grams. Optional, see SATURATED FAT / FIBER above.",
      +  "type": "number"
      +}
    • addedInput schema / properties / saturated_fat_g
      Added value: +{
      +  "description": "Updated saturated fat in grams. Optional, see SATURATED FAT / FIBER above.",
      +  "type": "number"
      +}
  5. Changed1 schema field changed
    • addedInput schema / properties / save_as_recipe
      Added value: +{
      +  "description": "True only when the user explicitly asks to save this meal as a reusable recipe. The recipe is copied from the final persisted meal. On update_meal, this can be the only requested action; use the real meal id or normal selectors and do not invent an edit.",
      +  "type": "boolean"
      +}
  6. Changed1 schema field changed
    • changedInput schema / properties / id / description
      Previous value: -"Meal ID, if already known. Alternative to date + name/target_meal_type, see FIND THE MEAL above."New value: +"Meal ID only if it came from a real meal/tool result; never invent or guess it. Otherwise omit it and use date + name/target_meal_type, see FIND THE MEAL above."
  7. Changed5 schema fields changed
    • changedInput schema / properties / add_food_items / description
      Previous value: -"Optional. Description of food to ADD to this meal that ISN'T a saved recipe, e.g. \"a banana\", \"small coffee with cream\" (see ADD FOOD THAT WASN'T SAVED above). Requires calories/protein_g/fat_g/carbs_g to be set to the estimated macros of just this new food -- never the meal's new total. Appends this text onto the meal's existing food_items and adds the macro fields onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Mutually exclusive with add_recipe_name -- never set both; if adding a saved recipe and separate ad-hoc food, make two calls."New value: +"Optional. Description of food to ADD to this meal that ISN'T a saved recipe, e.g. \"a banana\", \"small coffee with cream\" (see ADD FOOD THAT WASN'T SAVED above). Requires calories/protein_g/fat_g/carbs_g to be set to the estimated macros of just this new food -- never the meal's new total. Appends this text onto the meal's existing food_items and adds the macro fields onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). May be set together with add_recipe_name in one call, see mode 2 above."
    • changedInput schema / properties / add_recipe_name / description
      Previous value: -"Optional. Name (or a close phrase) of one of the user's saved recipes to FOLD INTO this meal, e.g. \"kombucha\", \"protein shake\" (see FOLD IN A SAVED RECIPE above). Adds the recipe's food text and macros onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Distinct from log_meal's recipe_name, which SETS a new meal's fields instead of adding to one that already exists. Mutually exclusive with add_food_items -- never set both."New value: +"Optional. Name (or a close phrase) of one of the user's saved recipes to FOLD INTO this meal, e.g. \"kombucha\", \"protein shake\" (see FOLD IN A SAVED RECIPE above). Adds the recipe's food text and macros onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Distinct from log_meal's recipe_name, which SETS a new meal's fields instead of adding to one that already exists. May be set together with add_food_items in one call, see mode 2 above."
    • changedInput schema / properties / date / description
      Previous value: -"Date the meal was logged. Format: YYYY-MM-DD. Used with name and/or target_meal_type to find the meal when id is omitted; defaults to today if id and date are both omitted."New value: +"Date the meal was logged. Format: YYYY-MM-DD. Used with name and/or target_meal_type to find the meal when id is omitted; defaults to today if id and date are both omitted. This only SELECTS which meal to update -- see move_to_date below to actually change a meal's stored date."
    • addedInput schema / properties / move_to_date
      Added value: +{
      +  "description": "Move this meal to a different date. Format: YYYY-MM-DD. Distinct from date above, which only finds the meal; this is what actually changes it, keeping the same id. Optional, omit if not moving the meal.",
      +  "type": "string"
      +}
    • addedInput schema / properties / remove_item_name
      Added value: +{
      +  "description": "Name or substring of a previously-added component to remove from this meal (see REMOVE ONE ADDED COMPONENT above). Exclusive of every other field below -- only id/date/name/target_meal_type may accompany it, to select the meal.",
      +  "type": "string"
      +}
  8. Changed2 schema fields changed
    • changedInput schema / properties / fluids / items / properties / beverage_type / description
      Previous value: -"Broad drink type. Default water. Use other when the exact drink is not in the enum and preserve its name in beverage_name."New value: +"Broad drink type. Default water. Energy drinks are accepted and stored as other; preserve the exact drink in beverage_name."
    • changedInput schema / properties / fluids / items / properties / beverage_type / enum
      Previous value: -[
      -  "water",
      -  "electrolyte",
      -  "sports_drink",
      -  "coffee",
      -  "tea",
      -  "juice",
      -  "milk",
      -  "soda",
      -  "broth",
      -  "other"
      -]New value: +[
      +  "water",
      +  "electrolyte",
      +  "sports_drink",
      +  "coffee",
      +  "tea",
      +  "juice",
      +  "milk",
      +  "soda",
      +  "broth",
      +  "other",
      +  "energy_drink"
      +]
  9. Changed10 schema fields changed
    • changedInput schema / properties / caffeine / description
      Previous value: -"Optional caffeine doses in this intake. Every dose must identify the ingested caffeine source. If the user gave exact milligrams, preserve them exactly. If only a food/drink is described, estimate caffeine with the same nutrition-estimation judgment used for meal macros. Each item preserves its consumed time."New value: +"Optional caffeine doses in this intake. Keep each dose simple: caffeine amount is required and type is optional. The dose date follows the intake/meal date. If the user gave exact milligrams, preserve them exactly; otherwise estimate from the described food or drink."
    • changedInput schema / properties / caffeine / items / properties / caffeine_mg / description
      Previous value: -"Caffeine in milligrams. Preserve an explicit user amount exactly; otherwise estimate from the described source."New value: +"Caffeine in milligrams. Preserve an explicit user amount exactly; otherwise estimate from the described intake."
    • removedInput schema / properties / caffeine / items / properties / consumed_at
      Removed value: -{
      -  "description": "Alternative ISO 8601 timestamp with offset. Optional.",
      -  "type": "string"
      -}
    • removedInput schema / properties / caffeine / items / properties / consumed_date
      Removed value: -{
      -  "description": "Local date YYYY-MM-DD. Default: the meal date, then today.",
      -  "type": "string"
      -}
    • removedInput schema / properties / caffeine / items / properties / consumed_time
      Removed value: -{
      -  "description": "Local time HH:MM. Default: current local time for today; ask rather than invent a time for historical intake.",
      -  "type": "string"
      -}
    • removedInput schema / properties / caffeine / items / properties / note
      Removed value: -{
      -  "description": "Additional context. Optional.",
      -  "type": "string"
      -}
    • removedInput schema / properties / caffeine / items / properties / source_name
      Removed value: -{
      -  "description": "Specific food, drink, supplement, or product name. Required when source_type is other; optional otherwise.",
      -  "type": "string"
      -}
    • changedInput schema / properties / caffeine / items / properties / source_type / description
      Previous value: -"Required broad ingested caffeine source. Use other only when source_name identifies the specific food, drink, or supplement."New value: +"Optional broad caffeine type."
    • removedInput schema / properties / caffeine / items / properties / source_type / enumFallback
      Removed value: -{
      -  "annotate": "source_name",
      -  "value": "other"
      -}
    • changedInput schema / properties / caffeine / items / required
      Previous value: -[
      -  "caffeine_mg",
      -  "source_type"
      -]New value: +[
      +  "caffeine_mg"
      +]
  10. Changed1 schema field changed
    • addedInput schema / properties / caffeine
      Added value: +{
      +  "description": "Optional caffeine doses in this intake. Every dose must identify the ingested caffeine source. If the user gave exact milligrams, preserve them exactly. If only a food/drink is described, estimate caffeine with the same nutrition-estimation judgment used for meal macros. Each item preserves its consumed time.",
      +  "items": {
      +    "properties": {
      +      "caffeine_mg": {
      +        "description": "Caffeine in milligrams. Preserve an explicit user amount exactly; otherwise estimate from the described source.",
      +        "type": "number"
      +      },
      +      "consumed_at": {
      +        "description": "Alternative ISO 8601 timestamp with offset. Optional.",
      +        "type": "string"
      +      },
      +      "consumed_date": {
      +        "description": "Local date YYYY-MM-DD. Default: the meal date, then today.",
      +        "type": "string"
      +      },
      +      "consumed_time": {
      +        "description": "Local time HH:MM. Default: current local time for today; ask rather than invent a time for historical intake.",
      +        "type": "string"
      +      },
      +      "note": {
      +        "description": "Additional context. Optional.",
      +        "type": "string"
      +      },
      +      "source_name": {
      +        "description": "Specific food, drink, supplement, or product name. Required when source_type is other; optional otherwise.",
      +        "type": "string"
      +      },
      +      "source_type": {
      +        "description": "Required broad ingested caffeine source. Use other only when source_name identifies the specific food, drink, or supplement.",
      +        "enum": [
      +          "coffee",
      +          "espresso",
      +          "tea",
      +          "energy_drink",
      +          "soda",
      +          "pre_workout",
      +          "supplement",
      +          "other"
      +        ],
      +        "enumFallback": {
      +          "annotate": "source_name",
      +          "value": "other"
      +        },
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "caffeine_mg",
      +      "source_type"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  11. Changed16 schema fields changed
    • addedInput schema / properties / add_food_items
      Added value: +{
      +  "description": "Optional. Description of food to ADD to this meal that ISN'T a saved recipe, e.g. \"a banana\", \"small coffee with cream\" (see ADD FOOD THAT WASN'T SAVED above). Requires calories/protein_g/fat_g/carbs_g to be set to the estimated macros of just this new food -- never the meal's new total. Appends this text onto the meal's existing food_items and adds the macro fields onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Mutually exclusive with add_recipe_name -- never set both; if adding a saved recipe and separate ad-hoc food, make two calls.",
      +  "type": "string"
      +}
    • addedInput schema / properties / add_recipe_name
      Added value: +{
      +  "description": "Optional. Name (or a close phrase) of one of the user's saved recipes to FOLD INTO this meal, e.g. \"kombucha\", \"protein shake\" (see FOLD IN A SAVED RECIPE above). Adds the recipe's food text and macros onto the meal's current values; never use this to replace a meal outright (omit it and pass food_items/calories/etc. directly for that). Distinct from log_meal's recipe_name, which SETS a new meal's fields instead of adding to one that already exists. Mutually exclusive with add_food_items -- never set both.",
      +  "type": "string"
      +}
    • changedInput schema / properties / alcohol_g / description
      Previous value: -"Updated alcohol in grams. Optional — omit if not changing."New value: +"Updated alcohol in grams. Same REPLACE-vs-ADD rule as calories above, except this one stays optional even with add_recipe_name or add_food_items set: omitting it just adds nothing."
    • changedInput schema / properties / calories / description
      Previous value: -"Updated total calories (kcal). Optional — omit if not changing."New value: +"Updated total calories (kcal). Optional, omit if not changing (or, with add_recipe_name, if the recipe already has a stored value). REPLACES the current value unless add_recipe_name or add_food_items is also set, in which case this is the AMOUNT BEING ADDED (the new food's own calories, not the meal's new total), added onto the meal's current value. Required whenever add_food_items is set, since there is no saved recipe to fall back on."
    • changedInput schema / properties / carbs_g / description
      Previous value: -"Updated carbohydrates in grams. Optional — omit if not changing."New value: +"Updated carbohydrates in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."
    • addedInput schema / properties / date
      Added value: +{
      +  "description": "Date the meal was logged. Format: YYYY-MM-DD. Used with name and/or target_meal_type to find the meal when id is omitted; defaults to today if id and date are both omitted.",
      +  "type": "string"
      +}
    • changedInput schema / properties / fat_g / description
      Previous value: -"Updated fat in grams. Optional — omit if not changing."New value: +"Updated fat in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."
    • addedInput schema / properties / fluids
      Added value: +{
      +  "description": "Optional drinks consumed in this intake. Omit when no drink amount is known. Hydration is persisted only when the user enabled hydration tracking.",
      +  "items": {
      +    "properties": {
      +      "alcohol_g": {
      +        "description": "Alcohol grams in this specific drink. Required per alcoholic fluid when more than one drink is present.",
      +        "type": "number"
      +      },
      +      "beverage_name": {
      +        "description": "Specific drink name when useful, e.g. IPA, vodka soda, latte.",
      +        "type": "string"
      +      },
      +      "beverage_type": {
      +        "description": "Broad drink type. Default water. Use other when the exact drink is not in the enum and preserve its name in beverage_name.",
      +        "enum": [
      +          "water",
      +          "electrolyte",
      +          "sports_drink",
      +          "coffee",
      +          "tea",
      +          "juice",
      +          "milk",
      +          "soda",
      +          "broth",
      +          "other"
      +        ],
      +        "type": "string"
      +      },
      +      "unit": {
      +        "description": "Volume unit. Default ml.",
      +        "enum": [
      +          "ml",
      +          "fl_oz"
      +        ],
      +        "type": "string"
      +      },
      +      "volume": {
      +        "description": "Consumed drink volume in the supplied unit.",
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "volume"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedInput schema / properties / food_items / description
      Previous value: -"Updated food description. Optional — omit if not changing."New value: +"Updated food description. Optional, omit if not changing. With add_recipe_name and add_food_items both omitted, this REPLACES the current description outright. With either one present and this omitted, the new food's text (the recipe's stored food_items, or add_food_items itself) is appended instead. Passing this alongside add_recipe_name/add_food_items overrides the append with this exact text."
    • changedInput schema / properties / id / description
      Previous value: -"Meal ID from list_meals. Required — do not proceed without it."New value: +"Meal ID, if already known. Alternative to date + name/target_meal_type, see FIND THE MEAL above."
    • changedInput schema / properties / meal_type / description
      Previous value: -"Updated meal type. Optional — omit if not changing."New value: +"Updated meal type to WRITE onto the meal (e.g. reclassify a Snack as Dinner). Optional, omit if not changing. Never inferred from add_recipe_name. Distinct from target_meal_type above, which FINDS a meal by its current type and is never written."
    • changedInput schema / properties / meal_type / enum
      Previous value: -[
      -  "Breakfast",
      -  "Lunch",
      -  "Dinner",
      -  "Snack",
      -  "Post-Workout"
      -]New value: +[
      +  "Breakfast",
      +  "Lunch",
      +  "Dinner",
      +  "Snack",
      +  "Post-Workout",
      +  "Shake",
      +  "Other"
      +]
    • addedInput schema / properties / name
      Added value: +{
      +  "description": "Substring of the food description (case-insensitive) to disambiguate multiple meals on the same date. Only used when id is omitted.",
      +  "type": "string"
      +}
    • changedInput schema / properties / protein_g / description
      Previous value: -"Updated protein in grams. Optional — omit if not changing."New value: +"Updated protein in grams. Same REPLACE-vs-ADD rule as calories above, including required-with-add_food_items."
    • addedInput schema / properties / target_meal_type
      Added value: +{
      +  "description": "Which meal type to FIND on the date, e.g. Breakfast, to disambiguate multiple meals logged that day -- \"update today's breakfast\" is target_meal_type: \"Breakfast\". Case-insensitive, only used when id is omitted. This is NEVER written to the meal; it only narrows the search, exactly like name above. Distinct from meal_type below, which SETS the new type to write. If no meal of this type is logged on the date, the call throws naming the meal types that ARE logged that day and changes nothing -- it never falls back to whichever meal the date happens to match.",
      +  "enum": [
      +    "Breakfast",
      +    "Lunch",
      +    "Dinner",
      +    "Snack",
      +    "Post-Workout",
      +    "Shake",
      +    "Other"
      +  ],
      +  "type": "string"
      +}
    • removedInput schema / required
      Removed value: -[
      -  "id"
      -]
  12. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, and the description substantiates that with concrete behavioral consequences: mode 3 replaces whole totals and 'throws away what was already logged' if misapplied, additive modes fold values, remove_item_name throws when no recorded component exists, and hydration sidecars are replaced only after safe insertion. This is far beyond what the annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core intent and sibling routing, and organized with clear headers (FIND THE MEAL, THREE MODES, etc.). It is long, but for a 20-parameter tool with irreversible replace/add semantics, the length is largely earned; a few sentences on saturated fat/fiber and caffeine could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 20 parameters, mutation semantics, a destructive annotation, and multiple coexisting modes, the description covers selection, all three update modes, date moves, component removal, hydration and caffeine sidecar handling, and recipe saving. An output schema exists, so return-value explanation is correctly omitted. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds substantial semantic meaning beyond the schema: the REPLACE-vs-ADD rule per field, which fields are required only when add_food_items is set, the interplay when both add_recipe_name and add_food_items are set, and the distinction between target_meal_type (selector) versus meal_type (write). This is the rare case where prose meaningfully extends structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource ('Update an existing meal') and immediately distinguishes its scope from log_meal and delete_meal by naming the exact trigger conditions. It explicitly calls out that a plain food statement should route to log_meal, which prevents the most likely sibling confusion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('current message explicitly changes, corrects, or adds to a meal already logged'), when-not-to-use ('Never infer an update from earlier chat history'), and names the alternative tool (log_meal) with the precise disambiguating condition. It also covers in-tool mode selection and the ambiguity fallback ('ask before updating').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.