Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
FITATU_SESSIONNoPath to the Fitatu session file used by the MCP server. Falls back to $FITATU_SESSION_PATH, then ~/.fitatu/session.json (written by `fitatu-api login`).
FITATU_LOG_LEVELNoLog level for the library, one of DEBUG, INFO, WARNING, ERROR. Logs go to stderr, never stdout; defaults to WARNING.
FITATU_SESSION_JSONNoThe session JSON itself, instead of a session file; takes precedence over any file. Useful where no writable session file fits (containers, cron). Produced by `fitatu-api login --print` or `fitatu-api import-session --print`.
FITATU_SESSION_PATHNoAlternative to $FITATU_SESSION: path to the Fitatu session file used when $FITATU_SESSION is not set; otherwise ~/.fitatu/session.json is used.
FITATU_CLIENT_PROFILENoJSON object with the keys of WEB_CLIENT_PROFILE to change (e.g. '{"app_version": "4.14.0"}') when Fitatu changes what its web app sends before a release of this library follows. Any other key or a non-plain-text value is refused and fitatu-mcp then does not start.

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}

Tools

Functions exposed to the LLM to take actions

NameDescription
get_todayA

Today's date in the user's time zone: date (YYYY-MM-DD), timezone and weekday. Call it when the user says today, yesterday, tomorrow, this week or a weekday, and count from it.

get_dayA

Read one diary day: per meal its meal_key (the slot other tools take), meal_name (the name the user gave it) and every logged food (row_id, food_type, product_id or recipe_id, name, measure_id, measure_name and measure_quantity, weight in g, energy in kcal, protein/fat/carbohydrate/fiber/sugars/salt in g, eaten); per-meal and day totals; and logged activities (row_id, name, energy in kcal burned); note, the user's own text for the day (null without one), and tags_ids, the ids of its note tags. What the user ate is eaten_totals (rows ticked as eaten); when it is 0 but totals is not, the rows are logged without the tick, so use totals and say so. totals counts every row, planned or eaten. Burned energy is not subtracted. Read the day first to get the row_ids that update_item, move_item and remove_items take. A PRODUCT or RECIPE row's product_id or recipe_id is the food_id that add_food takes, with its food_type, measure_id and measure_quantity as quantity.

get_targetsA

Read the user's daily goals for a day: energy in kcal, protein/fat/carbohydrate as grams and percent of energy, and BMR/TMR in kcal. date is the day asked for; settings_since is when these goals took effect (an earlier day is normal).

get_profileA

Read what the user's goals are computed from, for advice: height_cm, weight_kg (the current weight in the profile; a weigh-in logged for today updates it), start_weight_kg and target_weight_kg, bmi (from height_cm and weight_kg), goal (lose, maintain or gain) with pace_kg_per_week, pal (the activity level: TMR = BMR x pal), sex (male, female or null), age in years, and premium: active (whether the account has Fitatu Premium) and end_date. kg and cm whatever units the user chose in the app; a value is null when the profile lacks it. The daily goals are get_targets, the weigh-ins get_weight_history.

get_range_summaryA

Read Fitatu's own summary of a date range, as the app's Summary tab shows it: nutrition (energy in kcal; protein, fat, carbohydrate, fiber, sugars, salt in g) counts every logged row, ticked as eaten or not, like get_day's totals; eaten_nutrition the same for the rows ticked as eaten only; activity_energy is kcal burned. Both are totals over the whole range, not daily averages: divide by the number of days for one. For goals and what is left per day, use get_progress.

get_progressA

Progress against the user's goals, day by day, for one day or a range of up to 62 days: per day and for energy, protein, fat and carbohydrate, logged (every row, planned or eaten; null when nothing is logged that day), the goal (target in kcal for energy; target_min and target_max in g for a macro, which is on target between the two) and left (the goal minus logged, a macro's from target_max; negative when over). totals gives the whole range: logged, eaten (only rows ticked as eaten) and the goal summed over the days. Works on every account; without Fitatu Premium it reads each day on its own, so it covers at most 31 days, and each day has eaten too. Answers 'what is left today', 'did I hit protein' and how each day went; a summary of a week or month with weight and top foods, or of a longer range, is get_report (over 31 days without Fitatu Premium, get_range_summary).

get_top_foodsA

