Nutrition Research Assistant

Nutrition Research Assistant

Enables natural-language nutrition research for Indian foods, combining a curated knowledge base with hybrid RAG and specialized agents. Provides MCP tools for knowledge search, safe calculations, document retrieval, and optional live web search.

Category
Visit Server

README

Nutrition Research Assistant

Production-grade multi-agent Indian nutrition research assistant: answers questions about Indian food and nutrition by combining a curated internal knowledge base, hybrid RAG, specialized agents, MCP tools, conversational memory, optional live web search, graceful failure handling, and end-to-end OpenTelemetry-compatible tracing.

graph TD
    Client[CLI / Swagger / Demo script] --> API[FastAPI :8000]
    API --> Sup[Agno Supervisor]
    Sup --> KA[Knowledge Agent]
    Sup --> CA[Calculator Agent]
    Sup --> DA[Document Agent]
    Sup --> WA[Health/Web Agent]
    KA --> MCP[FastMCP Server :8001/mcp]
    CA --> MCP
    DA --> MCP
    WA --> MCP
    MCP --> Chroma[ChromaDB + BM25 + RRF + Reranker]
    MCP --> Calc[Safe calculator]
    MCP --> Web[Agno DDGSTools]
    MCP --> Docs[documents.json]
    Sup --> Mem[(SQLite memory)]
    API --> OTel[OpenTelemetry + structlog]

Core principle (PRD §89): the LLM decides what should happen; MCP tools perform what must happen deterministically. Agents never touch Chroma directly — everything flows through MCP.

Tech Stack

Layer Choice
Python / packages 3.12+ · uv (pyproject.toml + lock)
LLM DeepSeek deepseek-v4-flash (OpenAI-compatible)
Agents Agno (Supervisor + 4 specialized agents)
MCP FastMCP server, streamable-http on :8001/mcp
Vector DB ChromaDB (local, cosine)
Embeddings BAAI/bge-small-en-v1.5 (local)
Reranker BAAI/bge-reranker-base (local cross-encoder)
BM25 rank_bm25
Memory Agno sessions + SQLite (data/app.db)
API FastAPI + uvicorn
Observability OpenTelemetry (console exporter; OTLP-swappable) + structlog
Web search Agno built-in DDGSTools (optional)

Repository Layout

corpus/         8 curated nutrition documents (frontmatter + per-food tables)
scripts/        ingest.py · rebuild_index.py · test_retrieval.py · eval_questions.json
                test_mcp_wiring.py · test_agents.py · test_memory.py · demo.py
src/
  api/          FastAPI app, routes, schemas          (chat / health / ready)
  agents/       models.py (DeepSeek) · mcp_client.py · agents.py (specialists + supervisor)
  mcp_server/   server.py + tools/{knowledge,calculator,documents,web}.py
  rag/          embeddings · chroma · bm25 · fusion (RRF) · reranker · pipeline
  memory/       SQLite storage
  services/     circuit breaker · retry
  observability tracing (OTel) · logging (structlog)
  config/       settings.py          core/ errors.py · models.py
  cli.py        REPL client
tests/          unit + API tests

Quick Start

# 1. Environment
uv venv --python 3.12
uv sync

# 2. Secrets
cp .env.example .env        # set DEEPSEEK_API_KEY

# 3. Ingest the corpus (downloads bge-small-en-v1.5 on first run)
uv run python scripts/ingest.py

# 4. Start the MCP tool server  (terminal 1)
uv run python -m src.mcp_server.server

# 5. Start the API                 (terminal 2)
uv run uvicorn src.api.app:app --reload --port 8000

Swagger UI: http://127.0.0.1:8000/docs (API port is configurable via API_PORT in .env — this workspace uses 8002 because 8000 is taken)

Try it:

uv run python -m src.cli                # interactive REPL
uv run python scripts/demo.py           # scripted 5-question demo
curl -X POST http://127.0.0.1:8000/api/v1/chat \
  -H "Content-Type: application/json" \
  -d '{"session_id":"demo","message":"How much protein is in 100g cooked chickpeas?"}'

API

Endpoint Purpose
POST /api/v1/chat {session_id, message}{status, session_id, response, sources[], trace_id}
GET /health {status, mcp, chroma, llm} — liveness, no secrets
GET /ready {status, checks} — alive vs ready distinction

Degraded responses carry status: "degraded", a human-readable message, and the trace_id — never a 500 traceback.

MCP Tools (port 8001)

Tool Backend Notes
search_knowledge(query, top_k, filters) hybrid RAG (dense + BM25 + RRF + rerank) returns chunks with document_id / score / method
calculate(expression) AST-whitelisted safe evaluator no eval, no code execution
get_document(document_id) ingested documents.json never fabricates ids
search_web(query) Agno DDGSTools optional; WEB_SEARCH_ENABLED
search_health_information(query) DDGSTools + domain ranking prioritizes WHO/ICMR/NIH/CDC

Agents

Agent Tools Handles
Supervisor team of 4 intent, routing, composition, memory
Knowledge search_knowledge nutrition facts, comparisons, raw vs cooked
Calculator calculate serving scaling, totals
Document get_document document retrieval
Health/Web web + health search current info, general health (educational only)

Failure Handling

  • MCP down → controlled degraded response with trace_id (no 500); circuit breaker fails fast, probes after cooldown (PRD §70/§85)
  • MCP timeout — 10s transport read timeout; agent run bounded by AGENT_TIMEOUT_SECONDS
  • Chroma down → "Knowledge retrieval temporarily unavailable" (optionally falls back to web)
  • LLM down / bad keyLLM_UNAVAILABLE-style degraded message
  • Web disabled → "Live search is currently unavailable."
  • Retry policy: 2 attempts with backoff, then degrade — never endless

Observability

Every request produces one trace: api.request → supervisor.run → mcp.<tool> → rag.dense_search / rag.bm25 / rag.rrf / rag.reranker, with trace_id echoed in the API response, logs, and spans. All logs are JSON (structlog) with timestamp, level, logger, trace_id, span_id. Set OTEL_EXPORTER_OTLP_ENDPOINT to export to Jaeger/Tempo/Collector (uv sync --extra otel).

Tests & Retrieval Eval

uv run pytest -q
uv run python scripts/test_retrieval.py --rerank   # Recall@5/10, MRR, Hit@1/3 over 24 questions

The eval dataset (scripts/eval_questions.json, 24 questions across 7 categories) measures retrieval quality; the reranker lifts Hit@1/3 over raw fusion. Results land in data/eval/results.json.

Definition of Done (PRD §87)

  • Core — FastAPI runs; DeepSeek via OpenAI-compatible client; Agno agents operational; FastMCP operational; Chroma populated; 8 documents; memory works
  • MCP — all 5 tools work and agents use MCP as the real execution path
  • RAG — dense + BM25 + RRF + cross-encoder rerank; metadata preserved; eval exists
  • Agents — Supervisor + 4 specialists; multi-agent composition works
  • Memory — session ids; follow-ups resolve; persisted in SQLite
  • Observability — trace_id per request; nested spans; MCP/RAG/LLM/errors traced
  • Failure handling — MCP unavailable/timeout, Chroma, LLM, web all controlled; no unhandled exception reaches the user

Troubleshooting

  • Hugging Face symlink warning — Windows-only; set HF_HUB_DISABLE_SYMLINKS_WARNING=1 (cosmetic)
  • Retrieval returns nothing — Chroma empty: run python scripts/ingest.py
  • "tool service unavailable" — MCP server not running (start it) or breaker cooling down (wait ~30s, or restart API)
  • Health says llm not_configuredDEEPSEEK_API_KEY missing in .env

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured