nutrition-mcp
Allows Hermes to track nutrition by providing tools to manage foods, aliases, recipes, and meal logs, with local-first persistence.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nutrition-mcplog tuna pizza for lunch"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
nutrition-mcp
A local-first nutrition tracker exposed as an HTTP MCP server for Hermes. SQLite is the source of truth for foods, recipes, and meal history; the agent does not need to memorize nutrition facts.
Data Model
The catalog separates a generic food from the products that can satisfy it:
Food type: a generic concept such as
mozzarella,tuna, orpickles.Food product: nutrition for a specific product or brand, always stored per 100 g with a usual portion name and weight.
Brand: stored on a product, such as
Milbona.Retailer: a searchable relationship, such as
Lidl; one product may be linked to multiple retailers.Alias: an exact phrase for either a product, recipe, or generic food type.
Recipe: a reusable set of foods and/or nested recipes with an optional measured yield.
Meal entry: an immutable nutrition snapshot plus quantity, grams, per-100g facts, recipe components, and recipe adjustments.
For example, a Mozzarella food type can contain several branded products. If the Milbona product is sold at Lidl and is the default:
mozzarellaresolves to the default Milbona product.milbona mozzarellaresolves from its brand and food-type relationship.lidl mozzarellaresolves from its retailer and food-type relationship.All three point to one concrete product for logging; other mozzarella products remain available by their own aliases or IDs.
Resolution is conservative. Exact product aliases are checked first, then generic aliases/defaults, then exact relationship phrases. Ambiguous relationship phrases fail instead of selecting an arbitrary product.
Product and food-type notes, aliases, brands, retailers, and names are searchable. Notes are useful for details such as low moisture, only sold at Lidl, or the jar with the green lid.
Related MCP server: nutrition-mcp
Nutrition Rules
Use add_food_product for all new packaged foods and ingredients. It requires:
all nutrition facts per 100 g;
usual_portion_grams;usual_portion_name, such as1 slice,1 piece, orusual serving.
The older add_food tool remains available for backward compatibility and unusual serving-only data. audit_foods lists migrated or legacy foods that still lack a reliable weight or per-100g facts. Repair those with update_food_product.
Tracked nutrients are calories, protein, carbs, fat, fiber, sugars, saturated fat, and salt. salt_g means grams of salt from the nutrition label, not milligrams of sodium.
Historical entries always keep their stored snapshots when products, defaults, or recipes change later.
MCP Endpoint
URL:
http://HOST:8765/mcpTransport: Streamable HTTP through FastMCP
Health endpoints:
GET /andGET /health
If MCP_TOKEN is set, every HTTP request must include:
Authorization: Bearer <token>PUBLIC_HOSTS is a comma-separated list of hostnames or IP addresses accepted by MCP DNS-rebinding protection. Do not include a scheme or port.
Tools
Food products:
add_food_product,update_food_product,get_food,search_foods,list_foodsadd_food,update_foodfor backward compatibilityadd_alias,delete_food,audit_foods
Generic food catalog:
add_food_type,update_food_type,get_food_type,search_food_typesadd_food_type_alias,assign_food_to_type,set_default_foodadd_retailer,link_food_retailer,unlink_food_retailer,list_retailers
Recipes:
add_recipe,update_recipe,get_recipe,search_recipes,delete_recipe
Logging and history:
log_food,log_recipeget_day,get_entries,get_weekly_reportupdate_entry,bulk_update_entries,delete_entry,finalize_daylist_aliases,health
Catalog Example
Create the generic type first:
{
"name": "Mozzarella",
"aliases": ["mozzarella", "mozz"],
"notes": "Generic mozzarella used on pizza"
}Then create a branded product with per-100g nutrition and a usual portion:
{
"name": "Mozzarella",
"brand": "Milbona",
"food_type_alias": "mozzarella",
"kcal_per_100g": 250,
"protein_g_per_100g": 18.5,
"carbs_g_per_100g": 2.0,
"fat_g_per_100g": 19.0,
"fiber_g_per_100g": 0,
"sugars_g_per_100g": 1.0,
"saturated_fat_g_per_100g": 13.0,
"salt_g_per_100g": 0.6,
"usual_portion_grams": 40,
"usual_portion_name": "pizza portion",
"aliases": ["milbona mozzarella"],
"retailers": ["Lidl"],
"make_default": true,
"notes": "Low-moisture bag normally used for pizza"
}After this, all of these log the same product:
{"alias": "mozzarella", "grams": 60}{"alias": "milbona mozzarella", "grams": 60}{"alias": "lidl mozzarella", "grams": 60}Use set_default_food to change which branded product a generic alias resolves to. Existing meal entries are unchanged.
Recipes And Nested Recipes
Recipe items may target either a food or another recipe. A nested recipe must have a positive yield_grams, because the parent needs to know what fraction is used. Cycles are rejected.
Example dough recipe:
{
"name": "Pizza dough batch",
"aliases": ["pizza dough"],
"yield_grams": 600,
"ingredients": [
{"alias": "flour", "grams": 400},
{"alias": "olive oil", "grams": 20}
]
}Use 165 g of that recipe inside a pizza:
{
"name": "Tuna pizza",
"aliases": ["tuna pizza"],
"yield_grams": 285,
"ingredients": [
{"recipe_alias": "pizza dough", "grams": 165},
{"alias": "tuna", "grams": 60},
{"alias": "mozzarella", "grams": 60}
]
}Recipe responses include direct_items and fully flattened ingredients. Logs snapshot the flattened components and source paths, so the complete history remains understandable after later recipe edits.
One-off recipe changes are normalized and stored in the entry:
{
"alias": "tuna pizza",
"adjustments": [
{"alias": "mozzarella", "delta_grams": 20}
]
}Each stored adjustment records the original request and before/after/delta quantities and grams. Updating the logged recipe quantity scales those snapshots consistently.
Correcting Entries
update_entry accepts either quantity or grams for one entry. bulk_update_entries applies several corrections atomically:
{
"date": "2026-07-17",
"updates": [
{"entry_id": 104, "grams": 85},
{"entry_id": 105, "scale_factor": 0.9},
{"entry_id": 107, "quantity": 2, "note": "Corrected from photo"}
]
}Each item may contain only one of quantity, grams, or scale_factor. If any correction is invalid, the entire request is rolled back.
Automatic Database Migration
At startup the server checks schema_meta. Schema 1-3 databases are upgraded automatically to schema 4 before MCP tools are registered.
The migration:
Creates a consistent SQLite backup under
/data/backups.Applies all schema and data changes in one transaction.
Preserves food and recipe aliases, searchable notes, recipes, entries, and historical macro snapshots.
Creates generic food types and portions for existing foods when the source data supports them.
Validates row counts, historical totals, foreign keys, and
PRAGMA quick_check.Updates the schema version only after validation succeeds.
Foods without a known serving weight are preserved in legacy mode as needs_review; the migration never invents grams or per-100g values. The /health result reports migration status and review counts.
Data Paths
Inside the container:
SQLite DB:
/data/nutrition.dbMigration backups:
/data/backupsDaily Markdown:
/data/exports/daily/YYYY-MM-DD.mdCSV:
/data/exports/csv/YYYY-MM-DD.csvJSON:
/data/exports/json/YYYY-MM-DD.json
CSV and JSON exports include grams, amount source, per-100g nutrition, and persistent recipe adjustments.
Local Development
py -3.12 -m venv .venv
.\.venv\Scripts\python -m pip install -e ".[test]"
.\.venv\Scripts\python -m pytest
.\.venv\Scripts\python -m app.mainTest the local endpoint:
curl -H "Authorization: Bearer change-me" http://localhost:8765/healthDocker Compose
The included compose file builds locally and persists the database in ./data:
docker compose up -d --build
docker compose logs -f nutrition-mcpFor Unraid, use a host path instead of the relative volume:
services:
nutrition-mcp:
image: ghcr.io/ispas-catalin/nutrition-mcp:0.5.0
container_name: nutrition-mcp
restart: unless-stopped
ports:
- "8765:8765"
environment:
DATA_DIR: /data
TZ: Europe/Bucharest
MCP_TOKEN: "replace-with-a-long-random-token"
PUBLIC_HOSTS: "192.168.1.142,nutrition-mcp"
HOST: 0.0.0.0
PORT: 8765
volumes:
- /mnt/user/appdata/nutrition-mcp:/dataAfter replacing the token:
docker compose pull
docker compose up -d
curl -H "Authorization: Bearer YOUR_REAL_TOKEN" http://192.168.1.142:8765/healthUnraid Add Container
Name:
nutrition-mcpRepository:
ghcr.io/ispas-catalin/nutrition-mcp:0.5.0Network Type:
bridgePort: host
8765to container8765TCPPath:
/mnt/user/appdata/nutrition-mcpto/dataTZ=Europe/BucharestMCP_TOKEN=<long random token>PUBLIC_HOSTS=192.168.1.142,nutrition-mcpWebUI:
http://[IP]:[PORT:8765]/
Hermes MCP Config
mcp_servers:
nutrition:
url: "http://192.168.1.142:8765/mcp"
headers:
Authorization: "Bearer <REAL_MCP_TOKEN>"Detailed agent behavior and call examples are in HERMES_AGENT_INSTRUCTIONS.md.
Security Notes
Use a strong token and keep port
8765on the trusted LAN; do not expose it directly to the internet.Keep
/dataprivate because it contains meal history and nutrition preferences.No arbitrary SQL tool is exposed.
Deletes require exact IDs and refuse unsafe referenced records.
Back up
/mnt/user/appdata/nutrition-mcpbefore major host changes even though schema migrations create their own database backup.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseBqualityDmaintenanceA personal fitness tracking server that enables logging and querying workouts, nutrition, and body metrics through a local SQLite database. Integrates with OpenNutrition MCP for food logging and supports exercise history tracking for workout progression.Last updated17
- Alicense-qualityDmaintenanceMCP server for USDA nutrition data lookup, meal logging, and daily macro tracking.Last updated171MIT
- Alicense-qualityBmaintenanceA filesystem-based MCP server that turns any MCP-capable AI agent into a conversational calorie and protein tracker with natural-language estimates, confidence-aware logging, daily/weekly progress, food-history search, and export, working offline with local fallback data.Last updated171MIT
- AlicenseAqualityAmaintenanceA local-first nutrition MCP server for food search, barcode lookup, meal estimation, intake logging, hydration, and nutrition coaching workflows.Last updated465587MIT
Related MCP Connectors
MCP server for Withings health data — sleep, activity, heart, and body metrics.
UN FAOSTAT global food & agriculture statistics over a local SQLite mirror, via MCP.
The everything Zotero MCP server — Web API v3 + local API, safe writes, citations, search.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Ispas-Catalin/hermes-nutrition-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server