shopping-radar

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.

Category
Visit Server

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 par httpx.

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 :

  1. 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).
  2. Labelliser Ă  la main (verdict + reason) selon eval/LABELING.md.
  3. 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 :

  1. Retries + rotation de fingerprint (gratuit, activé) : LEBONCOIN_RETRIES=3.
  2. Proxy résidentiel FR : LEBONCOIN_PROXY=... ou un pool LEBONCOIN_PROXIES=p1,p2,... (rotation aléatoire). Options : LEBONCOIN_IMPERSONATE, LEBONCOIN_DATADOME_COOKIE.
  3. ✅ Source leboncoin_apify (la plus fiable, recommandĂ©e) : acteur Apify fatihtahta/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_months oĂč 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured