← MetricBridge

Ask your agent about your real Apple Health data

Paste one command. Claude Code, Claude Desktop, Cursor, VS Code, opencode, OpenClaw or Hermes then reads your Apple Health export through 18 tools over 194 metrics, on your own machine. Nothing to host, no account, no cloud AI in the path.

Install: one command (Claude Code)

claude mcp add health-export -- npx -y health-export-mcp

On a Mac that is the whole install: since 1.7.3 the server finds the app's iCloud Drive folder by itself. On Windows or Linux, or if your export lands somewhere else, add -e HEALTH_DATA_DIR="/path/to/your/export/folder". Needs Node.js 18 or later. Then restart the client and ask: "Use health-export: how did my HRV this week compare with last week?"

The Cursor and VS Code links install npx -y health-export-mcp with no folder set, which is right on a Mac; on Windows or Linux add HEALTH_DATA_DIR to the entry afterwards. Other clients: client config.

Last updated 28 October 2026 · health-export-mcp 1.8.0 · source on GitHub · npm: health-export-mcp

What a real answer looks like

You ask in plain language; the agent picks a tool; the tool answers with numbers that carry their own provenance: the unit, the exact date ranges, whether each window was complete, and how much history the export holds. This is the real output of get_trends on health-export-mcp 1.7.3, captured on 27 October 2026 from the built-in --demo dataset (synthetic, so it can be published; a real export answers with the same fields and without the watermark).

You: "Use health-export: how did my HRV this week compare with last week?"

Agent calls get_trends with {"metric":"heart_rate_variability","window":7} and gets:

[SYNTHETIC DEMO DATA] {"metric":"heart_rate_variability","unit":"ms","window":7,
 "recent":50.859,"prior":51.306,"change":-0.447,"changePercent":-0.871,"direction":"flat",
 "recentRange":{"from":"2026-08-12","to":"2026-08-18"},"recentDays":7,"priorDays":7,
 "windowSatisfied":true,"coverage":{"firstDate":"2025-07-15","lastDate":"2026-08-18","days":400}}

Agent: Your HRV averaged 50.9 ms over 12 to 18 August against 51.3 ms the week before, down 0.4 ms (0.9%). Both windows had all seven days, so this is flat, not a dip. The export holds 400 days, back to 15 July 2025.

Every data tool answers this way. get_mcp_status names the file it read and the latest data date; compare_periods reports pointsInRange for each period and comparable: false when one side is too thin; correlate_metrics refuses below ten aligned days and says "association, not causation" in the payload. A number without its working does not come out of this server.

On this page

What your agent can answer: the 18 tools

All sixteen are read-only and none makes a network request. Your agent picks the tool from your question; you never name one. The left column is the question, the right is what answers it.

Your questionToolWhat comes back
"Is my health data connected?"get_mcp_statusThe file it read, metric and workout counts, latest data date, a freshness summary. Agents call this first.
"Is this export current enough to trust?"get_freshnessstale against a threshold (26 hours by default), judged on the daily cache and sleep sessions, age_hours, as_of, per-file write times, and stale_copy when this computer still has an older copy of a file than the phone wrote.
"What do you have on me?"list_metricsEvery metric in the export with unit, day count and date range.
"What was my resting heart rate each day in September?"get_health_metricsDaily values for one metric (or all) over a range, plus avg/sum/min/max/latest. Long ranges roll up to weekly or monthly points with the aggregate still over every day.
"How does this week compare with last week?"get_trendsRecent N days against the prior N: change, percent change, direction, whether both windows were complete.
"Compare this January with last January" or "before and after I started the medication"compare_periodsTwo arbitrary periods, or a logged event with N days either side (the event day excluded).
"Give me HRV, RHR and sleep for the last 14 days as JSON"get_structured_exportClean JSON for chosen metrics and range, paginated with a cursor.
"What has my heart rate done today?"get_intradayYesterday and today hour by hour, written by the app's hourly automations (app 1.4 or later), with each hour's lowest and highest reading for vitals when the app writes them. Replaced each run, not a history.
Anything phrased loosely: "average HRV last month"query_health_dataRoutes a plain question to structured results. The specific tools above are cheaper and more predictable.
"When did I start the new medication / change shifts / travel?"list_eventsEvents you logged in the app, or your agent logged with add_event (medication, habit, visit, life, shift, episode, travel), filtered by type, tag or date, each marked as from the app or the agent.
"I started magnesium today, note it"add_eventLogs an event you state into health-events-agent.json, the one file the server writes, so a later export from the app never wipes it. Sealed when your export is encrypted.
"Remove that event you logged"remove_eventRemoves an event your agent logged. Events you logged in the app are edited in the app.
"What conditions or goals have I told you about?"get_profileOnly the profile fields you switched on. An absent field means withheld, never "none".
"Show my runs this month with heart rate and pace"get_workoutsWorkouts by activity and date, with heart rate, running dynamics, cycling power, intervals and whether a route exists. Paginated.
"How did I sleep last night, and was it split?"get_sleep_sessionsClustered sleep sessions attributed to the waking day, with stage totals; split nights stay split.
"Where am I in my cycle?"get_cycle_contextDay-in-cycle and a coarse phase from logged period starts only. Never predictive; only with sensitive categories on.
"Does a late workout go with worse HRV the next day?"correlate_metricsPearson r between two metrics with a 0 to 3 day lag; refuses under ten aligned days; states association, not causation.
"What do you call VO2 max, and is 180 lb in kg?"resolve_metricCanonical name and unit for any spelling, unit conversions with formulas, whether the export holds it, and (on newer exports) which device fed each metric.

