# Project export: Sweet by Metabolic Company of CalHacks

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: Sweet is an iMessage native diabetes management AI assistant.
- Devpost: https://devpost.com/software/sweet-by-metabolic-company-of-calhacks
- GitHub: https://github.com/hemanthkapa/Sweet
- Video: https://www.youtube.com/embed/bO0LeXn3RPY?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Result: winner (Interaction Company: Best MCP Automation)
- Team: 2 GitHub contributor(s) — Hemanth Kapa (11 commits), GyuJin Lee (10 commits)

## Devpost submission (written by the team)

### Inspiration

Living with diabetes means juggling between multiple tasks everyday from checking glucose levels to calculating carbs to giving right dosing of insulin, all while trying to live normally. We thought, what if instead of using complex apps and manual tracking, you could simply text your phone like you're talking to a friend, and get instant, intelligent help with your diabetes management?

### What it does

Sweet lets users manage diabetes through conversational text messages with an AI assistant. The AI analyzes meals, monitors glucose levels, and calculates insulin doses using real-time data integration. Users text the Poke AI to get instant health insights, and the system learns patterns over time to provide personalized recommendations. Real-time Dexcom CGM integration AI-powered meal analysis from photos Personalized insulin dose calculations Glucose pattern tracking based on food/activity and send alerts when needed SMS-based conversational interface

### How we built it

Sweet is built as an MCP (Model Context Protocol) server that integrates multiple APIs and AI services: FastMCP Framework: Used FastMCP as the foundation for our MCP server, enabling seamless integration with Poke's conversational interface Dexcom Integration: Connected to Dexcom's Share API for real-time CGM data retrieval and glucose trend analysis AI-Powered Intelligence: Integrated Gemini API for NLP, food recognition, and personalized nutrition analysis SMS Communication: Implemented Twilio for reliable text message alerts in an urgent situation Python Backend: Built custom modules for insulin calculation algorithms, carb ratio management, and pattern recognition logic

### Challenges we ran into

MCP Learning Curve: First-time developers struggling with Model Context Protocol architecture and tool structuring Stateless Communication: Managing HTTP requests without persistent state for real-time health data Multi-API Coordination: Synchronizing Dexcom, Gemini, and Twilio APIs in a single conversational flow Medical Data Reliability: Ensuring accurate, safe handling of critical health information under all conditions. (Our tool is still in its early stages, so insulin dosage and macros predictions may not yet be fully reliable.) Dexcom API Complexity: Navigating between Sandbox and Share APIs, understanding authentication flows, and parsing complex glucose data structures

### Accomplishments we're proud of

Seamless Multi-API Integration: Successfully unified Dexcom, Gemini AI, and Twilio into the MCP server Natural Conversation Interface: Transformed complex diabetes management into simple text-based interactions Adaptive Pattern Learning: Created a system that learns and personalizes to individual users over time Real Impact Potential: Built something that could genuinely reduce the daily burden of diabetes management

### What we learned

We learned that working with healthcare data requires serious responsibility. Even a tiny mistake can have big consequences. Our goal is to build something that genuinely helps people, but safety always comes first. Creating our first healthcare MCP taught us how important it is to spot patterns and use context, so our tool can truly support users where it matters.

### What's next

Multi-Platform Expansion: Bring Sweet to Discord, Slack, WhatsApp, and native mobile apps Predictive Intelligence: ML-powered glucose forecasting and smart meal database that learns from users Clinical Integration: Web dashboard with comprehensive weekly/monthly reports for patients, healthcare provider access. Connect Poke with closed loop insulin pump for insulin dosage automation. Community Platform: Enable users to share interesting use cases and strategied they find while using the chat interface. Disclaimer: Sweet is still in development. While real-time glucose data is pulled from your sensor, macro tracking and insulin dosage suggestions are early-stage and may not be fully reliable. Please do not rely on these features for critical decisions.

## README (from the GitHub repository)

# Sweet by Metabolic Company of CalHacks

**Manage diabetes from your textbox**

## Features:

- **🔗 Dexcom Integration** - Real-time glucose monitoring with trend analysis and historical data
- **🍎 AI Food Analysis** - Smart nutrition breakdown with personalized tips using Gemini AI
- **💉 Insulin Calculator** - Precise dosing based on carbs and glucose with safety checks (keep in mind this is a fun hack, dont take it too seriosly: at least for now.)
- **📊 Pattern Learning** - Track meals and glucose responses for personalized recommendations
- **🚨 Smart Alerts** - Background monitoring with AI-generated suggestions for high/low glucose
- **🤖 MCP Server** - Works seamlessly with Poke AI assistant through conversational text

## 👻 Start:

### Prerequisites

- Dexcom Account (username and password)
- Gemini API Key
- Python 3.8+
- Ngrok account (for exposing local server)

### Setup

1. **Clone the repository**

   ```bash
   git clone <repository-url>
   cd sweet
   ```

2. **Set up Python environment**

   ```bash
   cd mcp
   python -m venv venv
   source venv/bin/activate  # On Windows: venv\Scripts\activate
   pip install -r requirements.txt
   ```

