No description
- HealthUnit.gram(prefix) → HealthUnit.gramUnit(prefix) (Scripting app API)
- HealthUnit.millimeterOfMercury() → HealthUnit.fromString('mmHg')
- Updated header: Scriptable → Scripting app
- content-disposition: inline instead of attachment (fixes download issue)
|
||
|---|---|---|
| .agents/skills/beads | ||
| .beads | ||
| .claude | ||
| .codex | ||
| data | ||
| recipes | ||
| scripts | ||
| src | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| README.md | ||
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-liciousget_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 scalinglog_custom_food(name, calories, nutriments?, grams, date?, meal?)— Log homemade/restaurant fooddelete_entry(id)— Remove a logged entry
Summary & History
daily_summary(date?)— All 14 nutrients vs goals, remaining, entry listhistory(days?)— Last N days of totals (default 7)list_entries(date?)— List entries with IDs for deletion
Goals
get_goals()— Current daily nutrient targetsset_goals(goals)— Update goals (partial merge)
Weight
log_weight(weight_kg, date?)— Log body weight in kgweight_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
- OpenFood Facts Search-a-licious — Full-text product search
- OpenFood Facts API v3 — Barcode lookups
- OpenFood Facts Parquet — Future offline bulk import (7.82 GB, 4.7M products)
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