The server also ships 22 MCP prompts (daily brief, weekly review, doctor visit prep, an n-of-1 experiment protocol, medication before/after, shift block comparisons and more), a --doctor diagnostics command, and status --max-age <hours> as a freshness gate for cron jobs. Prompt and tool reference with every parameter: the README.

get_mcp_status

Reports the data source, how many metrics and workouts are available, the most recent data date and a freshness summary. Since 1.7.3 the source line also says why that folder was chosen (HEALTH_DATA_DIR, the iCloud default on a Mac, or the current directory).

{ "ok": true, "source": "file /Users/you/Library/Mobile Documents/iCloud~ai~healthexport~app/Documents/.health-cache.json (default: the MetricBridge iCloud Drive folder)",
  "metricCount": 34, "workoutCount": 12, "lastDataDate": "2026-10-26",
  "freshness": { "state": "fresh", "stale": false, "age_hours": 3.2, "stale_after_hours": 26 } }

get_health_metrics

ParameterTypeNotes
metricstringe.g. step_count, or any alias resolve_metric accepts. Omit for all metrics.
start, endstringYYYY-MM-DD, both optional.
aggregationstringavg, sum, min, max or latest. Defaults to sum for cumulative metrics, average otherwise.
granularitystringauto (default), day, week or month. Auto picks the finest bucket that fits the response budget.
filterDaysobjectRestrict to days covered by logged events of a type or tag, with negate to exclude them.
ParameterTypeNotes
metricstringRequired.
windowintegerDays per window. Defaults to 7.
excludeTravelDaysbooleanDrop days on which the phone changed time zone.

get_intraday

The current hour-by-hour window written by the iOS app's hourly automations (app 1.4 or later) to health-intraday.json, beside the daily cache. The file is replaced on every hourly run (a live within-day view, not an accumulating history), so day-level questions still belong to get_health_metrics. Optional metric filters to one metric; when no hourly automation has delivered yet it answers available: false with setup guidance instead of an error.

{ "available": true, "file": "health-intraday.json", "replacedEachRun": true,
  "metrics": [ { "name": "heart_rate", "unit": "count/min",
                 "points": [ { "t": "2026-08-17 09:00:00 +0100", "v": 71 } ],
                 "latest": { "t": "2026-08-17 09:00:00 +0100", "v": 71 } } ] }

resolve_metric

ParameterTypeNotes
namestringRequired. Any spelling, e.g. steps, StepCount, Body Weight, VO2 max. A word that names several metrics comes back with candidates, never a guess.
value, unitnumber, stringOptional. Converts the value into the canonical unit, e.g. 180 lb to kg.

Full setup, the first time

Under two minutes if the app is already exporting to iCloud Drive on a Mac: paste the command, restart the client, ask. The first time, add the app install and a few minutes for iCloud to bring the file to your Mac.

  1. Install the MetricBridge iOS app. Install the MetricBridge iOS app on your iPhone and allow read access to the Apple Health types you want to share. It has a 7-day free trial, then costs $24.99 once. Download on the App Store.
  2. Choose an export destination. In the app, choose where the export goes: iCloud Drive, a local folder, or your LAN. The app writes .health-cache.json there. On a Mac, iCloud Drive needs no further setup.
  3. Add the server to your MCP client. In Claude Code run: claude mcp add health-export -- npx -y health-export-mcp. On a Mac the server finds the app's iCloud Drive folder by itself (since 1.7.3); on Windows or Linux, or for another folder, add -e HEALTH_DATA_DIR="/path/to/your/export/folder". Claude Desktop: open health-export.mcpb instead.
  4. Check the connection. Ask your agent to call get_mcp_status. It reports the data source, the metric count and the most recent data date.