3. **Configure environment variables**
   Create a `.env` file in the `mcp/` directory:

   ```env
   DEXCOM_USERNAME=your_dexcom_userame
   DEXCOM_PASSWORD=your_dexcom_password
   DEXCOM_REGION=your_region  # Options: us, ous, jp (us=United States, ous=Outside US, jp=Japan)
   GEMINI_API_KEY=your_gemini_api_key
   # Server Configuration
   PORT=8000
   ENVIRONMENT=development
   ```

4. **Start the MCP server**

   ```bash
   cd mcp/src
   python server.py
   ```

5. **Expose server via Ngrok**
   In a new terminal:
   ```bash
   ngrok http 8000
   ```
   Copy the HTTPS URL (e.g., `https://randommonkey.ngrok-free.app`)

### Connecting to Poke

1. **Configure Poke MCP Integration**

   In your [Poke](https://poke.com) dashboard, add the Sweet MCP server:

   - Go to your Poke MCP integration settings
   - Add your ngrok URL (e.g., `https://randommonkey.ngrok-free.app/mcp`) as the server endpoint
   - This allows Poke to communicate with your running Sweet server

2. **Start using Sweet!**

   Simply text Poke on your phone with messages like:

   - "What is my current glucose level?"
   - "I'm having this meal, could you please analyze the macros based on the description/image?"
   - "How much insulin should i be taking for this meal?"
   - "Analyze my glucose levels starting this morning, what meal has affected me the most?"

   Sweet can do much more, your imagination is the limit.

## Available tools

### Main Functions:

- **`get_current_glucose()`** - Get real-time glucose reading from Dexcom CGM
- **`analyze_food(food_description)`** - AI-powered nutrition analysis with personalized tips
- **`calculate_insulin_dose(carb_grams, ...)`** - Calculate insulin dose based on carbs and glucose
- **`track_meal_context(food, carbs, insulin, glucose)`** - Log meals for pattern learning
- **`start_glucose_alerts(thresholds)`** - Begin background glucose monitoring with AI alerts
- **`get_diabetes_management_summary()`** - Get comprehensive diabetes management overview

---

Wohoo have a sweet life 💌

Disclaimer: _Sweet is still in development. While real-time glucose data is pulled from your sensor, macro tracking and insulin dosage suggestions are early-stage and may not be fully reliable. Please do not rely on these features for critical decisions._


## Detected evidence (automated analysis)

Indexed codebase: 11 recognized source files, 70 KB.
- Python (language) — detected in the code

## Codebase structure (from repository index)

### Files (14 of 14)

```
.gitignore
mcp/README.md
mcp/render.yaml
mcp/requirements.txt
mcp/src/diabetes_context.py
mcp/src/glucose_monitor.py
mcp/src/notifications.py
mcp/src/server.py
README.md
recipients.json
tests/test_dexcom_api.py
tests/test_dexcom_integration.py
tests/test_notifications.py
tests/test_server.py
```

### Dependencies

- mcp/requirements.txt: fastmcp@>=2.12.0, google-generativeai@>=0.8.0, pydexcom@>=0.4.1, python-dotenv@>=1.0.0, requests@>=2.31.0, twilio@>=9.2.3, uvicorn@>=0.35.0

### Recent commits (newest first)

- tiny edit
- moved test files
- Merge branch 'main' of https://github.com/hemanthkapa/ilovesugar
- Merge branch 'main' of https://github.com/hemanthkapa/ilovesugar
- consistency is key
- Update directory name in README instructions
- Ignore local env, caches, logs, and venv
- Stop tracking .env (contains secrets)
- Merge branch 'main' of https://github.com/hemanthkapa/ilovesugar
- Twilio Integration
- update readme and the file structure.
- threshold setup for low and high
- glucost level warning
- keeping some context
- yerbaaaa
- dexcom integration: hemanth cooked!
- dexcom api
- Merge branch 'main' of https://github.com/hemanthkapa/ilovesugar
- wohooo
- Add collaboration setup guide for teammate

## Key source files (fetched from GitHub, selected and truncated for size)

### mcp/requirements.txt

```
fastmcp>=2.12.0
uvicorn>=0.35.0
python-dotenv>=1.0.0
requests>=2.31.0
pydexcom>=0.4.1
google-generativeai>=0.8.0
twilio>=9.2.3

```

### mcp/src/server.py

```python
#!/usr/bin/env python3
import os
import json
from datetime import datetime
from fastmcp import FastMCP
from pydexcom import Dexcom
from pydexcom.errors import AccountErrorEnum
from dotenv import load_dotenv
import google.generativeai as genai
from diabetes_context import (
    track_meal_with_context,
    log_glucose_response,
    analyze_meal_patterns,
    get_smart_recommendations,
    learn_from_outcome,
    get_diabetes_summary
)
from glucose_monitor import start_monitoring, stop_monitoring, status as glucose_monitor_status
from notifications import (
    list_recipients as list_alert_recipients_impl,
    add_recipient as add_alert_recipient_impl,
    remove_recipient as remove_alert_recipient_impl,
    send_sms_to_all as send_sms_to_all_impl,
    send_glucose_alert as send_glucose_alert_impl,
)

# Load environment variables from .env file
load_dotenv()

# Configure Gemini
genai.configure(api_key=os.getenv('GEMINI_API_KEY'))

mcp = FastMCP("ilovesugar MCP Server")

@mcp.tool(description="Test connection to Poke - returns server status and timestamp")
def test_poke_connection() -> dict:
    """Test if Poke can successfully connect to this MCP server"""
    return {
        "status": "connected",
        "server": "ilovesugar MCP Server",
        "timestamp": datetime.now().isoformat(),
        "message": "Poke connection successful!"
    }

@mcp.tool(description="Greet a user by name with a welcome message from the MCP server")
def greet(name: str) -> str:
    return f"Hello, {name}! Welcome to ilovesugar MCP server!"

@mcp.tool(description="Get detailed server information including environment and capabilities")
def get_server_info() -> dict:
    return {
        "server_name": "ilovesugar MCP Server",
        "version": "1.0.0",
        "environment": os.environ.get("ENVIRONMENT", "development"),
        "python_version": os.sys.version.split()[0],
        "capabilities": ["poke_connection_test", "greeting", "server_info", "echo", "dexcom_glucose_data", "comprehensive_food_analysis", "insulin_dose_calculation", "diabetes_context_management", "glucose_monitoring_alerts"],
        "status": "ready"
    }

@mcp.tool(description="Simple echo tool to test basic functionality")
def echo(message: str) -> str:
    """Echo back the message to test basic tool functionality"""
    return f"Echo: {message}"

@mcp.tool(description="Get current glucose reading from Dexcom CGM")
def get_current_glucose() -> dict:
    """Get the most recent glucose reading from Dexcom Share service"""
    try:
        
        username = os.getenv('DEXCOM_USERNAME')
        password = os.getenv('DEXCOM_PASSWORD')
        region = os.getenv('DEXCOM_REGION', 'us')  # Default to US region
        
        if not username or not password:
            return {
                "error": "Dexcom credentials not configured",
                "message": "Please set DEXCOM_USERNAME and DEXCOM_PASSWORD environment variables"
            }
        
        # Initialize Dexcom client
        dexcom = Dexcom(username=username, password=password, region=region)
        
        # Get current glucose reading
        glucose_reading = dexcom.get_current_glucose_reading()
        
        if glucose_reading:
            return {
                "value": glucose_reading.value,
                "mg_dl": glucose_reading.mg_dl,
                "mmol_l": glucose_reading.mmol_l,
                "trend": glucose_reading.trend,
                "trend_direction": glucose_reading.trend_direction,
                "trend_description": glucose_reading.trend_description,
                "trend_arrow": glucose_reading.trend_arrow,
                "datetime": glucose_reading.datetime.isoformat(),
                "raw_data": glucose_reading.json
            }
        else:
            return {
                "error": "No glucose reading available",
                "message": "No current glucose reading found"
            }
            
    except AccountErrorEnum as e:
        return {
            "error": "Dexcom authentication failed",
            "message": f"Invalid credentials or account error: {str(e)}"
        }
    except Exception as e:
        return {
            "error": "Dexcom API error",
            "message": f"Failed to retrieve glucose data: {str(e)}"
        }

@mcp.tool(description="Get latest glucose reading from Dexcom CGM")
def get_latest_glucose() -> dict:
    """Get the latest glucose reading from Dexcom Share service"""
    try:
        
        username = os.getenv('DEXCOM_USERNAME')
        password = os.getenv('DEXCOM_PASSWORD')
        region = os.getenv('DEXCOM_REGION', 'us')  # Default to US region
        
        if not username or not password:
            return {
                "error": "Dexcom credentials not configured",
                "message": "Please set DEXCOM_USERNAME and DEXCOM_PASSWORD environment variables"
            }
        
        # Initialize Dexcom client
        dexcom = Dexcom(username=username, password=password, region=region)
        
        # Get latest glucose reading
        glucose_reading = dexcom.get_latest_glucose_reading()
        
        if glucose_reading:
            return {
                "value": glucose_reading.value,
                "mg_dl": glucose_reading.mg_dl,
                "mmol_l": glucose_reading.mmol_l,
                "trend": glucose_reading.trend,
                "trend_direction": glucose_reading.trend_direction,
                "trend_description": glucose_reading.trend_description,
                "trend_arrow": glucose_reading.trend_arrow,
                "datetime": glucose_reading.datetime.isoformat(),
                "raw_data": glucose_reading.json
            }
        else:
            return {
                "error": "No glucose reading available",
                "message": "No latest glucose reading found"
            }
            
    except AccountErrorEnum as e:
        return {
            "error": "Dexcom authentication failed",
        
[truncated — 21898 more characters]
```

### mcp/render.yaml

```yaml
services:
  - type: web
    name: fastmcp-server
    runtime: python
    buildCommand: pip install -r requirements.txt
    startCommand: python src/server.py
    plan: free
    autoDeploy: false
    envVars:
      - key: ENVIRONMENT
        value: production

```

### tests/test_notifications.py

```python
#!/usr/bin/env python3
import os
import sys
import json
from datetime import datetime

# Ensure src/ is importable
PROJECT_ROOT = os.path.dirname(os.path.dirname(__file__))
SRC_DIR = os.path.join(PROJECT_ROOT, 'src')
sys.path.insert(0, SRC_DIR)

import notifications as notif  # noqa: E402


def test_format_glucose_alert_sms_truncates():
    long_note = "A" * 500
    payload = {
        'level': 'high',
        'value': 300,
        'threshold': 250,
        'timestamp': datetime.now().isoformat(),
        'suggestion': long_note,
    }
    msg = notif.format_glucose_alert_sms(payload)
    assert '...' in msg
    # message should be reasonably short for SMS
    assert len(msg) < 300


def test_list_recipients_merges_env_and_file(tmp_path, monkeypatch):
    # prepare file recipients
    data = [
        {"name": "Alice", "phone": "+15550000001"}
    ]
    file_path = tmp_path / 'recipients.json'
    file_path.write_text(json.dumps(data), encoding='utf-8')

    # env config
    monkeypatch.setenv('ALERT_RECIPIENTS_FILE', str(file_path))
    monkeypatch.setenv('ALERT_RECIPIENTS', '+15550000002,+15550000001')  # contains duplicate

    recips = notif.list_recipients()
    phones = sorted([r['phone'] for r in recips])

    # Should contain both numbers with duplicate deduped
    assert "+15550000001" in phones
    assert "+15550000002" in phones
    assert len(phones) == 2

```

### tests/test_dexcom_integration.py

```python
#!/usr/bin/env python3
"""
Test script for Dexcom integration
This script tests the Dexcom tools via share
"""

import os
import sys
from dotenv import load_dotenv
import pytest

# Add src directory to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))

# Load environment variables
load_dotenv()

def test_dexcom_tools():
    """Test the Dexcom integration tools"""
    print("Testing Dexcom Integration...")

    # Check if credentials are configured
    username = os.getenv('DEXCOM_USERNAME')
    password = os.getenv('DEXCOM_PASSWORD')
    region = os.getenv('DEXCOM_REGION', 'us')

    if not username or not password:
        pytest.skip("Dexcom credentials not configured; skipping integration test")

    print(f" Credentials found: {username} (region: {region})")

    # Test pydexcom directly
    from pydexcom import Dexcom

    print("\nTesting Dexcom connection...")
    dexcom = Dexcom(username=username, password=password, region=region)
    assert dexcom is not None

    print("Testing get_current_glucose_reading()...")
    glucose_reading = dexcom.get_current_glucose_reading()
    # Allow None; just ensure no exception and type consistency when present
    if glucose_reading:
        assert hasattr(glucose_reading, 'value')

    print("\nTesting get_latest_glucose_reading()...")
    latest_reading = dexcom.get_latest_glucose_reading()
    if latest_reading:
        assert hasattr(latest_reading, 'value')

    print("\nTesting get_glucose_readings(minutes=60)...")
    glucose_readings = dexcom.get_glucose_readings(minutes=60)
    if glucose_readings:
        assert isinstance(glucose_readings, list)

if __name__ == "__main__":
    success = test_dexcom_tools()
    if success:
        print("\n Dexcom integration test completed!")
    else:
        print("\nDexcom integration test failed!")
        sys.exit(1)

```

### tests/test_server.py

```python
#!/usr/bin/env python3
"""
Test script for ilovesugar MCP server
Tests basic connectivity and tool functionality
"""
import requests
import json
import time
import sys
import pytest

def test_server_health():
    """Test if the server is running and accessible"""
    # Test basic server response
    response = requests.get("http://localhost:8000/", timeout=5)
    print(f" Server is running (status: {response.status_code})")
    # FastMCP may not serve '/' with 200; 404 is acceptable as long as server responds
    assert response.status_code in (200, 404)

def test_mcp_endpoint():
    """Test the MCP endpoint specifically"""
    response = requests.get("http://localhost:8000/mcp", timeout=5)
    print(f" MCP endpoint accessible (status: {response.status_code})")
    # GET /mcp may return 406 (Not Acceptable) without proper headers; accept 200 or 406
    assert response.status_code in (200, 406)

def test_tools_via_http():
    """Test if we can call tools via HTTP (basic test)"""
    #checking if server responds
    response = requests.get("http://localhost:8000/mcp", timeout=5)
    print("Server responds to MCP requests")
    assert response.status_code in (200, 406)

def main():
    """Run all server tests"""
    print("Testing ilovesugar MCP Server")
    print("=" * 40)
    
    # Test 1: Server health
    print("\n1. Testing server health...")
    if not test_server_health():
        print("\n💡 Make sure to start the server first:")
        print("   cd /Users/kapa/Documents/ilovesugar")
        print("   source venv/bin/activate")
        print("   python src/server.py")
        sys.exit(1)
    
    # Test 2: MCP endpoint
    print("\n2. Testing MCP endpoint...")
    test_mcp_endpoint()
    
    # Test 3: Basic functionality
    print("\n3. Testing basic functionality...")
    test_tools_via_http()
    
    print("\n" + "=" * 40)
    print(" Server tests completed!")
    print("\nNext steps:")
    print("1. Start ngrok: ngrok http 8000")
    print("2. Add the ngrok URL to Poke at poke.com/settings/connections")
    print("3. Test with Poke: 'Test the ilovesugar connection'")

if __name__ == "__main__":
    main()
```

### tests/test_dexcom_api.py

```python
import requests
import json
from urllib.parse import urlparse, parse_qs
from dotenv import load_dotenv
import os

load_dotenv(dotenv_path='.env')

DEXCOM_API_URL = 'https://sandbox-api.dexcom.com'
DEXCOM_CLIENT = os.getenv('DEXCOM_CLIENT')
DEXCOM_CLIENT_SECRET = os.getenv('DEXCOM_CLIENT_SECRET')
REDIRECT_URI = os.getenv('REDIRECT_URI')

def get_auth_url():
    """1. Generates the URL for Dexcom login and authorization."""
    auth_url = (
        f"{DEXCOM_API_URL}/v2/oauth2/login?"
        f"client_id={DEXCOM_CLIENT}&"
        f"redirect_uri={REDIRECT_URI}&"
        f"response_type=code&"
        f"scope=offline_access"
    )
    return auth_url

def get_access_token(code):
    """3. Exchanges the received 'code' for an 'access_token'."""
    token_url = f'{DEXCOM_API_URL}/v2/oauth2/token'
    data = {
        'client_id': DEXCOM_CLIENT,
        'client_secret': DEXCOM_CLIENT_SECRET,
        'code': code,
        'grant_type': 'authorization_code',
        'redirect_uri': REDIRECT_URI
    }
    
    try:
        print("\n--- 2. Exchanging for access token... ---")
        response = requests.post(token_url, data=data)
        response.raise_for_status() # Raise an exception if there's an error
        
        tokens = response.json()
        access_token = tokens['access_token']
        print("Successfully received access token.")
        return access_token
    
    except requests.exceptions.RequestException as e:
        print(f"\nFailed to exchange token.")
        print(f"Error: {e}")
        print(f"Server response: {response.text}")
        return None

def get_glucose_data(access_token):
    """4. Fetches glucose data using the 'access_token'."""
    headers = {'Authorization': f'Bearer {access_token}'}
    
    # Fixed date for querying sandbox data
    glucose_url = f'{DEXCOM_API_URL}/v3/users/self/egvs'
    params = {
        'startDate': '2024-01-01T00:00:00',
        'endDate': '2024-01-02T00:00:00'
    }

    try:
        print("\n--- 3. Fetching glucose data... ---")
        response = requests.get(glucose_url, headers=headers, params=params)
        response.raise_for_status()
        
        glucose_data = response.json()
        print("Successfully fetched data.")
        return glucose_data
        
    except requests.exceptions.RequestException as e:
        print(f"\nFailed to fetch data.")
        if response.status_code == 401:
            print("Error: 401 Unauthorized (Token may be expired or invalid.)")
        else:
            print(f"Error: {e}")
        print(f"Server response: {response.text}")
        return None

def main():
    # 0. Check if required libraries are installed
    try:
        import requests
    except ImportError:
        print(" 'requests' library is required. Please run: pip install requests")
        return

    # 1. Generate and print the authorization URL
    auth_url = get_auth_url()
    print("--- 1. Start Dexcom Authorization ---")
    print("Copy the URL below and open it in your web browser:")
    print("\n" + auth_url + "\n")
    print("After logging in, you might see an error page like 'This site can’t be reached'. (This is normal)")
    print("Copy the **entire address (URL)** from that page and paste it below:")
    
    # 2. Get the callback URL from the user
    callback_url = input("\nPaste URL here: ")
    
    # Parse the 'code' from the input URL
    try:
        parsed_url = urlparse(callback_url)
        query_params = parse_qs(parsed_url.query)
        
        if 'code' not in query_params:
            print("\nCould not find 'code' in the URL. Please check if you copied the address correctly.")
            return
            
        code = query_params['code'][0]
        print("\nSuccessfully extracted authorization code.")
    
    except Exception as e:
        print(f"\nError parsing URL: {e}")
        return

    # 3. Get 'access_token' with the 'code'
    token = get_access_token(code)
    
    if token:
        # 4. Fetch data with the 'access_token'
        data = get_glucose_data(token)
        
        if data:
            # 5. Print the result (JSON)
            print("\n--- 4. Final Result (JSON) ---")
            print(json.dumps(data, indent=2, ensure_ascii=False))

if __name__ == "__main__":
    main()
```

### mcp/src/notifications.py

```python
#!/usr/bin/env python3
"""
Notifications module for sending glucose alerts via SMS (Twilio) and managing recipients.

- Reads Twilio credentials from environment variables:
  TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM
- Reads recipients from either a JSON file or environment variable ALERT_RECIPIENTS.
  - ALERT_RECIPIENTS: comma-separated phone numbers, e.g. "+15551234567,+15557654321"
  - ALERT_RECIPIENTS_FILE: optional path to a JSON file storing an array of {name, phone}

Safe defaults:
- If Twilio isn't configured or import fails, we fall back to dry-run logging (no external calls).
- All sends are best-effort and never crash the caller; errors are returned in the result list.
"""

from __future__ import annotations

import json
import os
from dataclasses import dataclass
from datetime import datetime
from typing import List, Dict, Any, Optional


DEFAULT_RECIPIENTS_FILE = os.path.abspath(
    os.path.join(os.path.dirname(__file__), '..', 'recipients.json')
)


def _recipients_file_path() -> str:
    return os.getenv('ALERT_RECIPIENTS_FILE', DEFAULT_RECIPIENTS_FILE)


def _load_file_recipients() -> List[Dict[str, str]]:
    path = _recipients_file_path()
    if not os.path.exists(path):
        return []
    try:
        with open(path, 'r', encoding='utf-8') as f:
            data = json.load(f)
            if isinstance(data, list):
                # Normalize entries
                norm = []
                for item in data:
                    if isinstance(item, dict) and 'phone' in item:
                        norm.append({
                            'name': item.get('name') or '',
                            'phone': str(item['phone']).strip()
                        })
                return norm
    except Exception:
        pass
    return []


def _save_file_recipients(items: List[Dict[str, str]]) -> None:
    path = _recipients_file_path()
    try:
        with open(path, 'w', encoding='utf-8') as f:
            json.dump(items, f, indent=2, ensure_ascii=False)
    except Exception:
        # Best-effort; upstream should surface an error if needed
        pass


def list_recipients() -> List[Dict[str, str]]:
    """Return the merged list of alert recipients from file and env.

    Environment variable ALERT_RECIPIENTS (comma-separated phone numbers)
    is merged with the file-based list (deduped by phone).
    """
    file_list = _load_file_recipients()
    by_phone = {r['phone']: r for r in file_list if 'phone' in r and r['phone']}

    env_list: List[Dict[str, str]] = []
    env_str = os.getenv('ALERT_RECIPIENTS', '').strip()
    if env_str:
        for phone in [p.strip() for p in env_str.split(',') if p.strip()]:
            if phone not in by_phone:
                env_list.append({'name': '', 'phone': phone})

    # Merge and sort by name/phone for deterministic order
    merged = list(by_phone.values()) + env_list
    merged.sort(key=lambda x: (x.get('name') or '', x.get('phone') or ''))
    return merged


def add_recipient(name: str, phone: str) -> Dict[str, Any]:
    """Add a recipient to the file-backed list (env recipients are read-only)."""
    phone = (phone or '').strip()
    if not phone:
        return {"added": False, "error": "Phone is required"}

    items = _load_file_recipients()
    if any(r.get('phone') == phone for r in items):
        return {"added": False, "message": "Recipient already exists", "recipients": items}

    items.append({"name": name or '', "phone": phone})
    _save_file_recipients(items)
    return {"added": True, "recipients": items}


def remove_recipient(phone: str) -> Dict[str, Any]:
    """Remove a recipient by phone from the file-backed list."""
    phone = (phone or '').strip()
    items = _load_file_recipients()
    new_items = [r for r in items if r.get('phone') != phone]
    if len(new_items) == len(items):
        return {"removed": False, "message": "Recipient not found", "recipients": items}
    _save_file_recipients(new_items)
    return {"removed": True, "recipients": new_items}


@dataclass
class TwilioConfig:
    account_sid: Optional[str]
    auth_token: Optional[str]
    from_number: Optional[str]
    dry_run: bool


def _get_twilio_config() -> TwilioConfig:
    sid = os.getenv('TWILIO_ACCOUNT_SID')
    token = os.getenv('TWILIO_AUTH_TOKEN')
    from_num = os.getenv('TWILIO_FROM')
    dry_run_env = os.getenv('TWILIO_DRY_RUN', '').lower() in ('1', 'true', 'yes')

    # If any critical fields missing, force dry-run
    dry_run = dry_run_env or not (sid and token and from_num)
    return TwilioConfig(account_sid=sid, auth_token=token, from_number=from_num, dry_run=dry_run)


def _twilio_client_or_none(cfg: TwilioConfig):
    if cfg.dry_run:
        return None
    try:
        from twilio.rest import Client  # lazy import
        return Client(cfg.account_sid, cfg.auth_token)
    except Exception:
        return None


def send_sms_to_all(message: str) -> Dict[str, Any]:
    """Send an SMS to all recipients. Returns a summary result.

    This function is resilient: if Twilio is not configured or import fails,
    it will log a dry-run action and return without raising.
    """
    recipients = list_recipients()
    cfg = _get_twilio_config()
    client = _twilio_client_or_none(cfg)

    results = []
    for r in recipients:
        phone = r.get('phone')
        name = r.get('name') or ''
        if not phone:
            continue
        try:
            if client is None:
                # Dry run: pretend to send
                results.append({
                    'phone': phone,
                    'name': name,
                    'status': 'dry-run',
                    'message': message
                })
            else:
                msg = client.messages.create(
                    to=phone,
                    from_=cfg.from_number,
                    body=message
                )
                results.append({
                    'phone': phone,
                    'name': name,
 
[truncated — 1517 more characters]
```

### mcp/src/glucose_monitor.py

```python
#!/usr/bin/env python3
"""
Background glucose monitoring utility.

Checks Dexcom glucose every `interval_minutes` and triggers an alert when
value is outside the [low_threshold, high_threshold] range.

"""

from __future__ import annotations

import os
import json
import time
import threading
from datetime import datetime
from typing import Optional, Dict, Any

from pydexcom import Dexcom
import google.generativeai as genai
import os

# Internal singleton state
_monitor_thread: Optional[threading.Thread] = None
_stop_event: Optional[threading.Event] = None
_status: Dict[str, Any] = {
    "running": False,
    "last_check": None,
    "last_value": None,
    "last_alert": None,
    "last_notification": None,
    "last_notify_ts": None,
    "last_notify_level": None,
    "low_threshold": 70,
    "high_threshold": 250,
    "interval_minutes": 10,
    "cooldown_minutes": int(os.getenv('ALERT_COOLDOWN_MINUTES', '10') or '10'),
    "webhook_url": None,
    "last_error": None,
}


def _get_ai_suggestion(glucose_value: float, alert_level: str, threshold: float) -> str:
    """Get AI-powered suggestion based on glucose context using Gemini."""
    try:
        # Configure Gemini
        genai.configure(api_key=os.getenv('GEMINI_API_KEY'))
        model = genai.GenerativeModel('gemini-2.0-flash-exp')
        
        # Create context-aware prompt
        prompt = f"""
        You are a diabetes management expert providing immediate, actionable advice for a glucose alert. You provide general advice too about being active, drinking enough water, maintiaing good sleep. 
        
        Current Situation:
        - Glucose Level: {glucose_value} mg/dL
        - Alert Type: {alert_level.upper()}
        - Threshold: {threshold} mg/dL
        - Time: {datetime.now().strftime('%Y-%m-%d %H:%M')}
        
        Provide a concise, immediate action suggestion (1-2 sentences) that includes:
        1. What to do RIGHT NOW
        2. When to recheck glucose
        3. Any warning signs to watch for
        
        Be specific, actionable, and urgent. Focus on immediate safety and next steps.
        
        Format: "IMMEDIATE ACTION: [specific action]. [When to recheck]. [Warning signs to watch]."
        """
        
        response = model.generate_content(prompt)
        return response.text.strip()
        
    except Exception as e:
        # Simple fallback without hardcoded medical advice
        return f"AI suggestion unavailable. Please consult your healthcare provider for guidance on glucose level {glucose_value} mg/dL."

def _log_alert(message: str, payload: Dict[str, Any]) -> None:
    """Log alert to file and console."""
    try:
        # Write to local log file for audit/debug
        line = f"{datetime.now().isoformat()} | {message} | {json.dumps(payload, ensure_ascii=False)}\n"
        try:
            with open(os.path.join(os.getcwd(), "alerts.log"), "a", encoding="utf-8") as f:
                f.write(line)
        except Exception:
            pass
        print(f"[GlucoseMonitor] {line}", end="")
    except Exception as e:
        print(f"[GlucoseMonitor] Failed to log alert: {e}")


def _get_current_glucose_value() -> Optional[float]:
    """Return current glucose in mg/dL using Dexcom Share via pydexcom, or None on error."""
    try:
        username = os.getenv('DEXCOM_USERNAME')
        password = os.getenv('DEXCOM_PASSWORD')
        region = os.getenv('DEXCOM_REGION', 'us')
        if not username or not password:
            _status["last_error"] = "Dexcom credentials not configured"
            return None
        dexcom = Dexcom(username=username, password=password, region=region)
        reading = dexcom.get_current_glucose_reading()
        if reading:
            return float(reading.mg_dl)
        _status["last_error"] = "No current glucose reading available"
        return None
    except Exception as e:
        _status["last_error"] = f"Dexcom error: {e}"
        return None


def _monitor_loop(low_threshold: float, high_threshold: float, interval_minutes: int):
    interval_seconds = max(60, int(interval_minutes * 60))  # safety lower bound 60s
    cooldown_minutes = int(os.getenv('ALERT_COOLDOWN_MINUTES', str(_status.get('cooldown_minutes', 10))))
    _status.update({
        "running": True,
        "low_threshold": low_threshold,
        "high_threshold": high_threshold,
        "interval_minutes": interval_minutes,
        "cooldown_minutes": cooldown_minutes,
        "webhook_url": None,
        "last_error": None,
    })

    def should_notify(level: str, now_iso: str) -> bool:
        try:
            last_level = _status.get("last_notify_level")
            last_ts = _status.get("last_notify_ts")
            if not last_ts:
                return True
            if last_level == level:
                from datetime import datetime, timedelta
                last_dt = datetime.fromisoformat(last_ts)
                now_dt = datetime.fromisoformat(now_iso)
                if now_dt - last_dt < timedelta(minutes=cooldown_minutes):
                    return False
            return True
        except Exception:
            return True

    while _stop_event and not _stop_event.is_set():
        now = datetime.now().isoformat()
        value = _get_current_glucose_value()
        _status["last_check"] = now
        _status["last_value"] = value

        if value is not None:
            if value < low_threshold:
                # Get AI-powered suggestion for low glucose
                suggestion = _get_ai_suggestion(value, "low", low_threshold)
                msg = f"🚨 GLUCOSE ALERT: LOW at {value} mg/dL (below {low_threshold})"
                payload = {
                    "level": "low",
                    "value": value,
                    "threshold": low_threshold,
                    "timestamp": now,
                    "suggestion": suggestion,
                    "ai_generated": True
                }
                _status["last_alert"] = paylo
[truncated — 4103 more characters]
```

### mcp/src/diabetes_context.py

```python
#!/usr/bin/env python3
"""
Diabetes Context Management Module
Provides context-aware tools for Poke to track and learn from diabetes patterns
"""

from datetime import datetime
from typing import Optional, Dict, Any

class DiabetesContextManager:
    """Manages diabetes-related context for Poke's memory system"""
    
    def __init__(self):
        self.context_templates = {
            "meal_log": self._create_meal_log_context,
            "glucose_response": self._create_glucose_response_context,
            "pattern_analysis": self._create_pattern_analysis_context,
            "smart_recommendations": self._create_smart_recommendations_context,
            "outcome_learning": self._create_outcome_learning_context
        }
    
    def _create_meal_log_context(self, **kwargs) -> str:
        """Create context for meal logging"""
        return f"""
MEAL LOGGED: {kwargs.get('food_description', 'Unknown food')}
- Carbs: {kwargs.get('carb_grams', 'Unknown')}g
- Insulin: {kwargs.get('insulin_dose', 'Unknown')} units
- Pre-meal glucose: {kwargs.get('pre_meal_glucose', 'Unknown')} mg/dL
- Time: {kwargs.get('timestamp', datetime.now().strftime('%Y-%m-%d %H:%M'))}
- Notes: {kwargs.get('notes', 'None')}

Please remember this meal and its details for future pattern analysis.
"""
    
    def _create_glucose_response_context(self, **kwargs) -> str:
        """Create context for glucose response tracking"""
        glucose_rise = kwargs.get('post_meal_glucose', 0) - kwargs.get('pre_meal_glucose', 0)
        return f"""
GLUCOSE RESPONSE LOGGED:
- Meal: {kwargs.get('meal_description', 'Unknown')}
- Pre-meal: {kwargs.get('pre_meal_glucose', 'Unknown')} mg/dL
- Post-meal: {kwargs.get('post_meal_glucose', 'Unknown')} mg/dL
- Rise: {glucose_rise} mg/dL
- Time elapsed: {kwargs.get('time_elapsed_minutes', 'Unknown')} minutes
- Insulin used: {kwargs.get('insulin_dose_used', 'Unknown')} units

Please remember this response pattern for future analysis.
"""
    
    def _create_pattern_analysis_context(self, **kwargs) -> str:
        """Create context for pattern analysis requests"""
        return f"""
Please analyze my meal patterns for {kwargs.get('food_type', 'all foods')} over the {kwargs.get('time_period', 'last_week')}.

Look for:
1. Which foods cause the biggest glucose spikes
2. Best insulin ratios for different foods
3. Time-of-day effects on glucose response
4. Any patterns in my eating habits

Use your memory of my previous meals to provide insights.
"""
    
    def _create_smart_recommendations_context(self, **kwargs) -> str:
        """Create context for smart recommendations"""
        return f"""
Current situation: {kwargs.get('current_situation', 'General diabetes management')}

Based on your memory of my previous meals, glucose readings, and insulin doses:
1. What would you recommend for my next meal?
2. What insulin ratio should I use?
3. Any patterns you've noticed that I should be aware of?
4. Any foods that consistently cause problems?

Please provide personalized advice based on my historical data.
"""
    
    def _create_outcome_learning_context(self, **kwargs) -> str:
        """Create context for learning from outcomes"""
        accuracy = abs(kwargs.get('predicted_glucose_rise', 0) - kwargs.get('actual_glucose_rise', 0))
        return f"""
OUTCOME LEARNING:
- Meal: {kwargs.get('meal_description', 'Unknown')}
- Predicted rise: {kwargs.get('predicted_glucose_rise', 'Unknown')} mg/dL
- Actual rise: {kwargs.get('actual_glucose_rise', 'Unknown')} mg/dL
- Accuracy: {accuracy} mg/dL difference
- Insulin ratio used: {kwargs.get('insulin_ratio_used', 'Unknown')}

Please update your understanding of my glucose responses based on this outcome.
"""

def track_meal_with_context(
    food_description: str,
    carb_grams: float,
    insulin_dose: float,
    pre_meal_glucose: float,
    notes: str = None
) -> Dict[str, Any]:
    """
    Track a meal and store context for Poke to remember patterns
    
    Args:
        food_description: Description of the food eaten
        carb_grams: Grams of carbohydrates in the meal
        insulin_dose: Insulin units taken
        pre_meal_glucose: Blood glucose before meal (mg/dL)
        notes: Additional notes about the meal
    
    Returns:
        Dictionary with tracking info and context for Poke
    """
    context_manager = DiabetesContextManager()
    timestamp = datetime.now().isoformat()
    
    context = context_manager._create_meal_log_context(
        food_description=food_description,
        carb_grams=carb_grams,
        insulin_dose=insulin_dose,
        pre_meal_glucose=pre_meal_glucose,
        notes=notes,
        timestamp=timestamp
    )
    
    return {
        "meal_logged": True,
        "context_for_poke": context,
        "meal_summary": {
            "food": food_description,
            "carbs": carb_grams,
            "insulin": insulin_dose,
            "pre_glucose": pre_meal_glucose,
            "timestamp": timestamp
        },
        "instructions": "Please remember this meal and its details for future pattern analysis."
    }

def log_glucose_response(
    meal_description: str,
    pre_meal_glucose: float,
    post_meal_glucose: float,
    time_elapsed_minutes: int,
    insulin_dose_used: float
) -> Dict[str, Any]:
    """
    Log glucose response for Poke to remember and analyze
    
    Args:
        meal_description: Description of the meal
        pre_meal_glucose: Glucose before meal (mg/dL)
        post_meal_glucose: Glucose after meal (mg/dL)
        time_elapsed_minutes: Time between measurements
        insulin_dose_used: Insulin units that were taken
    
    Returns:
        Dictionary with response data and context for Poke
    """
    context_manager = DiabetesContextManager()
    glucose_rise = post_meal_glucose - pre_meal_glucose
    timestamp = datetime.now().isoformat()
    
    context = context_manager._create_glucose_response_context(
        meal_description=meal_description,
        pre_mea
[truncated — 4780 more characters]
```