Skip to content

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 exports
Available now · Health.md for Mac

The bundled server exposes 21 fixed tools. It does not read HealthKit, export folders, security-scoped bookmarks, or arbitrary files itself.

Preview · portable direct MCP

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.

  • 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.

  • 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.

Add the bundled helper to ~/.codex/config.toml:

[mcp_servers.healthmd]
command = "/Applications/Health.md.app/Contents/Helpers/healthmd-mcp"
args = []
startup_timeout_sec = 10
tool_timeout_sec = 1200
default_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.

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.

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.

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/list and resources/read methods.
  • _meta.ui.resourceUri on analysis and export-receipt tools.
  • validated structuredContent alongside 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.

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.

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
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
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

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.

Terminal window
healthmd mcp schema healthmd_sleep_sessions
healthmd mcp schema healthmd_metric_chart
healthmd mcp schema # complete fixed catalog

A 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.

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.

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:

  • status and durable state.
  • 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:

Terminal window
healthmd extract --metric workouts --last 30 --detail lossless --output workouts.json
healthmd export --iphone --all --raw --output health-corpus.json

MCP analysis remains a derived factual view. Generated-file exports continue to use the public healthmd.health_data contract through the production exporters.

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_cursor or 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.

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.

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