Did the file arrive? npx -y health-export-mcp --doctor prints the folder the server chose and why, each file's age and the freshness verdict. iCloud can take a few minutes after you tap Export in the app. When the trial ends and exports stop, get_freshness says so and links the unlock page; once the app is unlocked, exports resume with no change on this side.

Client configuration

Every client runs the same command, npx -y health-export-mcp, over stdio. On a Mac no environment variable is needed; elsewhere set HEALTH_DATA_DIR. Prefer a pinned, checksum-verified copy instead of npm? Download the files under verify the download and replace npx -y health-export-mcp with node /path/to/server.mjs in any block below, keeping the nine .mjs files together in one folder.

Claude Code

claude mcp add health-export -- npx -y health-export-mcp
# Windows, Linux, or an export outside iCloud Drive:
claude mcp add health-export -e HEALTH_DATA_DIR="/path/to/your/export/folder" -- npx -y health-export-mcp

Everything after -- is the command Claude Code runs. Add --scope user before the -- to make the server available in every project; the default is the current project. Check with claude mcp list. Claude Code also reads a project-scoped .mcp.json using the same mcpServers shape as Claude Desktop. If pairing is on, do not pass PAIRING_SECRET on the command line: it would land in your shell history and in ps output. Put it in the config file instead.

Claude Desktop

Easiest: open health-export.mcpb, click Install, and it asks for the export folder (and the pairing code, if you use one) itself. Desktop runs it with its own Node, so nothing goes on your PATH. Or edit claude_desktop_config.json, merge into mcpServers, then quit and reopen Claude Desktop:

{
  "mcpServers": {
    "health-export": {
      "command": "npx",
      "args": ["-y", "health-export-mcp"],
      "env": { "HEALTH_DATA_DIR": "/path/to/your/export/folder" }
    }
  }
}

Drop the env line on a Mac using iCloud Drive. If Desktop logs spawn npx ENOENT, its PATH cannot see Node (common with nvm or Homebrew): set "command" to the full path from which npx, or use the bundle.

Cursor

Cursor reads ~/.cursor/mcp.json (global) or .cursor/mcp.json (per project), using the same mcpServers block as Claude Desktop.

VS Code

VS Code reads .vscode/mcp.json in the workspace. The top key is servers, and a secret can be prompted for rather than stored:

{
  "servers": {
    "health-export": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "health-export-mcp"],
      "env": { "HEALTH_DATA_DIR": "/path/to/your/export/folder" }
    }
  }
}

opencode

Add the server to opencode.json (project) or ~/.config/opencode/opencode.json. The top key is mcp, command is an array and the env key is environment:

{
  "mcp": {
    "health-export": {
      "type": "local",
      "command": ["npx", "-y", "health-export-mcp"],
      "enabled": true,
      "environment": { "HEALTH_DATA_DIR": "/path/to/your/export/folder" }
    }
  }
}

OpenClaw, Hermes and any other MCP client

The server speaks standard MCP over stdio, so any compliant client works. Add a health-export entry with command npx, args ["-y", "health-export-mcp"] and, outside a Mac with iCloud Drive, HEALTH_DATA_DIR in its environment, in whatever shape that client's MCP config uses. Per-client blocks are kept current in AGENTS.md. Agents can also set this up for you from the setup skill.

ChatGPT, Gemini, Grok, n8n and Home Assistant do not run local MCP servers. They read the same data through the app's webhook export to an endpoint you run.

Environment variables

From health-export-mcp --help at 1.8.0. None is required on a Mac that exports to iCloud Drive.

VariablePurpose
HEALTH_DATA_DIRFolder containing .health-cache.json. When unset: on macOS, the app's iCloud Drive folder ~/Library/Mobile Documents/iCloud~ai~healthexport~app/Documents if it exists (since 1.7.3), otherwise the current directory. A leading ~ is expanded.
PAIRING_SECRETOnly if the iOS app has Agent pairing on. Must match the code shown under Settings → Agent pairing. Without it the data tools return a clear "Locked" error rather than an empty result.
HEALTH_EXPORT_PASSPHRASE, HEALTH_EXPORT_PASSPHRASE_FILEOnly if Export encryption is on in the app. The server decrypts in memory on your machine; the file form keeps the passphrase out of shell history.
HEALTH_STALE_AFTER_HOURSHours after which get_freshness reports the export as stale. Default 26.
HEALTH_DEMO=1Same as --demo: a watermarked synthetic dataset, no file read.
HEALTH_LISTEN=1, HEALTH_LISTEN_HOST, HEALTH_LISTEN_PORT, HEALTH_LISTEN_TOKENLocal-network path only: also accept pushes from the iPhone inside the MCP process (default bind 127.0.0.1:27184; the token is mandatory on any other bind).
HEALTH_MAX_RESULT_CHARSPer-answer size budget. Default 100000.

Transports (stdio only)

stdio is the only MCP transport. Every client config above uses it, and there is no hosted endpoint. The server only ever runs on your machine, reading a local file.

Verifying the download

The copy hosted here is minisign-signed and checksummed, so you can confirm you are running exactly what was published before you execute it. The signing key is also published in the GitHub repo (minisign.pub); pin it from there, not only from this site.

minisign -Vm SHA256SUMS -p minisign.pub
shasum -a 256 -c SHA256SUMS

npx -y health-export-mcp resolves the latest npm release at run time instead; npm verifies package integrity and each release carries npm provenance linking the tarball to its commit. Policy: security.

What agents can see

An agent never talks to your iPhone. It reads the files in the place you chose (iCloud Drive, a folder, or the local-network receiver), through this server on your own computer: the files the MetricBridge app writes, and any events your agent adds there. This is everything those files contain. The same list is in the app under Settings, What agents can see.

Agents can read

Reproductive health, sexual activity and alcohol are included only if you switch on sensitive categories in the app. They are off by default.

Never included

This covers the files an agent reads. A webhook, if you set one up, sends to a server you run, and the app lists every destination under Settings, What leaves this phone.

Who can read it: pairing

With pairing on (Settings, Agent pairing), this server serves your data only when PAIRING_SECRET matches the current code; otherwise every data tool answers “Locked”. The app writes only a SHA-256 hash of the code beside your data, never the code itself. Regenerating the code in the app cuts off every agent using the old one as soon as the new pairing file reaches your computer. Pairing covers the iCloud Drive and folder exports; it does not cover a copy saved by the local-network receiver. Pairing protects this server, not the files: anyone who can open the files can read them, unless you turn on export encryption in the app.

Is it private?

The server makes no network requests, has no dependencies, requires no account, and reads a local file you control, so your health data never reaches us or a cloud AI through it. Apple Health access happens only in the iOS app, which requests read-only HealthKit permission and never writes back. The export goes only to the destination you choose; what your agent then does with an answer is governed by that agent, not by this server. Full data-flow table: privacy.

Frequently asked questions

What is an Apple Health MCP server?

An Apple Health MCP server is a Model Context Protocol server that exposes your Apple Health data to AI agents as tools they can call on demand, rather than as a file you paste into a chat.

How do I install health-export-mcp in Claude Code?

Run one command: claude mcp add health-export -- npx -y health-export-mcp. On a Mac it finds the app's iCloud Drive folder by itself; on Windows or Linux add -e HEALTH_DATA_DIR="/path/to/your/export/folder". It requires Node.js 18 or later.

Do I need the iOS app?

For your own data, yes. This server reads a file and does not talk to your iPhone directly. The MetricBridge iOS app writes the JSON export, and without the app there is no export for this server to read. To try the tools first, the --demo mode serves a watermarked synthetic dataset.

How many tools and prompts does the server have?

The server has 18 tools and 22 MCP prompts. 16 only read; add_event and remove_event write one file, health-events-agent.json, beside your export. None of the tools can write to Apple Health, and none of them make network requests.

Is the MCP server free?

The MCP server is free and open source under the MIT license. The MetricBridge iOS app that writes the export is a separate purchase: a 7-day free trial, then a single $24.99 one-time unlock, with no subscription.

Does the server send my health data anywhere?

No. The server makes no network requests, has no dependencies, requires no account, and reads a local file you control. Your health data never reaches us or a cloud AI through this server.

Does it work on Windows or Linux?

Yes, anywhere Node.js 18 runs. Only the iCloud Drive default is Mac-only: on Windows or Linux set HEALTH_DATA_DIR to the folder your export syncs to.

MetricBridge · Wellness information, not medical advice. · Home · What you get · On-device AI · Readiness · Methods · MCP server · GitHub · Changelog · Privacy · Security · Support · Press · Terms · Accessibility