Content
# Apple Watch Health MCP
Expose user-authorized Apple Health / Apple Watch data through a self-hosted Cloudflare Worker as a remote MCP tool, allowing ChatGPT, Codex, or other MCP clients to read the latest data and limited history.
> This project connects user-authorized Apple Health data to an AI assistant through a self-hosted MCP relay.
This is an experimental project that can be self-deployed, not a medical device, and does not provide diagnostic or treatment advice.
## What It Can Do
- iPhone reads data from HealthKit, including heart rate, resting heart rate, HRV, blood oxygen, respiratory rate, steps, distance, active energy, noise exposure, and sleep.
- Apple Watch obtains real-time heart rate samples through `HKWorkoutSession` after the user actively enables real-time mode.
- Sleep saves recent 7 days' stage segments (in bed, awake, core, deep sleep, REM, etc.), and other metrics save the last 3 samples each.
- Cloudflare Worker automatically removes duplicates and trims history, returning data, freshness, and retention range through four MCP tools.
- Two independent random tokens protect the upload interface and MCP address.
- Users can call the delete interface at any time to clear health snapshots on the server.
## Important Limitations
- MCP **cannot remotely start Apple Watch sensors**. Real-time heart rate must be started by the user on the watch by opening the app and tapping "Start".
- `watch_measure_now` can only wait for the next new heart rate sample after real-time mode is running.
- Metrics like blood oxygen, noise, and sleep can only read existing records in HealthKit and cannot be forced to measure immediately by third-party apps.
- HealthKit background updates are scheduled by the system and do not guarantee zero latency. Device model, region, system version, and user authorization affect available metrics.
- Retention windows are intentionally kept short: 7 days for sleep, 3 samples for other metrics. This project is not a long-term health archive or medical database.
## Architecture
```mermaid
flowchart LR
W[Apple Watch App] -->|Real-time Heart Rate HTTPS| C[Cloudflare Worker]
I[iPhone HealthKit App] -->|Limited Health History HTTPS| C
C --> D[(Durable Object\nSleep 7 Days / Other 3 Samples)]
A[ChatGPT / MCP Client] -->|Remote MCP| C
```
## Directory
- `ios/`: SwiftUI iPhone App, watchOS App, and Xcode project.
- `cloudflare/`: Worker, Durable Object, MCP interface, and automated testing.
- `PRIVACY.md`: Data flow, risks, and deletion methods.
- `SECURITY.md`: Key management and vulnerability reporting suggestions.
## 1. Deploy Cloudflare Worker
Requires Node.js 20+, Cloudflare account, and Wrangler.
```bash
cd cloudflare
npm install
npx wrangler login
```
Generate two different random tokens and temporarily save them in a password manager:
```bash
openssl rand -hex 32
openssl rand -hex 32
```
Write them to Worker Secret:
```bash
npx wrangler secret put UPLOAD_TOKEN
npx wrangler secret put MCP_PATH_TOKEN
npm run deploy
```
Note the Worker address after deployment, e.g.:
```text
https://watch-health-mcp.<your-subdomain>.workers.dev
```
## 2. Configure and Install Apple App
Copy the example configuration to two targets. `RelayConfig.plist` is added to `.gitignore`, do not commit it.
```bash
cp ios/Configuration/RelayConfig.example.plist ios/WatchHealthTest/RelayConfig.plist
cp ios/Configuration/RelayConfig.example.plist "ios/WatchHealthLive Watch App/RelayConfig.plist"
```
Fill in both files:
- `BaseURL`: The Worker address obtained in the previous step, without a trailing `/`.
- `UploadToken`: Write the `UPLOAD_TOKEN` to Cloudflare.
Then:
1. Open `ios/WatchHealthTest.xcodeproj` with Xcode.
2. Select your team in Signing & Capabilities for both iPhone and Watch targets.
3. If the Bundle Identifier conflicts, change `com.example.AppleWatchHealthMCP` to your unique identifier and keep the Watch App's Companion App Identifier consistent.
4. Confirm that both targets have HealthKit enabled.
5. Run the iPhone App and authorize it, then install `WatchHealthLive` from the Watch App installation list.
Without a private configuration file, the App can still read and display HealthKit data locally but will not upload.
## 3. Connect MCP Client
The remote MCP address is:
```text
https://watch-health-mcp.<your-subdomain>.workers.dev/mcp/<MCP_PATH_TOKEN>
```
Add the complete address to clients that support remote MCP. This URL itself is a credential for accessing health data, and it is prohibited to take screenshots, share, or submit it to GitHub.
Available tools:
- `watch_health_open_session`: Call first to view connection, real-time mode, and data freshness.
- `watch_get_latest_health`: Read all latest metrics, sampling time, data age, and history count.
- `watch_get_health_history`: Read complete stages of sleep for the recent 7 days or the last 3 samples of other metrics; can query a single metric through the `metric` parameter.
- `watch_measure_now`: Wait for a new heart rate sample after real-time mode is enabled.
## Delete Cloud Data
```bash
curl -X DELETE \
-H "Authorization: Bearer <UPLOAD_TOKEN>" \
"https://watch-health-mcp.<your-subdomain>.workers.dev/data"
```
After returning `{"ok":true,"deleted":true}`, the latest data, limited history, and pending commands in the Durable Object have been cleared.
## Development Check
```bash
cd cloudflare
npm test
npm run check
```
iOS and watchOS projects recommend using Xcode 16 or later. The minimum deployment target is iOS 17 and watchOS 10.
## License
[MIT](LICENSE)