iwatch-mcp
by Edplayerone
README.md
# iwatch-mcp
Real-time Apple Watch heart rate monitoring via the [Model Context Protocol](https://modelcontextprotocol.io).
Heart rate data flows: **Apple Watch → iPhone → Mac (via iCloud/HealthKit)**.
This server reads it from macOS HealthKit and exposes it as MCP tools to Claude or any MCP client.
## Architecture
```
Claude / MCP client
│ MCP (stdio)
▼
iwatch-mcp (Python) ← pip install
│ subprocess
▼
HealthKitHelper (Swift CLI) ← ./healthkit-helper/build.sh
│ HealthKit API
▼
macOS HealthKit database ← synced from Apple Watch via iPhone
```
## Prerequisites
| Requirement | Notes |
|---|---|
| macOS 13+ | HealthKit for Mac requires Ventura or later |
| Xcode | Installed from the App Store (needed to build Swift helper) |
| Apple Developer account | Required to sign the binary with HealthKit entitlement |
| Apple Watch paired | Data syncs through iPhone → iCloud → Mac |
| Python 3.11+ | For the MCP server |
> **Why signing is required:** `com.apple.developer.healthkit` is a restricted entitlement.
> macOS will reject HealthKit calls from binaries not signed with a valid Apple Developer certificate.
## Setup
### 1 — Build and sign the Swift helper
```bash
cd healthkit-helper
./build.sh
```
`build.sh` automatically finds the best signing identity in your keychain
(prefers "Developer ID Application", falls back to "Apple Development").
To list available signing identities:
```bash
security find-identity -v -p codesigning
```
To sign manually with a specific identity:
```bash
codesign --force \
--sign "Apple Development: you@example.com (TEAMID)" \
--entitlements HealthKitHelper.entitlements \
--options runtime \
.build/release/HealthKitHelper
```
### 2 — Grant HealthKit access
Run the helper once to trigger the macOS permission dialog:
```bash
./healthkit-helper/.build/release/HealthKitHelper latest
```
When prompted, open **System Settings → Privacy & Security → Health** and enable
**HealthKitHelper** for reading heart rate data.
### 3 — Install the Python MCP server
```bash
pip install -e .
```
Or with pipx (recommended for isolation):
```bash
pipx install .
```
### 4 — Connect to Claude
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`.
**Option A — venv entrypoint (recommended):**
```json
{
"mcpServers": {
"iwatch": {
"command": "/Users/ehuang/Repos/iwatch-mcp/.venv/bin/iwatch-mcp"
}
}
}
```
**Option B — run via python module:**
```json
{
"mcpServers": {
"iwatch": {
"command": "/Users/ehuang/Repos/iwatch-mcp/.venv/bin/python",
"args": ["-m", "iwatch_mcp.server"]
}
}
}
```
Restart Claude Desktop. The `iwatch` server will appear in the MCP panel.
## MCP Tools
### `get_heart_rate`
Returns the most recent heart rate sample from HealthKit.
**Example response:**
```json
{
"bpm": 72.0,
"timestamp": "2025-06-15T14:32:00.000Z",
"source": "Apple Watch",
"device": "Apple Watch Series 9"
}
```
---
### `stream_heart_rate(duration_seconds: int = 30)`
Collects readings over a rolling time window.
Immediately returns any buffered readings from the last 5 minutes, then
watches for new samples for `duration_seconds` seconds.
**Note:** Apple Watch syncs over iCloud — "real-time" latency is typically 10–60 seconds.
**Example response:**
```json
[
{"bpm": 68.0, "timestamp": "2025-06-15T14:31:45.000Z", "source": "Apple Watch", "device": "Apple Watch Series 9"},
{"bpm": 70.0, "timestamp": "2025-06-15T14:32:00.000Z", "source": "Apple Watch", "device": "Apple Watch Series 9"}
]
```
---
### `get_heart_rate_history(hours: float = 24.0)`
Retrieves and summarises historical heart rate data.
**Example response:**
```json
{
"count": 42,
"hours_requested": 24.0,
"min_bpm": 52.0,
"max_bpm": 143.0,
"avg_bpm": 71.3,
"first_timestamp": "2025-06-14T14:35:00.000Z",
"last_timestamp": "2025-06-15T14:32:00.000Z",
"samples": [...]
}
```
## MCP Resource
`healthkit://heart-rate/status` — reports whether the helper binary is built and ready.
## Environment Variables
| Variable | Default | Description |
|---|---|---|
| `HEALTHKIT_HELPER_PATH` | `healthkit-helper/.build/release/HealthKitHelper` | Override binary location |
## Troubleshooting
### "HealthKit is not available on this device"
HealthKit requires macOS 13+ on Apple Silicon (M1/M2/M3 Mac). It is not available on Intel Macs.
### "Auth failed" / empty results after first run
1. Open **System Settings → Privacy & Security → Health**
2. Scroll to find **HealthKitHelper** and toggle on **Heart Rate**
3. Also ensure the Health app is open and signed into iCloud
### No data / stale data
Health data syncs from Apple Watch through iPhone. Make sure:
- iPhone is nearby and connected (Wi-Fi or Bluetooth to Mac)
- iCloud Drive is enabled on both iPhone and Mac
- Health app is signed into the same Apple ID on Mac
### Binary not signed / HealthKit permission denied
HealthKit requires a real Apple Developer certificate. Ad-hoc signing (`-s -`) does not work
for the `com.apple.developer.healthkit` entitlement. You need either:
- A paid Apple Developer Program membership ($99/year)
- Or a free Apple Developer account (limited entitlements — HealthKit is included for device testing)
### Test the helper directly
```bash
# Latest reading
./healthkit-helper/.build/release/HealthKitHelper latest
# 24 hours of history
./healthkit-helper/.build/release/HealthKitHelper history 24
# Stream for 60 seconds
./healthkit-helper/.build/release/HealthKitHelper stream 60
```
TDQS
A4.4/5.0
Scored across 3 tools
Disambiguation5/5
Each tool serves a distinct purpose: one returns the most recent single reading, one retrieves historical data over a time window, and one streams live data. No overlap.
Naming Consistency5/5
All tools follow a consistent verb_noun pattern using snake_case: get_heart_rate, get_heart_rate_history, stream_heart_rate.
Tool Count5/5
Three tools is appropriate for heart rate access: current reading, history, and streaming. Not too few nor too many.
Completeness4/5
CRUD-like coverage: read single, read history, stream. Minor gap: no way to query a specific time range outside 'past N hours' or duration.
Maintenance
ActivityInactive
ResponsivenessNo issues