No description
Find a file
Anthony Merlo a072c6ba5e fix: potassium/calcium/magnesium unit conversion (g → mg)
OFF stores potassium_100g, calcium_100g, magnesium_100g in grams.
Goals are in mg. sum_nutriments now multiplies these by 1000.

Before: potassium showed 0.7mg (was 0.0007g displayed as mg)
After:  potassium shows 691.2mg (banana: 0.32g/100g × 216g × 1000)

Added MG_NUTRIENTS const to db.rs. Updated test assertions.
31 tests passing.
2026-08-21 10:10:22 +01:00
.agents/skills/beads bd init: initialize beads issue tracking 2026-08-20 16:39:21 +01:00
.beads feat: scriptable script + /ingest endpoint + smoothie recipe 2026-08-21 09:30:20 +01:00
.claude bd init: initialize beads issue tracking 2026-08-20 16:39:21 +01:00
.codex bd init: initialize beads issue tracking 2026-08-20 16:39:21 +01:00
recipes feat: scriptable script + /ingest endpoint + smoothie recipe 2026-08-21 09:30:20 +01:00
scripts fix: use Scripting app API (Health.queryQuantitySamples + HealthUnit) 2026-08-21 00:19:27 +01:00
src fix: potassium/calcium/magnesium unit conversion (g → mg) 2026-08-21 10:10:22 +01:00
tests fix: potassium/calcium/magnesium unit conversion (g → mg) 2026-08-21 10:10:22 +01:00
.gitignore feat: POST /ingest endpoint + recent_vitals MCP tool for Apple Health 2026-08-20 21:32:19 +01:00
AGENTS.md docs: README.md, AGENTS.md, CLAUDE.md 2026-08-20 16:53:33 +01:00
Cargo.lock test: add 25-test suite + fix sum_nutriments display keys 2026-08-20 17:25:41 +01:00
Cargo.toml test: add 25-test suite + fix sum_nutriments display keys 2026-08-20 17:25:41 +01:00
CLAUDE.md docs: README.md, AGENTS.md, CLAUDE.md 2026-08-20 16:53:33 +01:00
README.md docs: README.md, AGENTS.md, CLAUDE.md 2026-08-20 16:53:33 +01:00

Nutrition MCP

Personal calorie and nutrient tracking MCP server. Looks up food via OpenFood Facts, logs meals with portion-scaled nutrients, and tracks daily intake against gout and hypertension-aware goals.

Tech Stack

  • Rust — Systems language
  • rmcp — Official Rust MCP SDK (streamable HTTP transport)
  • axum 0.8 — Web framework for HTTP transport + auth middleware
  • sqlx 0.8 — Async SQLite
  • reqwest 0.12 — HTTP client for OpenFood Facts APIs
  • SQLite with FTS5 — Local database + full-text search

Health Context

This tracker is configured for two specific health conditions:

  • Gout — Tracks fructose (15g/day limit) and alcohol (0 limit). Both are known gout triggers.
  • Hypertension — Tracks salt (6g/day, NHS guideline), potassium (3500mg, helps lower BP), calcium (700mg), magnesium (300mg), and cholesterol (300mg).

14 Tracked Nutrients

Nutrient OFF field Default goal Unit Reason
Energy energy-kcal_100g 2500 kcal General
Protein proteins_100g 150 g General
Carbohydrates carbohydrates_100g 300 g General
Fat fat_100g 70 g General
Fiber fiber_100g 30 g General
Sugars sugars_100g 90 g General
Saturated fat saturated-fat_100g 20 g Hypertension
Salt salt_100g 6 g Hypertension (key)
Fructose fructose_100g 15 g Gout (key)
Alcohol alcohol_100g 0 % vol Gout (key)
Potassium potassium_100g 3500 mg Hypertension (key)
Calcium calcium_100g 700 mg Hypertension
Magnesium magnesium_100g 300 mg Hypertension
Cholesterol cholesterol_100g 300 mg Hypertension

MCP Tools (13)

Food Lookup

  • search_food(query, page_size?) — Full-text search via OpenFood Facts Search-a-licious
  • get_food_by_barcode(barcode) — Product lookup by barcode via OFF API v3

Logging

  • log_food(product_code, grams?, servings?, date?, meal?) — Log OFF product with portion scaling
  • log_custom_food(name, calories, nutriments?, grams, date?, meal?) — Log homemade/restaurant food
  • delete_entry(id) — Remove a logged entry

Summary & History

  • daily_summary(date?) — All 14 nutrients vs goals, remaining, entry list
  • history(days?) — Last N days of totals (default 7)
  • list_entries(date?) — List entries with IDs for deletion

Goals

  • get_goals() — Current daily nutrient targets
  • set_goals(goals) — Update goals (partial merge)

Weight

  • log_weight(weight_kg, date?) — Log body weight in kg
  • weight_history(days?) — Weight trend (default 30 days)

Future

  • bulk_import(parquet_url?) — Stub for offline Parquet import

Build

cargo build --release

Binary: target/release/nutrition-mcp

Environment Variables

Variable Default Description
NUTRITION_MCP_BIND 0.0.0.0:9432 Bind address
NUTRITION_MCP_API_KEY (random UUID) Bearer token for auth
NUTRITION_MCP_DB_PATH ~/.local/share/nutrition/nutrition.db SQLite database path
NUTRITION_MCP_OFF_USER_AGENT NutritionMCP/0.1.0 (personal use) User-Agent for OFF API

Run

NUTRITION_MCP_API_KEY=your-secret-key \
NUTRITION_MCP_BIND=0.0.0.0:9432 \
./target/release/nutrition-mcp

Health Check

curl http://localhost:9432/health
# → OK

MCP Connect

curl -X POST http://localhost:9432/mcp \
  -H "Authorization: Bearer your-secret-key" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}},"id":1}'

Deploy as systemd Service

# Create service file
cat > ~/.config/systemd/user/nutrition-mcp.service << 'EOF'
[Unit]
Description=Nutrition MCP Server
After=network.target

[Service]
ExecStart=%h/workspace/nutrition-mcp/target/release/nutrition-mcp
Environment=NUTRITION_MCP_BIND=0.0.0.0:9432
Environment=NUTRITION_MCP_API_KEY=your-secret-key
Environment=NUTRITION_MCP_DB_PATH=%h/.local/share/nutrition/nutrition.db
Environment=NUTRITION_MCP_OFF_USER_AGENT=NutritionMCP/0.1.0 (personal use; contact: atradeus@pm.me)
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
EOF

# Enable linger (survive logout)
loginctl enable-linger $USER

# Start
systemctl --user daemon-reload
systemctl --user enable --now nutrition-mcp

Connect from Hermes

hermes mcp add nutrition --url http://localhost:9432 --header "Authorization: Bearer your-secret-key"

Connect from Laptop (LAN)

hermes mcp add nutrition --url http://chronos:9432 --header "Authorization: Bearer your-secret-key"

Data Sources

All food data is cached locally in SQLite with FTS5 for instant repeat lookups.

Architecture

See AGENTS.md for full project instructions, conventions, and module map.

License

MIT