Nutrition Research Assistant
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 ( |
LLM | DeepSeek |
Agents | Agno (Supervisor + 4 specialized agents) |
MCP | FastMCP server, streamable-http on |
Vector DB | ChromaDB (local, cosine) |
Embeddings |
|
Reranker |
|
BM25 |
|
Memory | Agno sessions + SQLite ( |
API | FastAPI + uvicorn |
Observability | OpenTelemetry (console exporter; OTLP-swappable) + structlog |
Web search | Agno built-in |
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 testsQuick 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 8000Swagger 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 |
|
|
|
|
|
|
Degraded responses carry status: "degraded", a human-readable message, and the trace_id — never a 500 traceback.
MCP Tools (port 8001)
Tool | Backend | Notes |
| hybrid RAG (dense + BM25 + RRF + rerank) | returns chunks with document_id / score / method |
| AST-whitelisted safe evaluator | no |
| ingested | never fabricates ids |
| Agno | optional; |
| DDGSTools + domain ranking | prioritizes WHO/ICMR/NIH/CDC |
Agents
Agent | Tools | Handles |
Supervisor | team of 4 | intent, routing, composition, memory |
Knowledge |
| nutrition facts, comparisons, raw vs cooked |
Calculator |
| serving scaling, totals |
Document |
| document retrieval |
Health/Web | web + health search | current info, general health (educational only) |
Failure Handling
MCP down → controlled
degradedresponse 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_SECONDSChroma down → "Knowledge retrieval temporarily unavailable" (optionally falls back to web)
LLM down / bad key →
LLM_UNAVAILABLE-style degraded messageWeb 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 questionsThe 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_configured —
DEEPSEEK_API_KEYmissing in.env
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/yash-desai-naik/interview-task-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server