Apple Forme MCP
README.md
# Apple Forme MCP
Serveur MCP qui expose 2 tools basés sur tes données Apple Watch (via l'app
**Health Auto Export**, puisqu'Apple Health n'a pas d'API web) :
- `resume_hebdo` : distance, allure, régularité, tendance
- `charge_entrainement` : ratio charge aiguë/chronique (ACWR), avec fallback
si l'historique est trop court
S'y ajoute un **dashboard web** (`/dashboard`) servi par le même serveur :
stats filtrables par période (7/30/90 jours, tout) et par type d'exercice
(course, cyclisme, marche, yoga, cardio, pilates), avec comparaison vs la
période précédente et mode sombre. Consultable depuis n'importe quel appareil
du réseau local : `http://<ip-du-mac>:8000/dashboard`.
## Architecture
```
iPhone (Health Auto Export, même wifi que le Mac)
--POST JSON--> receiver.py (FastAPI, sur le réseau local uniquement)
--stocke--> forme.db (SQLite)
--lu par--> mcp_server.py --> Claude
```
Pas de tunnel public ici : le webhook n'est joignable que depuis ton réseau
wifi local. C'est le choix le plus simple côté vie privée — tes données de
santé ne transitent par aucun service tiers. La contrepartie : la sync ne se
fait que quand ton iPhone et ton Mac sont sur le même wifi (typiquement chez
toi le soir), et ton Mac doit être allumé avec `receiver.py` lancé à ce
moment-là. Largement suffisant pour un résumé hebdo et un calcul ACWR, qui
n'ont pas besoin de données en temps réel.
## 1. Installer les dépendances
```bash
cd apple-forme-mcp
python -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# édite .env : mets un WEBHOOK_TOKEN aléatoire
python -c "import secrets; print(secrets.token_hex(24))"
```
## 2. Lancer le webhook receiver
```bash
uvicorn receiver:app --host 0.0.0.0 --port 8000
```
`--host 0.0.0.0` fait écouter `receiver.py` sur toutes les interfaces réseau
du Mac, donc y compris le wifi — c'est ce qui permet à l'iPhone de le joindre.
## 3. Trouver l'IP locale de ton Mac
```bash
ipconfig getifaddr en0
```
Ça renvoie une adresse du type `192.168.1.42`. C'est l'IP à utiliser dans
l'automatisation Health Auto Export (voir étape 4). Elle peut changer si ta
box réattribue les IP — si l'automatisation arrête de fonctionner du jour au
lendemain, reviens vérifier cette commande.
Pense à laisser ton Mac allumé (pas en veille) et `receiver.py` lancé au
moment où tu veux que la sync se fasse — par exemple le soir en rentrant de
ta sortie.
## 4. Configurer Health Auto Export sur l'iPhone
Dans l'app > Automations > New Automation :
- **Automation Type** : REST API
- **URL** : `http://192.168.1.42:8000/health-auto-export/webhook` (remplace
par l'IP trouvée à l'étape 3)
- **Header** : `Authorization: Bearer <ton WEBHOOK_TOKEN>`
- **Data Type** : Workouts (décoche "Routes"/"GPS" — inutile pour les 2 tools
et c'est la donnée la plus sensible de l'export)
- **Format** : JSON
- **Export Version** : 2
- **Sync Behavior** : "Since Last Sync"
- **Fréquence** : ex. toutes les 6h, ou 1x/jour
⚠️ Limites Apple à connaître : les automatisations ne tournent que quand le
téléphone est déverrouillé, et iOS limite l'exécution en arrière-plan — donc
attends-toi à un léger délai, pas du vrai temps réel.
Fais un premier **Manual Export** dans l'app pour peupler direct ta base avec
ton historique existant, plutôt que d'attendre que ça s'accumule au fil de
l'eau. Les automatisations ne proposent que des plages relatives ; pour un
gros historique, utilise plutôt la section **Exportations** de l'app (plage
de dates libre → fichier JSON), transfère le fichier sur le Mac, puis :
```bash
python import_file.py ~/Downloads/HealthAutoExport-*.json
```
Les doublons sont gérés (upsert par identifiant de séance) : réimporter des
données déjà connues est sans effet.
## 5. Lancer le serveur MCP
```bash
python mcp_server.py
```
Puis ajoute-le dans `claude_desktop_config.json` :
```json
{
"mcpServers": {
"apple-forme": {
"command": "/chemin/absolu/vers/venv/bin/python",
"args": ["/chemin/absolu/vers/apple-forme-mcp/mcp_server.py"]
}
}
}
```
## Limites connues / à améliorer
- **Charge de session** : approximée via `durée × (FC moyenne / 60)` faute de
RPE façon Strava. À affiner avec un vrai TRIMP (Banister) une fois que tu
as FC repos/FC max calibrées dans le code (`training_load.py`).
- **Fallback ACWR** : en dessous de 21 jours d'historique, le tool renvoie une
tendance semaine/semaine précédente plutôt qu'un ratio non fiable.
- **Format d'export** : le code gère "Workouts v2". Si tu configures
l'automatisation en v1, dis-le moi pour que j'adapte `store.py`.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues