shopping-radar
Enables Claude to search and analyze product listings from multiple French marketplaces, evaluating price, delivery, and distance to a reference point to find the best value.
README
shopping-radar đđ
Serveur MCP qui permet à Claude de récupérer les annonces d'un produit sur plusieurs places de marché françaises et de les analyser rigoureusement : prix, date, livraison, et distance au point de référence (Montpellier) quand l'article n'est pas livrable.
Pensé pour trouver le meilleur rapport qualité-prix (ex. un cadeau), en comparant l'occasion au prix du neuf.
Sources (8)
| Source | Type | ClĂ© requise | Ătat |
|---|---|---|---|
| Leboncoin (direct) | occasion | â (intermittent, DataDome) | â actif |
| Leboncoin (Apify) | occasion fiable | APIFY_TOKEN (~1 $/1000 résultats) |
â testĂ©, opt-in |
| Vinted | occasion | â | â actif |
| Dealabs | deals neuf / erreurs de prix | â | â actif |
| eBay | occasion + reconditionné | EBAY_APP_ID + EBAY_CERT_ID (gratuit) |
đ sur clĂ© |
| Google Shopping | neuf (multi-marchands) | SERPAPI_KEY (gratuit limité) |
đ sur clĂ© |
| Idealo | comparateur neuf | APIFY_TOKEN (crédit gratuit) |
đ sur clĂ© |
| Keepa | Amazon neuf + historique | KEEPA_API_KEY (payant) |
đ sur clĂ© |
| Back Market | reconditionné garanti | APIFY_TOKEN + BACKMARKET_APIFY_ACTOR |
đ sur clĂ© |
Les 3 premiÚres fonctionnent sans aucune clé. Les autres s'activent en ajoutant la clé correspondante dans
.env. Aucune dĂ©pendance Python supplĂ©mentaire n'est nĂ©cessaire pour les activer (sauf Keepa) â tout passe parhttpx.
Couverture par usage
- Occasion : Leboncoin, Vinted, eBay
- Reconditionné : Back Market, eBay
- Neuf / prix de rĂ©fĂ©rence : Google Shopping (Amazon, Fnac, Darty, BoulangerâŠ), Idealo, Keepa, Dealabs
Pipeline d'analyse & qualité des données
analyze enchaĂźne : recherche multi-sources â dĂ©duplication â filtre logistique
(Montpellier) â filtre de pertinence â enrichissement qualitĂ© â tri par score
composite. Chaque offre gardée est enrichie de :
condition_labelâ Ă©tat normalisĂ© sur une Ă©chelle standard (neuf, comme neuf, trĂšs bon, bon, correct, reconditionnĂ©, pour piĂšces).is_bundleâ dĂ©tecte les lots/packs (« + 2 batteries », « pack complet »).risk_level(ok/faible/moyen/eleve) +risk_flags:prix_tres_bas(sous mĂ©diane â 30 %),marque_incoherente(marque â produit recherchĂ©),import_hors_fr(titre en langue Ă©trangĂšre â transfrontalier),vendeur_inconnu.deal_scoreâ note composite 0-100 oĂč le risque PRIME sur le prix : la valeur-prix est plafonnĂ©e sous le seuil « trop beau pour ĂȘtre vrai » (pas de bonus pour les prix d'arnaque) et un malus de risque (jusqu'Ă â45) Ă©crase le bonus prix. PondĂ©ration : prix vs neuf (50) + Ă©tat (20) + proximitĂ© (15) + confiance vendeur (10) â risque.- Segmentation par variante : les stats (mĂ©diane, seuil « trop bas ») sont calculĂ©es par segment (sous-modĂšle Ă premium/standard), pas sur un pool qui mĂ©langerait X4 nue / Adventure / Bike⊠Le seuil bas est auto-calibrĂ© par z-score robuste (mĂ©diane â k·MAD intra-segment), au lieu d'un ratio fixe.
- DĂ©tection de mislabel : une variante premium (« Adventure », « Bike »âŠ)
affichĂ©e sous le prix d'une version de base â flag
mislabel_suspect(résolu sans référence externe, par comparaison inter-segments). - Seuils configurables :
RISK_LOW_PRICE_RATIO,RISK_MAD_K,IMPORT_MARKERS,PREMIUM_KEYWORDS.
Limites encore ouvertes (assumĂ©es) : (1) la validation du modĂšle de risque repose sur des tests unitaires (change-detectors), pas sur un jeu labellisĂ© prĂ©cision/rappel ; (2) les stats vendeur (note, anciennetĂ©, derniĂšre connexion) et la fraĂźcheur/statut vendu des annonces ne sont pas encore exploitĂ©es â ce sont les signaux anti-fraude les plus forts ; (3) le score n'intĂšgre pas encore garantie FR / retour / complĂ©tude accessoires.
also_onâ autres sources oĂč l'article a Ă©tĂ© repĂ©rĂ© (dĂ©duplication inter-sources).
stats remonte aussi duplicates_removed, suspicious_count, new_reference_price.
Tests : python tests/test_core.py (tests déterministes, sans réseau).
Validation (au-delĂ des tests unitaires) : python eval/score.py <gold> mesure
le rappel scam (la vraie cible) séparément du risky, avec IC95% Wilson
(honnĂȘte sur petit N), + faux positifs sur les ok. Protocole de labellisation
figé dans eval/LABELING.md (verdict ok/risky/scam,
labellisation Ă l'aveugle).
Workflow gold réel :
python eval/make_batch.pyâeval/to_label.jsonl(batch rĂ©el, aveugle, stratifiĂ©-pour-faire-mal : imports/bundles/refurb/prix bas/phrases FR ambiguĂ«s).- Labelliser Ă la main (
verdict+reason) seloneval/LABELING.md. python eval/score.py eval/to_label.jsonlâ vrais prĂ©cision/rappel.
eval/gold.jsonl (25 lignes synthétiques) reste comme détecteur de régression
(il a chiffré puis verrouillé le fix « prix négociable »). C'est un détecteur de
modes d'échec, pas un go/no-go statistique au pourcent.
Vers un produit (SaaS) : voir docs/AUDIT.md (audit du code), docs/ARCHITECTURE.md (passage statelessâstateful : Postgres
- file de jobs + précalcul) et db/schema.sql. Le moteur actuel devient la couche worker, on ne le réécrit pas.
Sécurité free tier (quotas)
Un garde-fou (core/quota.py) compte les appels par provider et
bloque proprement avant de dépasser la limite gratuite (pas de facturation
surprise). Usage persisté dans .cache/usage.json. Limites par défaut (juin 2026,
surchargeables dans .env) :
| Provider | Limite gratuite | FenĂȘtre |
|---|---|---|
| SerpAPI | 250 recherches | mois |
| Apify (runs) | 50 runs (vrai plafond = 5 $ de crédit) | mois |
| eBay Browse | 5 000 appels | jour |
| Base Adresse Nationale | 2 000 (poli) | jour |
- Sources coûteuses opt-in : Idealo, Back Market (runs Apify) et Keepa
consomment du crĂ©dit â exclues des recherches par dĂ©faut. Pour les utiliser,
les nommer :
analyze(query, sources=["vinted","idealo"]). Google Shopping (SerpAPI, gratuit) fournit dĂ©jĂ le prix neuf de rĂ©fĂ©rence par dĂ©faut. - Ătat des quotas visible via l'outil
list_sources.
Fiabilité Leboncoin & proxy
Important : la lib lbc fait dĂ©jĂ le plus dur â impersonation TLS via
curl_cffi (JA3 d'un vrai navigateur), amorçage du cookie DataDome (GET homepage),
et utilisation de l'API mobile avec un User-Agent d'app. La couche TLS n'est
donc PAS le problÚme. Les 503 intermittents viennent de la réputation de l'IP
(ton IP perso flaggĂ©e aprĂšs quelques requĂȘtes). Le seul vrai levier = une IP propre.
Du gratuit au plus fiable :
- Retries + rotation de fingerprint (gratuit, activé) :
LEBONCOIN_RETRIES=3. - Proxy résidentiel FR :
LEBONCOIN_PROXY=...ou un poolLEBONCOIN_PROXIES=p1,p2,...(rotation alĂ©atoire). Options :LEBONCOIN_IMPERSONATE,LEBONCOIN_DATADOME_COOKIE. - â
Source
leboncoin_apify(la plus fiable, recommandée) : acteur Apifyfatihtahta/leboncoin-fr-scraper(proxy résidentiel inclus ~1 $/1000 résultats). Testée, données riches (GPS, code postal, vendeur pro/particulier). Opt-in :analyze(query, sources=["leboncoin_apify","vinted","google_shopping"]).
â ïž Pas de proxy gratuit fiable contre DataDome (les gratuits = IP datacenter, filtrĂ©es). Voie fiable « sans CB » : la source
leboncoin_apify(crédit Apify).
GĂ©nĂ©rique â fonctionne pour n'importe quel article
Rien n'est codĂ© en dur pour un produit donnĂ© : la requĂȘte est un paramĂštre, le
point de référence est dans .env (HOME_LAT/LNG), et les heuristiques sont
génériques. Pour un domaine précis, on ajoute des mots-clés via .env :
ACCESSORY_KEYWORDS=perche,objectif,trepied (photo) ou âŠ=pompe,antivol (vĂ©lo),
et BUNDLE_KEYWORDS=.... Le filtre de pertinence (is_relevant) s'adapte seul au
modÚle recherché (tokens chiffrés type « x4 », « 13 »).
RĂšgle livraison / distance (mise Ă jour)
Une annonce est rejetĂ©e uniquement si elle est explicitement non livrable ET trop loin. Si la livraison est inconnue (cas frĂ©quent Leboncoin), l'annonce est gardĂ©e avec un drapeau « (!) livraison Ă vĂ©rifier » plutĂŽt que jetĂ©e â on ne perd pas une bonne affaire potentiellement livrable.
Géolocalisation
Si une annonce n'a pas de coordonnées GPS (fréquent sur Leboncoin), le code
postal/ville est géocodé via l'API officielle Base Adresse Nationale
(gratuite, sans clé) pour calculer la distance à Montpellier. Cache dans
.cache/geocode.json.
Installation
python -m venv .venv
.venv\Scripts\activate # Windows
pip install -r requirements.txt
copy .env.example .env # puis éditer si besoin
Outils exposés à Claude (MCP)
list_sources()â sources disponibles + point de rĂ©fĂ©rence.search_all(query, max_price?, sources?, limit_per_source?)â rĂ©cupĂšre les offres normalisĂ©es de toutes les sources actives (en parallĂšle).analyze(query, max_price?, max_distance_km?, reference_price?, ...)â recherche + filtrage logistique (livrable OU à †X km de Montpellier) + tri par prix et score de valeur vs prix neuf.build_candidates(query, budget?, priorities?, top_k?, ...)â produit le « fichier de candidats » pour un agent dĂ©cideur : normalise chaque offre (schĂ©ma stable,total_cost_normalized,warranty_monthsoĂč null â 0), met en quarantaine le risque Ă©levĂ©/mislabel (jamais transmis), et stratifie en top-K par (modĂšle Ă Ă©tat). Renvoie aussi un brief de dĂ©cision. Le dĂ©terministe ne tranche rien de subjectif â c'est le job de l'agent.
Brancher sur Claude Code / Claude Desktop
Ajouter dans la config MCP (ex. claude_desktop_config.json) :
{
"mcpServers": {
"shopping-radar": {
"command": "python",
"args": ["C:/Users/rayan/Desktop/Dev/Leboncoin/server.py"]
}
}
}
Puis, dans Claude : « Analyse les Insta360 X4 d'occasion sous 320 âŹ, livrables ou Ă moins de 50 km de Montpellier. »
RÚgle métier « livraison / distance »
Une offre est gardée si :
- elle est livrable, OU
- sa distance au point de rĂ©fĂ©rence â€
MAX_DISTANCE_KM(défaut 60 km).
Si livraison et distance sont inconnues, l'offre est gardée mais marquée « à vérifier » (on ne jette jamais une offre faute d'information).
Avertissements
- Les clients Leboncoin/Vinted reposent sur des API non-officielles qui peuvent casser sans préavis et dont l'usage peut contrevenir aux CGU des sites. Réservé à un usage personnel et raisonnable.
- L'analyse finale (recommandation) est faite par Claude ; ce serveur fournit la donnée normalisée et un pré-tri déterministe.
Architecture
server.py # serveur MCP (outils list_sources / search_all / analyze)
core/
models.py # Offer normalisée + parsing prix/date
geo.py # distance Montpellier (haversine) + géocodage des CP manquants
geocode.py # géocodage Base Adresse Nationale (gratuit) + cache disque
score.py # filtre logistique/accessoires + scoring qualité-prix
sources/
base.py # interface Source
leboncoin.py vinted.py dealabs.py # gratuit
leboncoin_apify.py # Leboncoin fiable (Apify, opt-in)
ebay.py google_shopping.py idealo.py # sur clé
keepa.py backmarket.py # sur clé
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.