nutrition-mcp/AGENTS.md
Anthony Merlo 5beef81d70 docs: README.md, AGENTS.md, CLAUDE.md
- README: human-facing with tech stack, 14 nutrient table, 13 tools,
  env vars, build/run/deploy instructions, Hermes integration
- AGENTS/CLAUDE: build commands, architecture, module map, SQLite
  schema, conventions, tracked nutrients, session protocol

Closes nutrition-mcp-yd5, nutrition-mcp-4lv
2026-08-20 16:53:33 +01:00

111 lines
No EOL
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Agent Instructions
This project uses **bd** (beads) for issue tracking. Run `bd prime` for full workflow context.
## Build & Test
```bash
cargo build --release # Build binary
cargo test # Run unit tests
./target/release/nutrition-mcp # Run server (needs env vars)
```
### Smoke Test
```bash
# Start server
NUTRITION_MCP_BIND=127.0.0.1:9432 NUTRITION_MCP_API_KEY=test \
NUTRITION_MCP_DB_PATH=/tmp/test.db ./target/release/nutrition-mcp &
# Health check
curl http://127.0.0.1:9432/health
# MCP initialize
curl -X POST http://127.0.0.1:9432/mcp \
-H "Authorization: Bearer test" \
-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}'
```
## Architecture Overview
MCP server exposing 13 tools for personal nutrition tracking. Streamable HTTP transport with Bearer token auth.
### Module Map
```
src/
├── main.rs — Entry point: axum server, auth middleware, /health endpoint
├── config.rs — Config struct from env vars (bind, api_key, db_path, user_agent)
├── db.rs — SQLite schema, migrations, DbPool type, TRACKED_NUTRIENTS const, DEFAULT_GOALS_JSON
├── api.rs — OffClient: Search-a-licious + v3 barcode + SQLite cache (FTS5)
└── tools.rs — NutritionServer: 13 MCP tools via #[tool_router] + ServerHandler impl
```
### SQLite Schema
- **products** — OFF cache: code (PK), product_name, brands, nutriments (JSON), serving_quantity, serving_size, image_url
- **products_fts** — FTS5 virtual table on product_name (synced via triggers)
- **entries** — Food log: id, date, meal, product_code, food_name, grams, servings, nutriments (JSON, scaled to portion)
- **daily_goal** — Single row (id=1), goals JSON with 14 nutrient targets
- **weight_log** — id, date, weight_kg
### Nutrient Storage
All nutrients stored as JSON blob in `nutriments` TEXT column (verbatim from OFF API). Daily summaries use `json_extract()` or Rust-side parsing to aggregate the 14 tracked nutrients.
### Portion Scaling
Nutrients are stored per-100g in OFF data. When logging, `scale_nutriments()` multiplies each value by `grams / 100.0`. For servings, grams = `servings * serving_quantity`.
### Meal Auto-Detection
- breakfast: before 11:00
- lunch: 11:00–15:00
- dinner: 15:00–21:00
- snack: after 21:00
## Conventions & Patterns
- **JSON nutriments** — Never hardcode nutrient columns. Store OFF nutriments verbatim as JSON, query at runtime.
- **"no data" vs 0** — Micronutrients (potassium, calcium, magnesium) are sparse in OFF. Summary shows `"no data"` when no entries have the nutrient, not 0.
- **Env vars only** — No config files. All settings via environment variables.
- **API-first** — Always check SQLite cache first, fall back to OFF API, cache results.
- **User-Agent** — Always send custom User-Agent to OFF API (good citizenship).
## Tracked Nutrients (14)
```
energy_kcal → energy-kcal_100g
protein → proteins_100g
carbohydrates → carbohydrates_100g
fat → fat_100g
fiber → fiber_100g
sugars → sugars_100g
saturated_fat → saturated-fat_100g
salt → salt_100g
fructose → fructose_100g (gout)
alcohol → alcohol_100g (gout)
potassium → potassium_100g (hypertension)
calcium → calcium_100g (hypertension)
magnesium → magnesium_100g (hypertension)
cholesterol → cholesterol_100g (hypertension)
```
## Non-Interactive Shell Commands
**ALWAYS use non-interactive flags** to avoid hanging on confirmation prompts.
```bash
cp -f source dest # NOT: cp source dest
rm -f file # NOT: rm file
```
## Session Completion
1. **File issues for remaining work** - `bd create` for follow-up items
2. **Run quality gates** - `cargo build --release && cargo test`
3. **Close completed issues** - `bd close <id1> <id2> ...`
4. **PUSH** - `git add -A && git commit -m "..." && git push`
5. **Verify** - `git status` must show clean working tree