NutriTrace
Self-hosted personal nutrition and calorie tracker
Alternative to: myfitnesspal, cronometer, lose it, waistline

v1.2.0-dev01
2026-08-09First dev pre-release of the 1.2.0 minor. Introduces the Model Context Protocol (MCP) server so external AI clients (Claude Desktop, Cursor, Codex, VS Code) can talk to a running NutriTrace instance. Off by default; opt in with env flags.
Added
- Model Context Protocol server (#103, thanks @javydekoning). 12 tools across three tiers, each gated by its own env flag AND its own token scope, so admins can dial the surface area precisely. Read tools (5):
get_goals,get_daily_totals,list_diary_entries,search_foods,get_recent_foods. Enabled withMCP_ENABLED=1on the server and a token holdingmcp:read. Write tools (4):log_food,log_water,log_meal,log_body_stat. AddsMCP_WRITE_ENABLED=1andmcp:write. All additive; everything lands as normal editable entries in the diary UI. Destructive tools (3):delete_diary_entry,edit_diary_entry,create_food. AddsMCP_DESTROY_ENABLED=1,mcp:destroy, AND every call must includeconfirm: true(belt-and-suspenders: your MCP client already prompts per action, but the tool also refuses without the arg so a hallucinated call from a client that skips prompts still gets rejected). Tombstoned diary days are protected: writes refuse rather than silently resurrect an erased day. Every tool query is scoped onuser_id(static test enforces this on every future change). Full setup + Claude Desktop config: docs/nutritrace/mcp/. Tool reference: reference/mcp-tools/.
Changed
- Settings → API Tokens picker now shows a human-readable description under each scope. Previously the picker rendered only the raw scope name (
mcp:read,mcp:write,read:foods, etc.) with no hint what each grants. Admins had to cross-reference the federation / MCP docs to pick correctly. Descriptions load from the server so any future scope addition automatically explains itself. - Settings → API Tokens picker also shows a live MCP status indicator. When any of
MCP_ENABLED/MCP_WRITE_ENABLED/MCP_DESTROY_ENABLEDis set on the server, a pill above the scope grid displays which tiers are actually active. Prevents the pit where an admin mints a token withmcp:writeon a server that doesn’t haveMCP_WRITE_ENABLED=1and can’t figure out why the tool never appears.
Testing notes
- Everything MCP-related is opt-in. Leaving the env flags unset means zero change from v1.1.2.
- Repo ships
scripts/mcp-smoke.mjswhich hits a running instance end-to-end (handshake, tools/list, invoke each tool, verify auth + origin gates). Add--writesand--destroyto exercise those tiers too. - Static wiring test (
scripts/mcp-wiring.test.js, 17 checks) + integration test against a real temp SQLite (scripts/mcp-integration.test.js, ~20 assertions covering LIKE-escape, portion scaling, alt_units refusal, tombstone protection, source preservation, legacy body_stats refusal,confirm=truegating, dedup, per-nutriment value cap) both pass ondev. - 11 code-review passes across the three phases surfaced 66 static-analysis findings, all resolved before release. Real-world usage will surface a different class of bugs; please file issues for anything odd.
Signed APK on this release page. Docker image is multi-arch (amd64 + arm64):
docker compose pull && docker compose up -d
To turn MCP on, add to your docker-compose.yml under the nutritrace service environment: list:
- MCP_ENABLED=1
# - MCP_WRITE_ENABLED=1 # optional, unlocks the 4 log tools
# - MCP_DESTROY_ENABLED=1 # optional, unlocks the 3 destructive tools