- Auth Playwright (login local, session persistee, capture du bearer token) - Client httpx vers l'API interne (endpoints via discover_api.py) - Filtre d'exclusion insensible aux accents (coco & co) - Serveur FastMCP (streamable-http) + outils hf_* - Docker + compose pour deploiement homelab
91 lines
3.6 KiB
Markdown
91 lines
3.6 KiB
Markdown
# AntiCoco 🥥🚫
|
|
|
|
Serveur **MCP** qui donne accès à ton compte **HelloFresh** (France, `hellofresh.fr`) pour :
|
|
lire le menu de la semaine, **exclure des ingrédients** (la **noix de coco** en priorité),
|
|
**proposer une shortlist** de recettes, puis **enregistrer ta sélection** après confirmation.
|
|
|
|
Client MCP visé : **Hermes** (Nous Research), qui tourne sur le même homelab.
|
|
|
|
> ⚠️ HelloFresh n'a pas d'API publique. AntiCoco s'appuie sur l'API interne `gw/` du site
|
|
> (non documentée, susceptible de changer) — **usage strictement personnel**.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Hermes ──HTTP──▶ server.py (FastMCP, :9200/mcp)
|
|
├─ hellofresh/auth.py login Playwright + capture du bearer token
|
|
├─ hellofresh/api.py appels httpx vers le gateway HelloFresh
|
|
├─ hellofresh/filter.py exclusion (coco !) + scoring préférences
|
|
└─ config/ excludes.json · prefs.json · endpoints.json
|
|
```
|
|
|
|
## Mise en route
|
|
|
|
### 1. Installer
|
|
```bash
|
|
pip install -r requirements.txt
|
|
playwright install chromium
|
|
cp .env.example .env # remplir HF_EMAIL / HF_PASSWORD (optionnels, fallback re-login)
|
|
```
|
|
|
|
### 2. Découvrir les endpoints (étape 0, en local, fenêtre visible)
|
|
```bash
|
|
ANTICOCO_HEADLESS=0 python tools/discover_api.py
|
|
```
|
|
Connecte-toi, ouvre le menu de la semaine, change une recette pour capturer l'écriture, puis
|
|
Entrée. Vérifie/complète ensuite `config/endpoints.json` (généré depuis le trafic capturé,
|
|
voir aussi `.session/discovery_log.json`).
|
|
|
|
### 3. Tester en local
|
|
```bash
|
|
ANTICOCO_HEADLESS=0 python server.py # 1er run : login dans la fenêtre si besoin
|
|
```
|
|
Le login crée `.session/profile` (profil Playwright persistant) — réutilisé ensuite headless.
|
|
|
|
## Déploiement homelab (Docker)
|
|
|
|
`.session/` et `.env` ne sont **jamais** versionnés. Workflow :
|
|
|
|
```bash
|
|
# 1. Sur le Mac : générer une session connectée (fenêtre visible)
|
|
ANTICOCO_HEADLESS=0 python server.py # se connecter, puis Ctrl-C
|
|
|
|
# 2. Pousser le code
|
|
git add -A && git commit -m "..." && git push
|
|
|
|
# 3. Synchroniser la session vers le homelab (NON versionnée)
|
|
scp -r .session config/endpoints.json jerem@192.168.0.43:<path>/AntiCoco/
|
|
|
|
# 4. Sur le homelab : déployer
|
|
ssh homelab
|
|
cd <path>/AntiCoco && git pull && docker compose up -d --build
|
|
```
|
|
|
|
Vérifier : `curl -s http://127.0.0.1:9200/mcp` (le serveur répond au handshake MCP).
|
|
|
|
## Intégration Hermes
|
|
|
|
Enregistrer AntiCoco dans la config MCP de Hermes (côté homelab), URL
|
|
`http://127.0.0.1:9200/mcp` (transport streamable-http).
|
|
|
|
> Si Hermes n'accepte que le **stdio**, changer la dernière ligne de `server.py`
|
|
> (`mcp.run(transport="stdio")`) et lancer le serveur en sous-processus — le reste est identique.
|
|
|
|
## Outils MCP exposés
|
|
|
|
| Outil | Rôle |
|
|
|-------|------|
|
|
| `hf_auth_status()` | état de connexion |
|
|
| `hf_login()` | (re)connexion + capture token |
|
|
| `hf_list_weeks()` | semaines modifiables |
|
|
| `hf_get_menu(week)` | toutes les recettes, avec flag `contains_excluded` |
|
|
| `hf_propose(week, count=0)` | shortlist **sans coco**, classée par préférences |
|
|
| `hf_confirm_selection(week, recipe_ids)` | **écrit** la sélection (refuse la coco) |
|
|
| `hf_get_excludes()` / `hf_add_exclude(term)` / `hf_remove_exclude(term)` | gérer la liste d'exclusion |
|
|
|
|
## Configuration
|
|
|
|
- `config/excludes.json` — ingrédients bannis (matching insensible casse/accents). Coco déjà listée.
|
|
- `config/prefs.json` — mots-clés `liked`/`disliked` pour classer les propositions.
|
|
- `config/endpoints.json` — URLs gateway réelles (généré par `discover_api.py`, non versionné).
|