Healthfolder

io.github.CloudCorpRecordsPublished by GitHub account CloudCorpRecordsv0.1.0Updated Nov 5, 2026

Read a Health Access folder of Apple Watch workouts and vitals; write training plans back as files.

VerifiedSTDIODesktop onlyLocation & LifestyleFiles & Storage

Overview

AI-generated overview

Reads a local Health Access folder of Apple Watch workouts, vitals and ECGs, and writes training plans and effort ratings back as files.

What you can do
  • List and open workouts, with summary lines, parts text, zones and cardiac cost
  • Read vitals over recent days and weekly training summaries
  • Read day files for a date range, the catalog, the profile and ECG summaries
  • Store the athlete's effort rating on a workout
  • Validate and push a training plan into the folder, then check its status and list plans
When to use it
Useful when an athlete already exports Apple Health data into a Health Access folder and wants an assistant to review workouts, vitals and training load, or to draft and file training plans for the Watch app.
Requirements
Runs locally over stdio via npx or Docker; no account, network or API key. The server must locate the Health Access folder through --dir, the HEALTHACCESS_DIR (or TIDE_DIR) environment variable, a config.toml entry, or automatic discovery of cloud-drive and Documents locations. Docker needs the folder mounted and --dir passed.
Before you install
It reads personal health data (workouts, heart rate, sleep, body mass, blood pressure, profile) from the folder, so point it only at a folder you mean to expose to the assistant. rate_workout and push_plan write files into that folder; an existing Apple effort rating is refused unless override is true. The server also writes a presence file under mcp/clients with client name, machine name and last tool name.

Installation

In SourceWeft

  1. Open Healthfolder in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

healthfolder

Read a Health Access folder of Apple Watch workouts and vitals, and write training plans back into it — as plain files. The folder an app writes from Apple Health (workouts, day files, an index, a profile) is the whole API: this package is a local stdio MCP server plus a CLI over that folder. No account, no network, nothing leaves the machine.

How the folder is found