The foods that gave the user the most of a nutrient over a date range, most first: name, amount (kcal for energy, g otherwise, summed over the range) and per100 (the food's own amount per 100 g; null for a custom item). A recipe may be listed as its ingredients. Answers 'where does my sugar come from'. Premium only: on an account without Fitatu Premium, Fitatu refuses it (a forbidden error); tell the user, do not retry.

get_reportA

A weekly or monthly report (or one of any range) in one call. nutrition: for energy, protein, fat and carbohydrate the range's totals, logged (every row, planned or eaten) and eaten (rows ticked as eaten), and daily: logged averaged over days_logged (the days with anything logged) next to the average daily goal (target for energy, target_min and target_max for a macro). weight: the first and last weigh-in of the range (date, value in the user's weight unit) and the change; null without one. top_foods: the 5 foods with the most energy and the 5 with the most protein, as get_top_foods gives them. Without Fitatu Premium, top_foods is null (top_foods_note says why) and the range is at most 31 days; get_range_summary gives the totals of a longer one.

get_shopping_listA

A shopping list for a range of up to 14 days, worked out from the rows planned in the diary and not ticked as eaten. products sums them per product and measure (product_id, name, measure_name, quantity of that measure, weight_g; weight_g is null when a row does not give it), with the ingredients of each planned recipe added for its portions; recipes lists those recipes (date, meal, recipe_id, name, portions, and expanded false when its ingredients could not be read or it is a premium recipe on an account without Fitatu Premium, so they are missing from products); other_items lists custom and other rows as they are. It cannot know what the user already has at home, pack sizes or anything not planned in the diary: say so. Start at today ("this week" is today to Sunday): rows on past days not ticked as eaten were usually eaten anyway. One request per day and one per recipe.

search_foodA

Search the Fitatu food catalog (Polish names work best). Each hit has food_id and type (PRODUCT or RECIPE) for add_food and get_food_measures, name, brand, its default measure (measure_id, name, weight_g or capacity_ml of one measure) with energy_kcal for one such measure, times_used (how often the user logged it; null when the server does not say) and favorite (whether it is one of the user's favourites). A barcode belongs in find_by_barcode. With locale, the hits come from that country's catalog (foods the user logged before show up too) and can be logged like any other.

search_recipesA

Search the Fitatu recipe catalog for meal ideas, e.g. phrase 'kurczak' with max_energy_kcal 500 for a chicken dinner of at most 500 kcal, or diets ['vegan'], meal 'breakfast' and max_cooking_time 10 for a quick vegan breakfast. The filters are per portion and all apply together; all but max_energy_kcal need Fitatu Premium (without it a forbidden error: tell the user, search by phrase and max_energy_kcal instead). Each hit is shaped like a search_food hit of type RECIPE (food_id, name, energy_kcal and measure of one portion) plus cooking_time and preparation_time as the catalog gives them, rating, and premium: whether the app keeps the recipe for Fitatu Premium (get_recipe and get_food_measures read it only with Premium). get_recipe gives a hit's ingredients and steps. Log one with add_food: food_type RECIPE, quantity the portions.

get_recipeA

Read one recipe in full, from the catalog or the user's own: name, servings (how many servings the ingredients make), ingredients for the whole recipe (food_id, food_type, quantity, measure_id, name, measure_name and weight_g; create_recipe and update_recipe take only the first four: drop the rest), description (the steps), per_serving (its portion measure as get_food_measures lists it: weight_g, energy_kcal, protein_g, fat_g and carbohydrate_g of one serving; null when it has none), cooking_time and preparation_time in minutes as the catalog gives them, meals (the meal types it suits), tags (e.g. vegan, keto, polish), rating, premium, deleted, and own: whether it is the user's private recipe, which update_recipe and delete_recipe take. A premium recipe needs Fitatu Premium: without it a forbidden error.

find_by_barcodeA

Find the catalog product with a barcode (the EAN or UPC digits printed under the bars), or the user's own product with it (create_food's barcode). Returns it in the same shape as a search_food hit, for add_food and get_food_measures. A barcode that no product has is not_found: then search_food by the product's name.

get_food_measuresA

List the measures a food can be logged in: measure_id, name (e.g. 'g', 'portion', 'piece'), weight_g or capacity_ml, energy_kcal and protein_g, fat_g, carbohydrate_g of one measure (a macro is null when the food's details do not give it; a product the user created with unit ml gives a serving's ml as weight_g). Pass measure_id and a quantity of that measure to add_food. A premium recipe needs Fitatu Premium: without it a forbidden error.

get_recent_foodsA

List foods the user recently logged in a meal, most used first, in the same shape as search_food hits. Handy for 'my usual breakfast'.

get_favorite_foodsB

List the user's favourite products and recipes, in the same shape as search_food hits.

get_my_foodsA

List the foods the user created, their own recipes (create_recipe) and products (create_food), in the same shape as search_food hits: a RECIPE hit's food_id is what update_recipe and delete_recipe take, a PRODUCT hit's what update_food and delete_food take.

get_weight_historyA

List logged body weights as {date, value, difference, direction}, newest first: value in the user's weight unit (kg unless changed in the app), difference from the previous entry, direction the weight goal (1 gain, -1 lose, 0 keep). Pass from_date and to_date to choose the period; without them it lists the newest entries up to limit, however old (there is no default period). For the change over a long period, get_report.

get_body_measurementsA

Read how the user's body measurements changed over a period: per body_part (neck, chest, waist, stomach, hips, thigh, calf, biceps, fat_percentage) the first and last value of the period (start_value, end_value) and the difference. Sizes are in the user's size unit (cm unless changed in the app), fat_percentage in %. Parts with nothing logged are left out. Pass from_date and to_date to choose the period; without them the server picks it. Body weight is get_weight_history.

get_measurement_historyA

List the logged values of one body measurement as {date, value}, newest first: value in the user's size unit (cm unless changed in the app), fat_percentage in %. Days without that measurement are left out. Pass from_date and to_date to choose the period; without to_date it stops at today, so give it for later days; without either it lists the newest entries up to limit. The first and last value of every part over a period is get_body_measurements; body weight is get_weight_history.

get_waterA

Read how much water the user drank on a day (water_ml), the day's goal (target_ml) and the size of one glass in the user's settings (glass_ml); each is null when unknown.

get_fastingA

Read the user's intermittent fasting (post przerywany) for a range of up to 62 days: days lists each day with fasting, its eating_periods (when the user ate, from and to as times of day) next to expected (the eating windows of the scheme); a day without fasting is not listed. scheme is the fasting scheme in the user's settings (type, e.g. 16_08_hours or 5_2_days, week_days and start_date as Fitatu gives them), null when none is set.

get_habitsA

Read the habits the user took up in the app (e.g. drinking water every day): per habit its habit_id, name, length_days (how long it runs), days_done and checked_days (the days ticked), enrolled_date and completed. available lists the other habits the app offers (habit_id, name, length_days, premium).

get_good_daysA

List the days the app's summary marks as good days (Fitatu's own rule decides which), oldest first, with their count. Pass from_date and/or to_date to keep only a period; without them, every good day there is.

search_activityA

Search the activity (workout) catalog, e.g. 'bieganie' (running) or 'rower' (cycling). Each hit has activity_id for add_activity, name, and energy_kcal: the catalog's estimate for the effort in energy_for (e.g. '5 km w 00:30:00') for an average person. Scale it to what the user did to get the energy_kcal that add_activity needs.

preview_removalA

Show what remove_items would delete, without deleting anything: would_remove lists each food row with what it is (meal, meal_name, row_id, name, food_type, food_id, measure_id, measure_name, measure_quantity, energy in kcal, protein/fat/carbohydrate in g, eaten), as remove_items' removed does; missing lists the ids that are not food rows on the day. data.ok is false when one is missing. Call it before remove_items and name the foods to the user, not their row_ids.

add_foodA

Log a catalog food in a meal; returns its row_id. food_id and food_type come from a search_food, search_recipes, find_by_barcode, get_recent_foods, get_favorite_foods or get_my_foods hit, create_food's food_id (PRODUCT) or create_recipe's recipe_id (RECIPE). For a PRODUCT give either unit 'g' or 'ml' with quantity in grams or millilitres, or measure_id (from the hit or get_food_measures) with quantity = how many of that measure. A RECIPE is logged in portions unless measure_id names another of its measures; unit is for products only. A premium recipe needs Fitatu Premium: without it a forbidden error. A measure_id the food does not have is refused before anything is written (that check reads the food once), and the error lists its measures. Each call adds a row unless row_id is reused. The row is not read back: data.ok says the sync accepted it, so read get_day to check what was logged. The result names the measure the row was stored in (measure_id, measure_name, measure_quantity): grams of a food without a gram measure are stored as a count of another one (70 g as 2 portions of 35 g), and update_item's quantity counts that measure.

add_foodsA

Log several catalog foods in one meal with one write, e.g. a whole breakfast. Each item takes food_id, food_type, quantity and measure_id or unit as add_food does, and is checked the same way before anything is written (one read per item with measure_id or unit): when one is wrong, nothing is logged and the error names it as items[index]. Returns the rows (row_id, food_id, measure_id, measure_name, measure_quantity) in the order of items; they are not read back, data.ok says the sync accepted them. Each call adds rows unless row_id is reused.

add_custom_itemA

Log a food that is not in the catalog, by name and the nutrition of the whole amount eaten; returns its row_id. Each call adds a row unless row_id is reused. When the user gives only kcal, estimate protein_g, fat_g and carbohydrate_g for that food and tell the user they are estimates; an omitted one counts as 0 g.

