chineur
chineur
Chiffrage d'un projet entier au meilleur prix livraison comprise, neuf et occasion séparés, avec un plan de commande groupé qui minimise le total réellement payé.
Le moins cher article par article n'est pas la bonne réponse : 10 articles chez 10 marchands, c'est 10 frais de port. Le moteur de panier groupe les achats chez 2 ou 3 marchands, seuils de franco compris, et affiche l'écart avec ce total naïf.
Installation
python -m venv .venv && ./.venv/bin/pip install -e .
./.venv/bin/pytest # 74 tests hors ligne, aucun réseauPython 3.11 ou plus. Le projet tourne sans aucune clé : LeDénicheur, AliExpress et
Leboncoin ne demandent rien. Les sources à clé (eBay, Mouser) restent simplement éteintes,
et list_sources() le dit.
Related MCP server: aws-calculator-assistant
Clés
Aucun secret n'est lu dans un fichier versionné. bin/chineur-mcp.sh charge un .env
local s'il existe (ignoré par git), sinon il prend l'environnement tel quel, ce qui permet
de les injecter depuis un gestionnaire de secrets par simple substitution, la valeur ne
transitant alors que par l'environnement du processus :
export EBAY_CERT_ID=$(votre-cli-de-coffre get password 'eBay - API Browse')Variable | Rôle | Sans elle |
| keyset eBay Browse | source eBay éteinte |
| clé Mouser Search API | source Mouser éteinte |
| recours navigateur sur mur anti-bot | recours éteint, le reste fonctionne |
| répertoire d'état (cache, quotas, cookies, journal) |
|
Utilisation
Exposé en MCP stdio (bin/chineur-mcp.sh), trois outils :
Outil | Rôle |
| chiffre une liste complète en un seul appel |
| le cas à un seul article, en |
| état, quota horaire restant et coupure en cours de chaque source |
Chaque article accepte une quantité ou un plafond : "LD2410C x3", "ESP32-S3 <=12€".
En ligne de commande :
python -c "
import asyncio; from chineur.models import Project
from chineur.search import Orchestrator; from chineur.report import render
async def m():
o = Orchestrator(); print(render(await o.run(Project.build(['LD2410C x2','BME280'])), failures=o.failures))
asyncio.run(m())"Sources et ce qu'elles valent
Source | Volet | Port | Remarque |
LeDénicheur | neuf + occasion | exact | agrégateur : apporte Amazon, Cdiscount, Fnac, Rue du Commerce, Back Market, Rakuten en une requête |
AliExpress | neuf | estimé | seule source réaliste pour les modules chinois de niche |
Leboncoin | occasion | estimé | 10 recherches/heure maximum, non négociable |
eBay | neuf + occasion | exact | API Browse officielle, active depuis le 2026-08-06 |
Mouser | neuf | estimé | distributeur pro, API officielle. Couvre ce qu'AliExpress rate (étain, tresse, résistances, transistors, connectique). Inutile sur les modules chinois : absent, ou 3 à 5x le prix |
Limites connues, mesurées le 2026-08-05 et non contournables sans Playwright (V2) :
AliExpress ne donne ni le vendeur ni le port sur la page de recherche, et la fiche produit en HTTP simple est vide. Le groupage se fait donc au niveau de la plateforme, avec son seuil de franco. Après plusieurs requêtes rapprochées, AliExpress répond 200 avec une page de 2 Ko : c'est détecté et traité comme un blocage, pas comme une absence d'offre.
Le budget AliExpress est d'environ 6 requêtes par IP fraîche, mesuré le 2026-08-10 après 46 h sans aucune sollicitation : 6 articles servis (133 offres), blocage au 7e, FlareSolverr mis au mur lui aussi. Une liste de 17 articles ne peut donc pas être chiffrée en une fois par scraping, quelle que soit l'attente respectée. C'est la limite structurelle qui justifie l'API affiliée officielle (portals.aliexpress.com), et non un réglage de patience à trouver.
En occasion, le prix est indicatif. Les annonces Leboncoin sont du texte libre : un résultat peut être un lot, une pièce cassée ou un accessoire. Neuf et occasion ne sont jamais fusionnés en un prix unique.
Le port est marqué
~quand il est estimé (tableshipping.py) et?quand il est inconnu. Un total contenant une estimation est signalé comme tel.
Pertinence : le vrai facteur limitant
Mesuré le 2026-08-08 sur la liste type réelle (17 articles, composants) : les « introuvables » ne venaient pas d'un manque de sources mais du libellé. Deux causes distinctes, séparées en comptant les titres bruts rendus par eBay avant filtrage.
La requête est trop longue. « etain soudure 60/40 flux 0.8mm » fait renvoyer 0 résultat
par eBay ; « etain soudure » en renvoie 11. Chaque mot descriptif ajouté rétrécit le
résultat jusqu'au vide. D'où reduced_query et la seconde chance de guarded_search :
quand une source ne rend rien, on retente une fois sur un libellé réduit aux références
et aux deux premiers mots porteurs, les qualifiants jetés. Une requête de plus uniquement en
cas d'échec, et jamais sur le dernier crédit du quota.
Le filtre jetait du bon. « cables dupont assortiment » contre « Câble Dupont …
Assortiment 5 à 100pcs » tombait à 0.67 pour un seuil de 0.70 : le score ne comparait que
par inclusion de chaîne, donc le pluriel cassait tout. _apparie rapproche désormais sur le
préfixe commun (60 % du mot), réservé aux mots d'au moins 4 lettres — jamais aux nombres
ni aux références courtes, pour que « 2410 » et « 2420 » restent deux capteurs différents.
Résultat sur la même liste : eBay passe de 10 à 14 articles couverts sur 17, articles sans aucune offre de 5 à 3. Restent trois vrais introuvables, à toutes les sources : la plaque pastillée, le Diese 2201M et la Sugon 8620DX.
Le prix à payer, et il est réel. Une recherche élargie répond à une question plus large que celle posée : « ESP32-WROOM-32 DevKit 38 broches » élargi en « esp32 wroom 32 » remonte un modèle 30 broches. Toute offre issue d'un élargissement porte donc la réserve « recherche élargie à « … » », qui doit rester visible jusqu'à l'affichage.
Recours navigateur (FlareSolverr)
Le point faible du projet : AliExpress est la seule source des modules chinois, et elle se
fait bloquer au bout de 5 à 9 recherches. Le README annonçait ce trou comme « non
contournable sans Playwright (V2) ». Il l'est, sans dépendance supplémentaire côté projet :
une instance FlareSolverr pilote un vrai Chrome, exécute le JavaScript et porte une
empreinte de navigateur complète. Elle se déclare par FLARESOLVERR_URL ; non renseignée,
le recours est simplement éteint.
Mesuré le 2026-08-08, alors que le connecteur direct était bloqué et son disjoncteur ouvert :
fr.aliexpress.com/w/wholesale-LD2410C.html rend HTTP 200, 832 Ko, aucun marqueur anti-bot,
et le parseur HTML existant y décode 60 articles avec prix en EUR. Aucune modification du
parsing n'a été nécessaire.
Branchement dans AliExpress._items : sur mur anti-bot ou page tronquée, on tente le
recours avant de lever Blocked. Points de conception :
Recours, pas régime. Chaque appel démarre un Chrome : c'est lent et lourd. On n'y passe que sur un blocage avéré.
Noneet pas[]quand le recours ne donne rien. Une liste vide passerait pour « aucun résultat », le disjoncteur ne s'ouvrirait pas, et le connecteur retaperait la source bloquée à l'article suivant en aggravant le bridage.Jamais bloquant.
flaresolverr.fetchne lève pas : une panne du solveur masquerait la vraie cause derrière un incident d'infrastructure.FLARESOLVERR_URL=l'éteint.Abandon après 2 échecs consécutifs. Voir la limite ci-dessous : sans ça, chaque article suivant paierait encore des dizaines de secondes d'attente pour rien.
Sa limite, mesurée le 2026-08-08. Le recours n'est pas un contournement, c'est un
second budget. Sur huit recherches AliExpress enchaînées : six servies à 60 articles
chacune en 4 à 6 s, la septième en erreur 500 après 101 s d'attente, la huitième renvoyant
le mur anti-bot (208 Ko, marqueur RGV587). L'IP de sortie ne change pas, donc le même mur
finit par tomber. Deux conséquences dans le code : maxTimeout ramené de 90 à 45 s, et
un mur rendu en HTTP 200 compte comme un échec, sinon le compteur d'abandon ne se
déclencherait jamais.
En pratique le budget AliExpress passe donc d'environ 9 recherches à environ 15, avec 60 articles par page au lieu de 20. C'est un gain net, ce n'est pas l'illimité.
Garde-fous anti-ban
L'IP de sortie est unique et résidentielle : un ban la coupe entièrement. Tout le module est écrit pour ne jamais en arriver là.
Quotas horaires persistés en SQLite (
var/chineur.db) : Leboncoin 10/h, LeDénicheur 30/h, AliExpress 20/h, eBay 200/h, Mouser 60/h (quotas API, aucun risque IP).Espacement sérialisé par source, pas un simple
sleep: l'orchestrateur lançant tous les articles en parallèle, des délais concurrents s'écouleraient en même temps et les requêtes partiraient quand même en rafale. Chaque départ attend le précédent.Disjoncteur sur 403 / captcha / page tronquée : 1 h, 2 h pour AliExpress, dont la pénalité persiste au-delà de la rafale qui l'a déclenchée.
Le blocage AliExpress n'est ni un quota ni une question de cadence. Trois recettes du 2026-08-06, libellés jamais mis en cache :
espacement
transport
servies avant blocage
6-12 s
requêtes nues
5 (blocage à 46 s)
6-12 s
session à cookies
6 (blocage à 56 s)
45-60 s
session à cookies
2 (blocage à 108 s)
2,5 s
session à cookies, endpoint JSON
9 (blocage à 30 s)
Ralentir dégrade le rendement, donc la cadence n'est pas le levier : le meilleur rendement s'obtient en allant vite. Le blocage dure ~40 min, mesuré deux fois, et se signale par
FAIL_SYS_USER_VALIDATE/RGV587_ERROR::SM, l'anti-bot d'Alibaba qui exige une validation.Les articles sont lus sur l'endpoint interne
POST www.aliexpress.com/fn/search-pc/index(celui que la page de recherche appelle elle-même), charge utile de formemods, depuis une session déjà ouverte sur l'accueil. Il rend exactement les mêmes objets article que la page HTML, en.data.result.mods.itemList.content, pour 390 Ko au lieu de 600. Piège : plusieurs blocs de la réponse portent une clécontent, celui des filtres de recherche arrive avantitemList. La page HTML reste en repli automatique, mais uniquement si la réponse n'a plus la forme attendue : sur un mur anti-bot, retenter en HTML depuis la même IP ne ferait que gaspiller une requête.Session persistante (
transport.Session) conservée pour AliExpress : page d'accueil visitée une fois, cookies rejoués ensuite, pot dansvar/cookies/pour survivre à un redémarrage, jeté dès qu'une page revient tronquée. Aucun gain mesuré sur le blocage, gardée parce qu'elle rapproche le trafic de celui d'un navigateur.Piste non tranchée : si l'endpoint interne se referme un jour, sous-traiter la source à un service hébergé (omkar.cloud, 5 000 requêtes/mois gratuites), au prix d'un tiers qui voit nos recherches.
Cache consulté avant le rate limiter : rechiffrer un projet ne retape rien. TTL 1 h par défaut, mais jamais plus court que la coupure du disjoncteur (
Connector.effective_ttl, 6 h pour AliExpress). Sans ce plancher, un projet plus large que le budget d'une source ne peut pas se terminer : la relance d'après-coupure retrouve un cache vide, refait les mêmes premières recherches, rebrûle le budget et se fait rebloquer, indéfiniment. Sauf eBay, exclu du cache pour rester conforme à l'exemption (voir plus bas).Un projet dépassant le quota Leboncoin est traité par ordre d'enjeu décroissant, et les articles non traités sont nommés dans la restitution.
Économie de tokens
Le calcul reste en Python, seul le verdict remonte : sortie en texte tabulaire dense, une
meilleure offre neuve et une occasion par article, titres tronqués, URL nettoyées, notes
regroupées, diagnostics dans var/chineur.log. Mesuré : 10 articles ≈ 650 tokens.
Tests
pytest # 74 tests hors ligne, aucun réseau
pytest -m network # 5 tests d'intégration réels (consomment du quota)Le moteur de panier est entièrement testable hors ligne, y compris ses cas piégeux (seuil de franco déclenché par le groupage, marchand unique, article sans offre, égalités). La propriété « total optimisé ≤ total naïf » est vérifiée sur 50 jeux d'offres aléatoires.
Mouser
Une seule variable : MOUSER_API_KEY. Clé gratuite en self-service sur mouser.com/api-hub
(onglet Search API).
La clé doit être créée depuis mouser.fr. La recherche par mot-clé n'accepte aucun
paramètre de devise (vérifié dans le swagger api.mouser.com/api/docs/V1) : la devise est
celle du site d'inscription. Une clé créée sur mouser.com renvoie des dollars, que le
connecteur écarte plutôt que de les convertir à un taux inventé — la source paraîtrait
simplement vide.
Quotas annoncés par Mouser : 50 pièces par appel, 30 appels/minute, 1 000 appels/jour.
D'où limit_per_hour = 60 et 2 s d'espacement : ce n'est pas de l'anti-ban, c'est le
respect du quota.
Trois choix de fond :
mouserPaysCustomsAndDuties: true— Mouser expédie du Texas. Sans ce drapeau, les droits de douane arrivent après coup et un prix « moins cher » sur le papier devient plus cher à la livraison.searchOptions: InStock— une référence à 12 semaines de délai n'a rien à faire dans une comparaison de prix pour un projet en cours.Paliers de prix suivis à la quantité demandée. Retenir le palier 1 surestime tout achat groupé de composants passifs.
Les deux pièges qui fausseraient une comparaison, tous deux signalés en réserve sur l'offre : le minimum de commande (0,10 € l'unité par sachet de 100, soit 10 € réels à la caisse) et le format de prix (« 0,096 € » est un prix à trois décimales, « $1,250 » vaut mille deux cent cinquante — un parseur naïf se trompe d'un facteur mille dans les deux sens).
Port : non vérifié. Le franco de 50 € HT et les ~20 € en dessous sont recoupés sur le
web (2026-08-07), pas sur une facture. Ils vivent donc dans shipping.py et ressortent en
ESTIMATED, jamais en fait établi. À corriger dès la première commande réelle : sous le
franco, le port écrase le gain, et c'est ce seuil qui décide si la source sert à quelque chose.
eBay
EBAY_APP_ID (App ID) et EBAY_CERT_ID (Cert ID), pour un keyset Production — le seul
exploitable. Un keyset Sandbox se branche avec EBAY_ENV=sandbox, qui bascule sur
api.sandbox.ebay.com. En sandbox le connecteur reste éteint : l'inventaire est factice, les prix entreraient dans le panier sans que
rien ne le signale. EBAY_SANDBOX_OK=1 le rallume pour tester la plomberie uniquement.
Vérifié le 2026-08-06 sur un keyset Production : jeton client_credentials obtenu,
recherches réelles (29 offres sur « cable hdmi 2.1 2m », port exact lu dans
shippingOptions).
L'état de l'article se lit sur conditionId, jamais sur condition : ce dernier est
traduit par eBay (« Neuf », « Occasion », « Ouvert (jamais utilisé) » sur EBAY_FR), et la
table à clés anglaises d'origine ne matchait rien, donc tout ressortait en occasion.
Les articles 7000 (« pour pièces ») sont écartés : à 3 €, un article cassé gagnerait la
comparaison sans que rien ne le signale.
Conformité (« Your Keyset is currently disabled »). eBay n'active un keyset Production
qu'après abonnement aux notifications de suppression de compte, ou exemption. Le projet
prend l'exemption « je ne conserve pas de données eBay », et le code la rend littéralement
vraie : EBay.cacheable = False, donc aucune réponse eBay n'est écrite dans
var/chineur.db (elles contiennent des pseudos vendeurs). Un test le verrouille. Si un
jour on remet eBay en cache, l'exemption devient fausse : il faudra héberger l'endpoint de
notification à la place.
Licence
MIT, voir LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityBmaintenanceMCP server for finding, comparing, and ranking the cheapest real offers across eBay, Amazon, Craigslist, OfferUp, and Google Shopping, with tax estimation and exact-model filtering.6MIT
- AlicenseNot gradedqualityBmaintenanceBuild shareable AWS Pricing Calculator estimates programmatically via MCP tools, designed for creating MAP funding estimates from customer infrastructure descriptions.8MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying and comparing prices, availability, ratings, reviews, and seller details from major Russian and Chinese marketplaces (Wildberries, Ozon, Yandex Market, and others) without requiring API keys, via a unified MCP interface.3MIT

BizNetAI MCP Serverofficial
AlicenseNot gradedqualityBmaintenanceA hosted MCP server that routes natural-language shopping queries to independent merchant storefronts, returning normalized product and merchant results for AI agents and shopping assistants.MIT
Related MCP Connectors
Hosted no-auth MCP for exact-spec packaging search, live price, stock, cart handoff, and no-match.
Real, buyable product and service offers — live pricing and trackable links for any MCP agent.
Routes natural-language shopping queries to merchant storefronts, returns normalized results.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/GRSMael/chineur'
If you have feedback or need assistance with the MCP directory API, please join our Discord server