First hit wins:

  1. --dir <folder> on the command line
  2. the HEALTHACCESS_DIR environment variable (alias TIDE_DIR)
  3. dir = "..." in ~/.config/healthaccess/config.toml (the path can be overridden with HEALTHACCESS_CONFIG; zone bounds can also be set there as zones = [133, 146, 158, 169])
  4. discovery: iCloud Drive, then ~/Library/CloudStorage/*, ~/Dropbox, ~/Google Drive, ~/OneDrive*, ~/Box, then ~/Documents. A Health Access folder holds an index.json of schema healthaccess.index.v1 and a workouts/ directory. If discovery finds several, the server refuses to guess and lists them.

Run healthfolder --check to print the resolved folder, where it came from, and the zone bounds in effect.

CLI

sh
npx -y @reneturcios/healthfolder --checknpx -y @reneturcios/healthfolder list --sport swim --limit 5npx -y @reneturcios/healthfolder show 7A1C3E90npx -y @reneturcios/healthfolder vitals --days 14npx -y @reneturcios/healthfolder summary --weeks 4npx -y @reneturcios/healthfolder rate 7A1C3E90 7 "legs heavy, breathing fine"npx -y @reneturcios/healthfolder plan push ./s30.jsonnpx -y @reneturcios/healthfolder plan status 2026-10-24T20:22:05Z-s30npx -y @reneturcios/healthfolder plan listnpx -y @reneturcios/healthfolder day 2026-05-14npx -y @reneturcios/healthfolder days --from 2026-05-01 --to 2026-05-14 --groups heart,sleepnpx -y @reneturcios/healthfolder catalognpx -y @reneturcios/healthfolder profilenpx -y @reneturcios/healthfolder ecgs

Every command prints pretty JSON. Exit codes: 0 success, 1 domain or IO error, 2 usage error. --dir works on every subcommand.

MCP server

sh
npx -y @reneturcios/healthfolder mcp

MCP client config:

json
{  "mcpServers": {    "healthfolder": {      "command": "npx",      "args": ["-y", "@reneturcios/healthfolder", "mcp"]    }  }}

Add "--dir", "<absolute path>" to args to skip the folder search.

Tools (13)

ToolWhat it does
list_workoutsWorkouts from the index (deduplicated, newest first), one summary line each
get_workoutOne workout in full: document, summary, parts text, zones, cardiac cost
get_vitalsResting HR, HRV, body mass, sleep, steps, VO2max, blood pressure over the last N days
training_summaryOne entry per ISO week: volume, zones, effort, cardiac cost, rings from day files
rate_workoutStore the athlete's own effort rating (1–10) in the workout file
push_planValidate a training plan and write plans/<id>.json for the app to put on the Watch
get_plan_statusA plan's state: pending, scheduled, failed or cancelled
list_plansEvery plan with its state and planned distance/time
get_dayOne day file with every Health group it holds
get_daysDay files in a range (max 366 days), optionally reduced to named groups
get_catalogcatalog.json plus the export-coverage check
get_profileprofile.json as written
list_ecgsEvery ECG summary in ecg/, newest first

All results are pretty-printed JSON text with floats rounded to one decimal. Malformed arguments are JSON-RPC InvalidParams errors; domain problems (unknown id, failed validation, a refusal) come back as isError results with the reason in plain words.

Two safety rules are built in:

  • rate_workout only ever stores a number the athlete said. A workout that already carries Apple's own rating (effort_source: "apple") is refused unless the call passes override: true — the refusal names the file, the existing rating, and the remedy, and nothing is written.
  • push_plan reports every validation violation in one message (sport, name length, block/step shape, goal type and value, zone, label length), so a plan can be fixed in one pass.

Resources: healthaccess://index (the deduplicated index) and the template healthaccess://workout/{id} (one workout, heart-rate series included). MCP prompts are not implemented in this build.

Derived numbers

  • Zones. Four bounds, five zones. Bounds come from config.toml, else are estimated from the age in profile.json: max HR = 208 − 0.7 × age, bounds at 72/79/86/92 % of it (age 34 → [133, 146, 158, 169]). Zone seconds are computed from the heart-rate series: each sample's time until the next sample goes to that sample's zone, only time inside the workout counts, gaps over 60 s count as 60 s. With no bounds known, a file's own legacy zones are shown, marked bounds_source: "file".
  • Cardiac cost (swims only) = avg HR × best freestyle 100 m pace (s) / 60 = heart beats per 100 m; lower is better. The best 100 is the fastest work step of at least 95 m whose overlapping laps were at least half freestyle, normalised to 100 m; if no step qualifies and the swim is at least 100 m, the whole-workout pace is used.
  • Summary lines look like: 2026-05-14 Pool swim "S12" · 1200 m · 36:06 · avg HR 129 (max 162) · Z1–2 93% · effort 6/10 (apple) · best FR 100 2:12 → 284 beats/100 m — each segment appears only when its data exists.

Presence handshake

On initialize, and after tool calls at most once a minute, the server writes mcp/clients/<id>.json in the folder so the app can show "Connected". The id is the FNV-1a 64 hash of machine name + client name; the file carries the client name/version from the initialize request, the machine name (HEALTHACCESS_MACHINE overrides it), call counts carried over between writes, and the last tool name — never arguments or results. A failed write never fails a tool call. The CLI writes the same file, as client healthfolder-cli, only from the commands that write into the folder anyway (rate, plan push).

Docker

sh
docker run -i ghcr.io/cloudcorprecords/healthfolder            # stdio MCP serverdocker run --rm ghcr.io/cloudcorprecords/healthfolder list --dir /data

Mount the Health Access folder into the container and pass --dir (or set HEALTHACCESS_DIR) so the server can find it.

Development

sh
npm installnpm run build   # tsc -> dist/npm test        # tsx --test test/*.test.ts (synthetic folders, no network)npm run dev     # run the CLI from source

License

MIT — Copyright (c) 2026 Rene Turcios.

Source: README.md at commit cf06900

Tools

13

list_workouts

List workouts from the Health Access folder, newest first, with a one-line summary each. Read-only.

Parameterslimitsincesport

get_workout

Open one workout in full: the workout document plus summary, parts text and cardiac cost. Read-only.

Parametersidrequiredinclude_lapsinclude_hr_series

get_vitals

The seven-metric vitals view (resting HR, HRV, body mass, sleep, steps, VO2max, blood pressure) of the last N days, oldest first, with latest values and averages. Read-only.

Parametersdays

training_summary

Training summary: one entry per ISO week ending in the current week, empty weeks included. Read-only.

Parametersweeks

rate_workout

Store the athlete's own effort rating (1 to 10) and optional feel note in a workout file. Call only with a number the athlete said; an existing Apple rating is refused unless override is true.

Parametersidrequiredfeeleffortrequiredoverride

push_plan

Validate a healthaccess.plan.v1 training plan and write it into the folder's plans/ directory for the app to put on the Watch. Every validation violation is reported in one message.

Parametersplanrequired

get_plan_status

Read a plan's status as the app recorded it: pending, scheduled, failed or cancelled. Read-only.

Parametersidrequired

list_plans

List every plan in the folder's plans/ directory with its state, planned distance and time, newest first. Read-only.

Takes no parameters.

get_day

Read one day file (days/<date>.json) with every Health group it holds. Read-only.

Parametersdaterequired

get_days

Read the day files in a date range (at most 366 days), oldest first, optionally reduced to named groups. Read-only.

Parameterstorequiredfromrequiredgroups

get_catalog

Read catalog.json (which Health types have data and where they were exported) plus the export-coverage check. Read-only.

Takes no parameters.

get_profile

Read profile.json: age, birth year, sex, blood type and the app's other profile fields. Read-only.

Takes no parameters.

list_ecgs

List every ECG file in the folder's ecg/ directory, newest first. Read-only.

Takes no parameters.

Version history

1
  1. v0.1.0LatestNov 5, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts