Health.md MCP server and App
Health.md for Mac ships a signed healthmd-mcp stdio helper. Codex, Claude, and other MCP hosts can use it to query factual Apple Health data. They can also render visualizations, refresh encrypted local context, and run approved durable exports through the open Mac app.
Codex / Claude / another local MCP host <-> MCP JSON-RPC over stdio <-> signed healthmd-mcp helper <-> Health.md Mac loopback API on 127.0.0.1:17645 <-> connected iPhone for fresh HealthKit reads and exportsThe bundled server exposes 21 fixed tools. It does not read HealthKit, export folders, security-scoped bookmarks, or arbitrary files itself.
The separate 19-tool healthmd mcp serve topology for macOS, Linux, and Windows is publicly packaged as an explicitly unqualified preview. Its cloud-free serve-read-only entry exposes only the 13 readiness/query tools after local pairing. Install on macOS or Linux with brew install CodyBontecou/tap/healthmd.
Bundled Mac requirements
Section titled “Bundled Mac requirements”- Health.md for Mac installed and open.
- Health.md open on the connected iPhone when the refresh tool or an export starts fresh HealthKit work.
- A local MCP host with stdio support.
- The signed helper path shown under Health.md for Mac → CLI.
The normal helper path is /Applications/Health.md.app/Contents/Helpers/healthmd-mcp. Supported core MCP protocol versions are 2024-11-05, 2025-03-26, 2025-06-18, and 2025-11-25. Do not launch healthmd-mcp as an ordinary interactive command. The MCP host owns stdin and the process lifecycle.
Portable direct requirements
Section titled “Portable direct requirements”- Install the standalone preview on macOS, Linux, or Windows. The Mac app and its loopback service are not required.
- Pair once with a query-capable iPhone and keep Health.md foreground for each new typed request. Android typed MCP is not supported.
- Use Manual IP or Tailscale reachability and native credential storage. Linux requires an unlocked Secret Service provider.
- Configure the installed compatibility launcher or the same-binary stdio server. Both use the paired direct connection.
Codex setup
Section titled “Codex setup”Add the bundled helper to ~/.codex/config.toml:
[mcp_servers.healthmd]command = "/Applications/Health.md.app/Contents/Helpers/healthmd-mcp"args = []startup_timeout_sec = 10tool_timeout_sec = 1200default_tools_approval_mode = "prompt"
[mcp_servers.healthmd.tools.healthmd_export_files]approval_mode = "prompt"
[mcp_servers.healthmd.tools.healthmd_export_job_resume]approval_mode = "prompt"
[mcp_servers.healthmd.tools.healthmd_export_job_cancel]approval_mode = "prompt"Restart Codex. Call healthmd_doctor, then list metrics with healthmd_metrics. Use the refresh tool to acquire a small, exact scope. Then query that scope with healthmd_metric_chart. Hosts without interactive MCP Apps still receive exact JSON and a standard PNG chart.
Claude setup
Section titled “Claude setup”Use this local stdio entry in Claude Desktop’s MCP configuration or a trusted Claude Code .mcp.json:
{ "mcpServers": { "healthmd": { "command": "/Applications/Health.md.app/Contents/Helpers/healthmd-mcp", "args": [] } }}Restart Claude Desktop after editing its configuration. Claude project configurations require workspace trust and explicit server approval.
Claude Desktop versions that advertise the stable MCP Apps extension render Health.md’s interactive view inline. Claude Code and other text-first clients preserve the JSON and image fallbacks.
Portable direct MCP preview
Section titled “Portable direct MCP preview”In the public standalone preview, healthmd setup codex pairs a foreground iPhone and safely creates a same-binary healthmd mcp serve entry. That topology uses authenticated encrypted Manual IP or Tailscale transport on port 17647, native credential storage, and explicit per-request iPhone reads. Linux additionally requires an unlocked Secret Service provider. Windows uses Credential Manager.
Use the exact healthmd-cli/v<version> prerelease rather than the repository-wide latest-release pointer. See Direct phone CLI for the explicitly unqualified pairing and transport contract.
Native MCP App visualizations
Section titled “Native MCP App visualizations”Health.md implements stable io.modelcontextprotocol/ui negotiation with text/html;profile=mcp-app.
After a host advertises that MIME type, the server exposes:
ui://healthmd/query-visualization-v1.- standard
resources/listandresources/readmethods. _meta.ui.resourceUrion analysis and export-receipt tools.- validated
structuredContentalongside exact JSON text.
The view is a self-contained HTML5 resource with no network, remote scripts, remote fonts, storage, or nested frames. Its declared CSP contains empty connect/resource/frame/base domain lists. It follows the standard initialize, tool-result, theme, resize, cancellation, and teardown lifecycle.
It can render:
- metric line charts with units and explicit missing-data gaps.
- period comparisons with caller-selected aggregation.
- sleep sessions and stage-duration summaries.
- workouts and factual workout/sleep timing.
- coverage, missing intervals, evidence, and limitations.
- all-pages traversal receipts.
- durable export progress, destinations, and job receipts.
If the host does not support MCP Apps, the tools still work. healthmd_metric_chart adds image/png content for image-capable hosts while preserving complete JSON as text.
Available tools
Section titled “Available tools”The bundled Mac server exposes 21 fixed tools. It has 13 readiness/query tools, four generated-file job tools, and four encrypted-context refresh job tools. The portable preview has 19 tools. It keeps the 13 readiness/query tools and four export tools. It replaces Mac refresh jobs with two direct-pairing tools. It runs typed queries directly on the foreground iPhone.
Readiness and discovery
Section titled “Readiness and discovery”| Tool | Purpose |
|---|---|
healthmd_status |
Check Mac app, context, iPhone, and export readiness |
healthmd_doctor |
Diagnose the bundled helper and Mac loopback topology |
healthmd_capabilities |
List direct query, evidence, export, schema, and paging capabilities |
healthmd_metrics |
List canonical metric IDs, categories, units, and requirements |
Analysis and visualization
Section titled “Analysis and visualization”| Tool | Purpose |
|---|---|
healthmd_metric_chart |
Query metric series and render native charts with coverage and units |
healthmd_sleep_sessions |
List and visualize stable sleep sessions and physiology coverage |
healthmd_training_alignment |
Show factual workout timing against preceding/following sleep |
healthmd_workouts |
List and visualize workouts |
healthmd_coverage |
Inspect metric/date coverage and missingness |
healthmd_compare_periods |
Compare exact periods with explicit aggregation semantics |
healthmd_training_evidence |
Create a factual training evidence packet |
healthmd_query |
Send an exact healthmd.query_request and optionally traverse pages |
healthmd_evidence_packet |
Send an exact evidence request and optionally traverse pages |
Generated-file exports
Section titled “Generated-file exports”| Tool | Purpose |
|---|---|
healthmd_export_files |
Run a durable generated-file export; bundled Mac uses its selected folder, while portable direct MCP requires an explicit computer destination |
healthmd_export_job_status |
Inspect export progress and destination receipt |
healthmd_export_job_resume |
Resume the exact immutable durable export job |
healthmd_export_job_cancel |
Explicitly cancel the export job |
The export, resume, and cancel tools are marked as potentially destructive writes. Current Claude hosts require explicit interaction for these tools. Configured export modes can update or overwrite generated files. The Codex configuration above prompts for these tools as an additional safeguard.
Encrypted-context acquisition jobs · bundled Mac only
Section titled “Encrypted-context acquisition jobs · bundled Mac only”| Tool | Purpose |
|---|---|
healthmd_refresh |
Acquire an approved scope from iPhone into disposable encrypted Mac context |
healthmd_job_status |
Inspect refresh progress without reading health values |
healthmd_job_resume |
Resume the exact accepted refresh job |
healthmd_job_cancel |
Explicitly cancel an accepted refresh job |
Discover the complete query shape
Section titled “Discover the complete query shape”MCP tools/list includes complete nested JSON Schema for dates, metrics, sources, paging, period
ranges, aggregations, and the advanced healthmd.query_request. Typed tools also include concrete
examples. An agent should call the matching typed tool directly rather than inspect generic shell
help. In particular, sleep questions use healthmd_sleep_sessions. healthmd extract produces a
different canonical source-data projection.
The portable preview can inspect the same schema locally without opening a network listener or contacting iPhone. For the released Mac helper, use MCP tools/list.
healthmd mcp schema healthmd_sleep_sessionshealthmd mcp schema healthmd_metric_charthealthmd mcp schema # complete fixed catalogA minimal sleep call has this shape (resolve the inclusive dates for the actual request):
{ "dates": { "type": "exact", "range": { "start_date": "2026-07-22", "end_date": "2026-07-28" } }, "all_pages": true}Canonical sleep metrics and lossless session detail are supplied automatically by
healthmd_sleep_sessions.
Analyze and chart data
Section titled “Analyze and chart data”Call healthmd_doctor first and resolve metric IDs with healthmd_metrics. On the released Mac topology, typed query tools read the encrypted Mac context. They do not implicitly contact iPhone. For current data, call the refresh tool with explicit dates, metrics, and sources, wait for its durable job to complete, then chart the same scope:
{ "dates": { "type": "exact", "range": { "start_date": "2026-07-01", "end_date": "2026-07-14" } }, "metrics": { "type": "explicit", "metric_ids": ["steps", "resting_heart_rate"] }, "sources": { "type": "all_available" }, "detail_level": "summary", "all_pages": true}Pass that object to healthmd_metric_chart. The interactive view uses unit-safe small multiples. A missing or partial point breaks the line rather than becoming zero.
The released Mac typed tools evaluate encrypted local context and return bounded pages with coverage, missingness, evidence, and limitations. Only explicit refresh contacts the connected foreground iPhone and replaces the requested context scope. The portable preview instead evaluates each typed request directly on its paired foreground iPhone.
Run a generated-file export
Section titled “Run a generated-file export”Select and retain a writable destination folder in Health.md for Mac first. After the host shows the full arguments and the user approves, call healthmd_export_files:
{ "date_selection": "explicit_range", "date_range": { "start": "2026-07-01", "end": "2026-07-07" }, "settings_policy": "requested_dates_only", "categories": ["Sleep"], "detail_level": "summary", "wait_timeout_seconds": 300}Use date_selection: "all_available" without date_range for complete history. Optional metric_ids, categories, or all_metrics narrow iPhone acquisition without changing saved settings. detail_level applies only when one of those selections is present. all_metrics cannot be combined with explicit metric/category lists.
To run a saved export profile instead, set settings_policy to "profile" and pass profile_reference with the profile’s stable UUID. The optional name is display and error context in the public protocol. Current phone implementations may consult it after an ID miss, but that behavior is not rename-safe. Automation must treat the UUID as the stable identity:
{ "date_selection": "explicit_range", "date_range": { "start": "2026-07-01", "end": "2026-07-07" }, "settings_policy": "profile", "profile_reference": { "profileID": "11111111-2222-4333-8444-555555555555" }}The profile owns the settings scope. Do not combine profile_reference with metric_ids, categories, all_metrics, or the saved-settings policy. An unresolved reference returns a typed error. It does not fall back to live settings.
The examples above use the bundled Mac destination. With portable direct MCP, every generated-file request also requires an existing absolute computer folder in destination. The phone profile supplies output settings, not that host path:
{ "date_selection": "explicit_range", "date_range": { "start": "2026-07-01", "end": "2026-07-07" }, "settings_policy": "profile", "profile_reference": { "profileID": "11111111-2222-4333-8444-555555555555" }, "destination": "/absolute/existing/HealthVault", "wait_timeout_seconds": 300}Portable direct rejects a missing, relative, nonexistent, or symlink destination before starting the phone job.
Inspect:
statusand durablestate.job_id.- processed/total days and progress.
- files or Daily Notes written.
- validated desktop destination.
- committed partitions and bytes.
- pause/failure reason and expiry.
A timeout or closed MCP waiter does not cancel the durable job. Check healthmd_export_job_status before resuming after an unknown outcome. Only explicit cancel terminates the job.
Raw and canonical source transport can contain gigabytes of routes, clinical text, attachments, and source records. Health.md deliberately does not put those bodies into an MCP conversation. Use the validated streaming CLI for source-shaped output:
healthmd extract --metric workouts --last 30 --detail lossless --output workouts.jsonhealthmd export --iphone --all --raw --output health-corpus.jsonMCP analysis remains a derived factual view. Generated-file exports continue to use the public healthmd.health_data contract through the production exporters.
Paging and completeness
Section titled “Paging and completeness”Query/evidence tools expose all_pages: true where supported. The helper follows opaque cursors with cycle detection and aggregate byte/page ceilings, preserving each versioned response under healthmd.mcp_query_pages v1. If an automatic-traversal ceiling is reached, the successful partial wrapper sets receipt.traversal_complete to false and returns the exact receipt.next_cursor for lossless continuation. iPhone retains a paged compact snapshot for ten minutes of foreground inactivity and clears it on terminal traversal or backgrounding. One request has a 366,000-day and 64 MiB encoded compact-context guard. query_scope_too_large means partition dates or metric IDs across calls, not that the logical history is unavailable. Pages bound missing-interval and source-descriptor lists with explicit count/truncation fields and limitations.
Transport success is not completeness. Always inspect:
- requested-scope and corpus status.
- coverage and missing intervals.
- limitations and evidence.
next_cursoror traversal receipt.- unrelated skips.
- source schema and version.
The MCP App displays these fields instead of hiding them. If automatic traversal reaches its safety ceiling, narrow the scope or continue manually.
Security and privacy boundaries
Section titled “Security and privacy boundaries”The helper has no prompts, roots, sampling, shell, SQL, arbitrary file reads, arbitrary URL fetches, HealthKit writes, loopback HTTP service, or remote MCP endpoint. Its only MCP resource is the bundled App document. Generated-file writes are one fixed approval-gated operation. The released Mac helper uses the folder selected in Health.md for Mac. The portable preview requires an explicit existing destination that it validates and durably binds before transfer.
Direct trust is stored in Keychain, Secret Service, or Windows Credential Manager. Pairing uses the existing authenticated encrypted protocol. The iPhone must be foreground and explicitly connected to the computer’s LAN or Tailscale address. Query pages are bounded to the negotiated byte/item limits, and automatic all-pages aggregation has additional byte/page ceilings. Unbounded raw bodies stay on the validated streaming CLI path.
Health.md reports factual observations with units, provenance, coverage, and missingness. It does not diagnose, recommend treatment, infer causation, or call a direction better or worse.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Action |
|---|---|
| Host cannot start the helper | Use the absolute installed healthmd or .exe path with arguments mcp serve |
| Helper waits when run in Terminal | Expected; an MCP host must send JSON-RPC on stdin |
healthmd_not_paired |
Run healthmd direct pair and finish pairing on iPhone |
healthmd_unavailable |
Unlock and foreground Health.md on iPhone, enable Direct CLI Access, and connect to the computer |
query_scope_too_large |
Partition dates or metric IDs across calls; the logical corpus remains available across requests |
| No interactive chart | Update the host; the server still returns exact JSON and a PNG metric-chart fallback |
| Export destination unavailable | Mac: reselect the saved folder in Health.md. Portable preview: create and pass an existing absolute non-symlink desktop directory. |
| Export waiter times out | Inspect the durable export job by ID before resuming |
Result has next_cursor |
Set all_pages: true or continue the cursor manually |