# 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**. ## État (validĂ© de bout en bout, 2026-06) ✅ **Boucle complĂšte testĂ©e sur le vrai compte** : lecture du menu (`menus-service/menus` → dĂ©tails batch `recipes/recipes?ids=
`), filtrage coco (4/85 dĂ©tectĂ©es, faux positifs des tags internes neutralisĂ©s), proposition classĂ©e, et **Ă©criture rĂ©elle rĂ©ussie** (`PUT /v1/carts/{week}`, HTTP 200) — sĂ©lection par index de course, ids de compte dĂ©rivĂ©s dynamiquement. ✅ **Auth autonome (pur HTTP)** : le token (30 min) est rafraĂźchi par un simple `POST /gw/refresh` (le endpoint que la SPA appelle), **sans navigateur**. Le refresh_token roule par fenĂȘtres de 60 j, remises Ă  zĂ©ro Ă  chaque refresh → un homelab **allumĂ© en continu** reste authentifiĂ© sans intervention ni re-sync. Le navigateur headless ne sert plus que de filet de secours. > ⚠ La chaĂźne de refresh **peut casser** (homelab Ă©teint trop longtemps, ou refresh_token > consommĂ© hors `_refresh_session`) → `POST /gw/refresh` renvoie `invalid_grant` et > `auth_status()` passe Ă  `logged_in:false`. Le seul remĂšde est de **refaire le login CDP** > (cf. ci-dessous). **Restaurer un ancien `.session/` ne marche pas** : les refresh_token sont > rotatifs, les anciens sont morts. > ⚠ La connexion **directe** automatisĂ©e (Playwright/Chromium qui remplit le formulaire) est > bloquĂ©e par l'anti-bot HelloFresh. La session se crĂ©e donc via **attache CDP Ă  ton vrai Chrome** > (`tools/attach_capture.py`), oĂč le login marche normalement. ## Architecture ``` Hermes ──HTTP──▶ server.py (FastMCP, :9200/mcp) ├─ hellofresh/auth.py session storage_state + refresh HTTP /gw/refresh ├─ hellofresh/api.py httpx : menu, dĂ©tails, deliveries, PUT cart ├─ 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 ``` ### 2. CrĂ©er (ou rĂ©-crĂ©er) la session — login via TON Chrome, anti-bot contournĂ© C'est **la seule mĂ©thode de login qui marche** : un navigateur pilotĂ© par Playwright (mĂȘme avec `channel=chrome`) est bloquĂ© par l'anti-bot HelloFresh. On lance donc le vrai Chrome en mode debug et on s'y **attache en CDP** (lecture seule). MĂȘme procĂ©dure pour la 1Êłá”‰ session **et** pour une rĂ©-authentification aprĂšs `invalid_grant`. ```bash # 1) Lance ton vrai Chrome en mode debug avec un PROFIL DÉDIÉ (Chrome ≄149 refuse le debug # sur le profil par dĂ©faut). Ta fenĂȘtre Chrome habituelle peut rester ouverte. "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ --remote-debugging-port=9222 --user-data-dir="$HOME/.hf-chrome-debug" \ https://www.hellofresh.fr/my-account/deliveries/menu # 2) Connecte-toi dans cette fenĂȘtre (page de login = https://www.hellofresh.fr/login). # 3) Pendant que Chrome reste ouvert et connectĂ©, attache la capture : python tools/attach_capture.py # capture trafic + exporte .session/storage_state.json ``` `attach_capture` doit tourner **pendant** que tu (re)charges la page menu, pour capter le trafic. Il **Ă©crase** `.session/storage_state.json` avec la session fraĂźche (cookies ~60 j) — ne pas restaurer un vieux backup Ă  la place (refresh_token rotatif = anciens morts). VĂ©rifie ensuite : `python -c "from hellofresh import auth, json; print(auth.auth_status())"` → `logged_in: true`. `config/endpoints.json` est dĂ©jĂ  rempli ; rejoue `attach_capture` si l'API change. ### 3. Tester en local (headless, comme le homelab) ```bash python server.py # auth via storage_state, refresh token automatique ``` ## DĂ©ploiement homelab (Docker) `.session/` et `.env` ne sont **jamais** versionnĂ©s. Workflow : ```bash # 1. Sur le Mac : gĂ©nĂ©rer la session (cf. « Mise en route » §2 → .session/storage_state.json) # 2. Pousser le code git add -A && git commit -m "..." && git push # 3. Synchroniser la session vers le homelab (NON versionnĂ©e ; endpoints.json est dans git) # storage_state.json suffit (le homelab tourne headless et rafraĂźchit le token tout seul). scp .session/storage_state.json jerem@192.168.0.43:/AntiCoco/.session/ # 4. Sur le homelab : dĂ©ployer ssh homelab cd /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_next_delivery()` | **prochaine box rĂ©ellement sĂ©lectionnĂ©e** (≈4 recettes) + date/cutoff, images servables — prĂȘt Telegram | | `hf_favorites()` | recettes **favorites** du compte (images servables) | | `hf_get_menu(week)` | toutes les recettes, avec `contains_excluded` et `is_favorite` | | `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 + transfo CDN images (`image_cdn_*` : les URLs recettes CloudFront `
/0,0/image/X` rĂ©pondent en 502, réécrites vers `img.hellofresh.com/
/hellofresh_s3/image/X`). SĂ©lection courante via `my-deliveries/menu`, favoris via `cfs/v2/favorites/recipe`. Re-dĂ©couverte : `tools/probe_selection.py` / `tools/probe_menu_capture.py` (attache CDP).