MCP Tools Reference
Once you install the iOS app and sync your HealthKit data, these are the 11 MCP tools your AI can call. The server is open source — clone the repo, drop in your Supabase credentials, and add one config block to your AI client.
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.
git clone https://github.com/jefflitt1/health4ai
cd health4ai/mcp-server
pip install -r requirements.txtcp .env.example .env
# DATABASE_URL + HEALTHKIT_USER_ID{
"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 metricsget_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.
{
"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 nightget_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.
{
"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 deltaget_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.
{
"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 dateget_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.
{
"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 & intensityget_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.
{
"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 HKQuantityTypequery_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.
{
"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-yearget_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.
{
"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 agentsget_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.
{
"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 dayssearch_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.
{
"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 · percentilesget_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?"
{
"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 verdictcompare_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?"
{
"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.
| Identifier | Metric |
|---|---|
| HKQuantityTypeIdentifierHeartRateVariabilitySDNN | HRV |
| HKQuantityTypeIdentifierRestingHeartRate | Resting HR |
| HKQuantityTypeIdentifierVO2Max | VO2 max |
| HKQuantityTypeIdentifierStepCount | Steps |
| HKQuantityTypeIdentifierActiveEnergyBurned | Active calories |
| HKQuantityTypeIdentifierBodyMass | Weight |
| HKQuantityTypeIdentifierOxygenSaturation | Blood oxygen |
Connect your Apple Health data to Claude
Invite-only TestFlight — join the waitlist and request a beta invite. No public TestFlight link.
Join the waitlist