update_itemA

Change a logged food row: its quantity (in the row's own measure, see measure_name and measure_quantity in get_day) and/or eaten. Nothing else can be changed: for another food, or a custom row's name or nutrition, remove the row and add it again. Activities cannot be updated: remove and add them again. data.ok says a re-read shows the change; data.previous is the row's quantity and eaten before it, to undo the change.

move_itemA

Move a logged food row to another meal and/or day. The moved row gets a new row_id, returned here; the old one is gone. data.ok says a re-read confirms both.

copy_mealA

Copy the food rows of a meal, or only row_ids of it, to another meal and/or day in one write, e.g. 'the same breakfast as yesterday' or 'plan this lunch for tomorrow'. Products and recipes keep their measure and quantity, custom rows their name and nutrition; rows of other types are not copied and are listed in skipped. Returns the copies' row_ids (remove_items with them undoes the copy); data.ok says a re-read shows them all. Each call adds rows unless row_id is reused.

remove_itemsA

Delete logged food rows from a day by row_id (meals[].items[].row_id in get_day). removed lists each deleted row with what it was (meal, meal_name, row_id, name, food_type, food_id, measure_id, measure_name, measure_quantity, energy in kcal, protein/fat/carbohydrate in g, eaten), enough to add it again: with add_food, or with add_custom_item from its name and nutrition when food_id is null (a custom row); failed lists the rows still there. Ids that are not food rows on the day (already deleted, or an activity's row_id) are listed in missing, so repeating the call is safe. Preview a removal with preview_removal, which only reads; dry_run does the same here. data.ok is false when a row was missing or failed; the result's top-level ok only says the call ran.

log_weightA

Save the user's body weight for a day in kg, replacing a weight already saved for that day; other body measurements of that day are kept. data.ok says the server accepted it.

log_measurementsA

Save body measurements for a day: sizes in the user's size unit (cm unless changed in the app), fat_percentage in %. Only the values given are replaced; the day's other measurements and its weight are kept. Body weight is log_weight. data.ok says the server accepted it.

set_waterA

Set the total water drunk on a day in ml. It replaces the day's total instead of adding to it: to add some, read get_water and send the sum. For glasses, multiply by get_water's glass_ml (ask the user for the size when it is null). data.ok says the server accepted it.

set_targetsA

Change the user's daily goals from today on; earlier days keep theirs. energy_kcal sets a manual calorie goal. protein_pct, fat_pct and carbohydrate_pct set the macro split as whole percent of the energy, all three summing to 100; the grams follow from the energy. With energy_kcal alone the current split stays, or 20/30/50 when the account has none (say so); the percentages alone keep the current energy, as a manual goal. automatic true goes back to the goal Fitatu calculates from the user's profile, with no energy_kcal or percentages. water_glass_ml is the glass size water is counted in (get_water's glass_ml). Returns the goals now in effect as get_targets gives them, plus automatic, glass_ml and previous: the arguments that put back what this call changed, with no water_glass_ml when there was no glass size (that cannot be put back). data.ok says Fitatu's reply shows the change.

set_noteA

Replace the user's note for a diary day (get_day's note) with note; an empty note deletes it. The day's note tags are kept, and so is everything else of the day. data.previous is the note before ('' when there was none), to put it back; data.ok says a re-read shows the new note.

add_activityA

Log a workout from the activity catalog; returns its row_id. Fitatu stores energy_kcal as given and does not compute it (see search_activity). Each call adds an activity unless row_id is reused. data.ok says a re-read shows it.

remove_activityA

Delete a logged activity by row_id (activities[].row_id in get_day, or from add_activity). An id that is not an activity on the day (already deleted, or a food row's row_id) gives data.ok false, reason item_not_found and a message listing the day's activities, so repeating the call is safe; the result's top-level ok only says the call ran.

set_favoriteA

Add a catalog food to the user's favourites, or remove it with favorite false. food_id and food_type come from search_food, get_recent_foods or get_favorite_foods. Repeating it is safe. The server applies it asynchronously, so get_favorite_foods may not show the change for a moment. data.ok says the server accepted it.

create_recipeA

Save a private recipe in the user's own foods from catalog products, e.g. their usual smoothie, so it can be logged as one food. Only the user sees it; it never goes to the shared catalog. Each ingredient takes food_id, quantity and unit or measure_id as add_food does, is a PRODUCT, and is checked the same way before anything is written: when one is wrong, nothing is created and the error names it as ingredients[index]. Returns recipe_id and per_serving, its portion measure as get_food_measures lists it (weight_g, energy_kcal, protein_g, fat_g, carbohydrate_g of one serving; null when the recipe could not be read back). Log it with add_food: food_id recipe_id, food_type RECIPE, quantity the servings eaten. Each call creates another recipe: when one fails with anything but a validation, not_found or rate_limit error, look for it with get_my_foods before creating it again.

update_recipeA

Change one of the user's own private recipes (create_recipe's recipe_id or a get_my_foods RECIPE hit's food_id): its name, ingredients (the whole new list, each as create_recipe takes it and checked the same way), servings and/or description; what is not given stays as it is. Any other recipe is refused before anything is changed (that check reads the recipe). Returns per_serving as create_recipe does, and previous (name, servings, description, ingredients), which update_recipe takes to undo the change. data.ok says the server accepted it.

delete_recipeA

Delete one of the user's own private recipes: create_recipe's recipe_id or a get_my_foods RECIPE hit's food_id. Any other recipe (a catalog recipe, a shared one or another user's) is refused before anything is changed (that check reads the recipe). Fitatu keeps a deleted recipe marked deleted, out of the user's foods and searches; deleting it again gives data.ok true with already_deleted true.

create_foodA

Save a product in the user's own foods from its nutrition label, e.g. a bar the catalog does not have, to log it by weight or by its servings. Only the user sees it; it never goes to the shared catalog. Values are per 100 g (100 ml with unit ml), as the label gives them: when it gives only a serving's, scale them to 100 g. Energy in kcal, not kJ. Returns food_id and measures, its measures as get_food_measures lists them (null when it could not be read back). Log it with add_food: food_id, food_type PRODUCT, and unit g (ml) with the amount, or a measure_id with the count. Each call creates another product: when one fails with anything but a validation or rate_limit error, look for it with get_my_foods before creating it again.

update_foodA

Change one of the user's own products (create_food's food_id or a get_my_foods PRODUCT hit's food_id): any value create_food takes but unit; what is not given stays as it is, and servings replaces the list. Any other product is refused before anything is changed (that check reads it). Fitatu usually changes the product in place (replaced_food_id null), and rows already logged with it then show the new values too. It may save the change as a new product instead (seen after a rename or new servings): food_id is then the new id and replaced_food_id the old, retired one, and rows logged before keep the old values. Before changing a product the user has logged, tell them their logged rows may change. Returns measures as create_food does and previous, which update_food takes on food_id to undo the change. data.ok says the server accepted it.

delete_foodA

Delete one of the user's own products: create_food's food_id or a get_my_foods PRODUCT hit's food_id. Any other product (a catalog one or another user's) is refused before anything is changed (that check reads it). Rows already logged with it keep their name and values. Fitatu keeps a deleted product marked deleted, out of the user's foods and searches; deleting it again gives data.ok true with already_deleted true. previous holds what create_food takes to make it again (under a new food_id).

Prompts

Interactive templates invoked by user choice

NameDescription
podsumowanie_dniaSummarize a diary day: what was eaten against the goals, what is left, the meals and water.
przeglad_tygodniaReview this week, Monday to today: daily averages against the goals, the days that stood out, the weight change and, with Fitatu Premium, the top foods.
zaloguj_posilekLog a meal from a description, e.g. 'dwa jajka i kawa z mlekiem na śniadanie'.

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4/5.0

Scored across 47 tools

Disambiguation4/5

Most tools target a clearly distinct resource and action (add_food vs add_foods vs add_custom_item vs add_activity, get_day vs get_progress), and the descriptions explicitly cross-reference the right sibling tool. However, the report family (get_range_summary, get_progress, get_report, get_top_foods) and the measurement family (get_weight_history, get_body_measurements, get_measurement_history) overlap enough that only the very long descriptions prevent misselection.

Naming Consistency5/5

Every name is snake_case with a predictable verb_noun shape: get_*, add_*, update_*, remove_*, set_*, create_*, delete_*, search_*, find_*, move_*, copy_*, log_*, preview_*. No camelCase or vague verbs break the pattern.

Tool Count3/5

At 47 tools this is heavy, and several reads (three summary/report tools, three measurement-history tools) add surface redundancy. It is defensible given the breadth of the Fitatu domain (diary, foods, recipes, activities, body data, water, fasting, habits, goals, notes, reports), but it sits well above the comfortable 3-15 range.

Completeness5/5

Coverage is unusually thorough: full CRUD for user foods and private recipes, add/remove for diary rows and activities, reads and writes for weight, measurements, water, targets, notes and favourites, plus search, barcode lookup, meal copy/move, shopping list and multiple report views. No obvious lifecycle gap for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessSlow