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.
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
Free, on the App Store now. Start with a Google Sheet, or bring your own database.
Download on the App Store