Sélection courante + favoris + images servables (sortie prête Hermes)
Deux outils MCP pour qu'Hermes n'ait plus de scripts à écrire :
- hf_next_delivery() : prochaine box RÉELLEMENT sélectionnée (≈4 recettes,
pas le menu complet) + date/cutoff ; erreur stricte si introuvable
(jamais de repli propose). Saute les semaines PAUSED via next_delivery.
- hf_favorites() : recettes favorites du compte. Champ is_favorite ajouté
partout (hf_get_menu inclus).
Endpoints découverts (probe CDP) :
- sélection : GET /gw/my-deliveries/menu -> meals[].selection.quantity>0
- favoris : GET /gw/cfs/v2/favorites/recipe -> items[].object_id
(GET /gw/v1/carts/{week} renvoie 404 : pas la lecture de sélection.)
Images : URLs recettes CloudFront (502) réécrites vers
img.hellofresh.com/.../hellofresh_s3/... (hellofresh/images.py),
appliqué dans Recipe.summary() -> profite à tous les outils.
README : procédure de ré-auth CDP clarifiée (refresh tokens rotatifs,
backups inutiles, page /login, profil Chrome dédié).
Outils de re-découverte : tools/probe_selection.py, tools/probe_menu_capture.py
This commit is contained in:
52
server.py
52
server.py
@@ -73,6 +73,55 @@ async def hf_account_info() -> dict:
|
||||
return await anyio.to_thread.run_sync(_impl)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def hf_next_delivery() -> dict:
|
||||
"""Prochaine livraison + recettes RÉELLEMENT sélectionnées (prêt à mettre en forme).
|
||||
|
||||
Renvoie la semaine, la date de livraison, le cutoff, et les ~4 recettes de la box avec
|
||||
image servable (URL corrigée), temps de prépa, allergènes, tags, `is_favorite`. Erreur
|
||||
stricte si la sélection est introuvable — ne propose JAMAIS de recettes non sélectionnées.
|
||||
"""
|
||||
def _impl() -> dict:
|
||||
with api.HelloFreshClient() as client:
|
||||
acct = client.account_info()
|
||||
nd = acct.get("next_delivery") or {}
|
||||
week = nd.get("week")
|
||||
if not week:
|
||||
raise RuntimeError("Aucune prochaine livraison (abonnement en pause ?).")
|
||||
recipes = client.get_current_selection(week) # lève si vide / KO
|
||||
favs = client.favorite_ids()
|
||||
hf_filter.annotate(recipes)
|
||||
for r in recipes:
|
||||
r.is_favorite = r.id in favs
|
||||
return {
|
||||
"week": week,
|
||||
"delivery_date": nd.get("date"),
|
||||
"cutoff": nd.get("cutoff"),
|
||||
"count": len(recipes),
|
||||
"recipes": [r.summary() for r in recipes],
|
||||
}
|
||||
|
||||
return await anyio.to_thread.run_sync(_impl)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def hf_favorites() -> dict:
|
||||
"""Recettes favorites du compte, complètes (image corrigée, allergènes, `is_favorite`).
|
||||
|
||||
Lecture seule. Liste vide si aucun favori. Indépendant de la semaine (favoris globaux).
|
||||
"""
|
||||
def _impl() -> dict:
|
||||
with api.HelloFreshClient() as client:
|
||||
recipes = client.get_favorites()
|
||||
hf_filter.annotate(recipes)
|
||||
return {
|
||||
"count": len(recipes),
|
||||
"recipes": [r.summary() for r in recipes],
|
||||
}
|
||||
|
||||
return await anyio.to_thread.run_sync(_impl)
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
async def hf_get_menu(week: str = "") -> dict:
|
||||
"""Toutes les recettes proposées pour une semaine, chacune annotée.
|
||||
@@ -84,7 +133,10 @@ async def hf_get_menu(week: str = "") -> dict:
|
||||
w = week or api.current_week()
|
||||
with api.HelloFreshClient() as client:
|
||||
recipes = client.get_menu(w)
|
||||
favs = client.favorite_ids() # best-effort (set() si indispo)
|
||||
hf_filter.annotate(recipes)
|
||||
for r in recipes:
|
||||
r.is_favorite = r.id in favs
|
||||
return {
|
||||
"week": w,
|
||||
"count": len(recipes),
|
||||
|
||||
Reference in New Issue
Block a user