MCP Server Reference

MCP Tools Reference

Once you install the iOS app and sync your HealthKit data, these are the 11 MCP tools your AI can call. These tools read from the database option (your own Supabase/Postgres). The server is open source: clone the repo, drop in your database credentials, and add one config block to your AI client. The app's Connect Your AI screen has copy-paste config for Claude Desktop, Claude Code, and Cursor. Using the Google Sheet destination instead? An AI assistant with Google Drive access can read the sheet, or you can give it a CSV download; the MCP tools need the database option.

Setup

Full verified checklist (~15 min): /setup. Detail: docs/SETUP.md. Also listed on the Glama MCP registry. An npx one-liner is not published yet: clone + Python is the supported path.

1
Clone the MCP server
git clone https://github.com/jefflitt1/health4ai
cd health4ai/mcp-server
pip install -r requirements.txt
2
Configure .env
cp .env.example .env
# DATABASE_URL + HEALTHKIT_USER_ID
3
Add to your AI client
{
  "mcpServers": {
    "health4ai": {
      "command": "python",
      "args": ["/path/to/health4ai/mcp-server/main.py"],
      "env": {
        "DATABASE_URL": "postgresql://...",
        "HEALTHKIT_USER_ID": "<your auth UID>"
      }
    }
  }
}

Works with Claude Desktop, Cursor, Continue, and any MCP-compatible client. See /setup.

11 Tools

get_health_summaryOverview · key metrics

get_health_summary(days: int = 7) → {period_days, steps, hrv_sdnn_ms, resting_heart_rate_bpm, sleep, workouts, data_as_of}

Overview of key metrics across a date range. Nested objects for steps/HRV/RHR; sleep and workouts stay raw-only.

Example prompt
"What's my health summary for the last 7 days?"
Return shape
{
  "period_days": 7,
  "steps": {"total": 59024, "daily_avg": 8432, "days_with_data": 7, "unit": "count"},
  "hrv_sdnn_ms": {"avg": 52.1, "latest": 54.2, "readings": 14},
  "resting_heart_rate_bpm": {"avg": 58.0, "latest": 57.0},
  "sleep": {"total_records": 42, "stage_records": 28},
  "workouts": {"count": 4, "types": ["Running", "TraditionalStrengthTraining"]},
  "data_as_of": "2026-09-16T23:00:00+00:00"
}
get_sleepSleep stages · per night

get_sleep(days: int = 7) → {period_days, avg_sleep_hours, nights: [{date, source, stages, total_minutes, segments}]}

Per-night sleep stage breakdown (core/deep/rem minutes). One source per night by priority.

Example prompt
"How was my sleep last week?"
Return shape
{
  "period_days": 7,
  "avg_sleep_hours": 7.5,
  "nights": [{
    "date": "2026-06-17",
    "source": "Apple Watch",
    "stages": {"core": 252.0, "deep": 66.0, "rem": 108.0},
    "total_minutes": 426.0,
    "segments": [{"stage": "deep", "duration_minutes": 22.0, "...": "..."}]
  }]
}
get_hrv_trendHRV · trend delta

get_hrv_trend(days: int = 30) → {avg_hrv_ms, latest_hrv_ms, trend_vs_prior_week, daily_averages}

Daily HRV (SDNN) averages with 7-day vs prior-week delta and direction.

Example prompt
"Is my HRV improving?"
Return shape
{
  "period_days": 30,
  "days_with_data": 28,
  "avg_hrv_ms": 52.1,
  "latest_hrv_ms": 54.2,
  "trend_vs_prior_week": {"delta_ms": 3.2, "direction": "improving"},
  "unit": "ms",
  "daily_averages": [
    {"date": "2026-06-17", "avg_hrv_ms": 54.2, "source": "raw"},
    {"date": "2026-06-16", "avg_hrv_ms": 49.8, "source": "raw"}
  ]
}
get_daily_snapshotAll metrics · single date

get_daily_snapshot(date: str = "") → {date, highlights, workouts, sleep_records, all_metrics, …}

Everything recorded for a specific date (YYYY-MM-DD). Defaults to today. Highlights fall back to daily summaries past 30 days.

Example prompt
"What does my health data look like for June 15?"
Return shape
{
  "date": "2026-06-15",
  "total_records": 186,
  "truncated": false,
  "metrics_present": ["HKQuantityTypeIdentifierStepCount", "..."],
  "highlights": {
    "steps": 9241,
    "active_energy_cal": 612,
    "resting_hr_bpm": 57,
    "hrv_sdnn_ms": 51.4,
    "weight_kg": 78.2
  },
  "highlights_source": "raw",
  "workouts": [{"type": "Running", "duration_minutes": 42.0, "calories": 487}],
  "sleep_records": 12,
  "all_metrics": {"HKQuantityTypeIdentifierStepCount": [{"value": 120, "unit": "count", "at": "..."}]}
}
get_workoutsWorkout log · type & intensity

get_workouts(days: int = 30, limit: int = 20) → {total_workouts, by_type, workouts: [{date, workout_type, duration_minutes, …}]}

Workout log with type, duration, distance, and calories.

Example prompt
"How many workouts did I do this month?"
Return shape
{
  "period_days": 30,
  "total_workouts": 12,
  "total_duration_hours": 8.4,
  "by_type": {"Running": 7, "TraditionalStrengthTraining": 5},
  "workouts": [{
    "date": "2026-06-17",
    "started_at": "2026-06-17T06:30:00+00:00",
    "workout_type": "Running",
    "duration_minutes": 42.0,
    "distance_km": 6.8,
    "calories_burned": 487,
    "source": "Apple Watch"
  }]
}
query_metricRaw time series · any HKQuantityType

query_metric(metric_type: str, days: int = 7, limit: int = 200) → {granularity, count, avg, samples|daily, …}

Time series for any HKQuantityType. ≤30 days returns raw samples; longer windows return daily aggregates. Empty results may include data_status.

Example prompt
"Show me my VO2 max readings for the last 90 days"
Return shape (raw, ≤30d)
{
  "metric_type": "HKQuantityTypeIdentifierVO2Max",
  "period_days": 7,
  "granularity": "raw",
  "count": 2,
  "avg": 48.3,
  "min": 47.9,
  "max": 48.7,
  "samples": [{
    "value": 48.3,
    "unit": "mL/kg·min",
    "started_at": "2026-06-17T07:14:22+00:00",
    "ended_at": null,
    "source": "Apple Watch",
    "metadata": null
  }]
}
get_long_term_trendMonthly aggregates · multi-year

get_long_term_trend(metric_type: str, months: int = 24) → {overall_avg, monthly_trend, daily_data, …}

Multi-year monthly aggregates. Merges recent raw with historical daily summaries so the trend has no recency gap.

Example prompt
"What's my HRV trend for the last 2 years?"
Return shape
{
  "metric_type": "HKQuantityTypeIdentifierHeartRateVariabilitySDNN",
  "months_requested": 24,
  "days_with_data": 612,
  "overall_avg": 51.8,
  "overall_min": 28.4,
  "overall_max": 78.1,
  "unit": "ms",
  "monthly_trend": [{
    "month": "2026-06",
    "avg": 51.8,
    "days_with_data": 17,
    "sources": ["raw", "summary"]
  }],
  "daily_data": [{"date": "2026-06-17", "avg": 54.2, "min": 48.1, "max": 61.0, "count": 3, "source": "raw"}]
}
get_coaching_briefStructured context · AI agents

get_coaching_brief() → {data_status, recovery, sleep, training_load_30d, activity_7d, fitness_markers}

Structured coaching context for AI agents. Includes freshness status — do not cite numbers when data_status is stale/none.

Example prompt
"Give me a training readiness brief"
Return shape
{
  "generated_at": "2026-09-16T23:00:00+00:00",
  "data_status": {"status": "fresh", "hours_since_newest_sample": 3.2, "guidance": "..."},
  "recovery": {
    "hrv_latest_ms": 54.2,
    "hrv_7d_avg_ms": 52.1,
    "hrv_trend": "stable",
    "hrv_delta_vs_prior_week_ms": 1.1,
    "resting_hr_latest_bpm": 57,
    "coaching_note": "Recovery stable"
  },
  "sleep": {"avg_hours_last_7_nights": 7.3, "nights_tracked": 7, "quality_flag": "borderline"},
  "training_load_30d": {"total_workouts": 12, "total_hours": 8.4, "weekly_avg_workouts": 2.8, "by_type": {"Running": 7}},
  "activity_7d": {"avg_daily_steps": 8432, "avg_active_energy_cal": 520},
  "fitness_markers": {"vo2max_latest": 48.3, "weight_kg_latest": 78.2}
}
search_recordsThreshold filtering · worst/best days

search_records(metric_type: str, days: int = 90, min_value: float | None = None, max_value: float | None = None, limit: int = 100) → {results: [{date, value, source}], filters, …}

Find days where a metric crossed a threshold. Cumulative metrics filter on daily total; rate metrics on daily average. Results sorted highest-to-lowest.

Example prompt
"What were my worst HRV days this year?" → max_value=40
Return shape
{
  "metric_type": "HKQuantityTypeIdentifierHeartRateVariabilitySDNN",
  "period_days": 90,
  "days_searched": 87,
  "days_matched": 2,
  "filters": {"min_value": null, "max_value": 40},
  "value_type": "daily_avg",
  "unit": "ms",
  "results": [
    {"date": "2026-03-12", "value": 28.4, "source": "raw"},
    {"date": "2026-01-08", "value": 31.2, "source": "summary"}
  ]
}
get_metric_statsPersonal baseline · percentiles

get_metric_stats(metric_type: str, days: int = 90) → {mean, std_dev, percentiles, thresholds, …}

Personal baseline and percentiles. thresholds.good_day_above = p75; poor_day_below = p25. Answers "is 42ms HRV good for me?"

Example prompt
"Is my HRV today above or below my normal range?"
Return shape
{
  "metric_type": "HKQuantityTypeIdentifierHeartRateVariabilitySDNN",
  "period_days": 90,
  "data_points": 84,
  "value_type": "daily_avg",
  "unit": "ms",
  "min": 28.4,
  "max": 78.1,
  "mean": 52.1,
  "std_dev": 9.3,
  "percentiles": {"p10": 38.2, "p25": 44.0, "p50": 51.4, "p75": 59.1, "p90": 67.8},
  "thresholds": {"good_day_above": 59.1, "poor_day_below": 44.0}
}
compare_periodsBefore/after · with verdict

compare_periods(metric_type: str, period_a_start: str, period_a_end: str, period_b_start: str, period_b_end: str, label_a: str = "Period A", label_b: str = "Period B") → {label_a, label_b, comparison}

Compare two YYYY-MM-DD ranges. Period objects are keyed by label_a / label_b. Answers "did my sleep improve after I started lifting?"

Example prompt
"Compare my sleep before and after I started taking magnesium"
Return shape
{
  "metric_type": "HKCategoryTypeIdentifierSleepAnalysis",
  "value_type": "daily_avg",
  "before": {
    "start": "2026-04-01", "end": "2026-04-14",
    "data_points": 14, "avg": 6.8, "min": 5.1, "max": 8.2, "unit": "min"
  },
  "after": {
    "start": "2026-04-15", "end": "2026-04-28",
    "data_points": 14, "avg": 7.4, "min": 6.0, "max": 8.5, "unit": "min"
  },
  "comparison": {
    "delta": 0.6,
    "pct_change": 8.8,
    "verdict": "after is higher than before"
  }
}

HKQuantityType Identifiers

Pass these strings as metric_type toquery_metric or get_long_term_trend.

IdentifierMetric
HKQuantityTypeIdentifierHeartRateVariabilitySDNNHRV
HKQuantityTypeIdentifierRestingHeartRateResting HR
HKQuantityTypeIdentifierVO2MaxVO2 max
HKQuantityTypeIdentifierStepCountSteps
HKQuantityTypeIdentifierActiveEnergyBurnedActive calories
HKQuantityTypeIdentifierBodyMassWeight
HKQuantityTypeIdentifierOxygenSaturationBlood oxygen
On the App Store

Connect your Apple Health data to Claude

Free, on the App Store now. Start with a Google Sheet, or bring your own database.

Download on the App Store