Intelligence MCP Exposure — Roadmap
Auth (2026-08-20). Les cles bei_ sont desormais verifiees sur les DEUX surfaces — MCP et REST: via un resolveur unique. Voir « Ce qui tourne reellement » sous Quotas. Status (2026-05-22, numerotation corrigee le…
Auth (2026-08-20). Les cles
bei_sont desormais verifiees sur les DEUX surfaces — MCP et REST: via un resolveur unique. Voir « Ce qui tourne reellement » sous Quotas.Status (2026-05-22, numerotation corrigee le 2026-09). Le serveur vit dans
src/app/api/mcp/intelligence/route.ts, pas dans le module propose plus bas. Ce qui tourne : JSON-RPC + SSE transport, real per-orgIntelligenceApiKeybearer auth (replacing the earlier stub), 12 read tools live, releve dansTOOLS(les dix premiers le 20 aout 2026) :searchStoreIntelligence,listKnownStores,searchSimilarStores,getTopStores,inspectDomain,getStoreGraph,predictStoreTrajectory,findEmergingNiches,getWinningAngles,getSupplierIntel, puislist_watched_storesetstore_changes(octobre 2026, voir « Surface agents » plus bas). (La doc disait 5 : les cinq derniers ont ete ajoutes sans que cette ligne suive.) Issuance UI at/[orgSlug]/~/settings/api-keys. Restent absents : write tools, un vrai flow OAuth avec refresh, et les notificationstools/listChangedsur un pub/sub reel.Le numero de phase ne veut rien dire pour ce serveur, et cette ligne le dit plutot que de choisir : ce doc annoncait « Phase 3 shipped », l'en-tete de la route disait « Phase 1 transport » et le manifeste
GETrendstatus: "phase_2_runtime". Ce qui fait foi est la liste de capacites ci-dessus.
Why
BoostEcom Intelligence (/intelligence) already exposes:
- A web UI for browsing the canonical record graph (rankings + detail pages)
- A REST API mirror (
/api/intelligence/top/[category],/api/intelligence/inspect/[tool]) - A marketplace listing pointing to those surfaces (
/marketplace/mcp/boostecom-intelligence)
The missing piece is a real MCP server so any MCP-aware agent
(Claude desktop/code, Cursor, Continue, Windsurf, Zed, ChatGPT desktop,
custom bots speaking stdio/HTTP/SSE) can call the Intelligence tools
the same way they call the existing Shopify Admin MCP at
src/features/shopify/mcp/.
Scope of the follow-up
Tools to expose
| Tool | Mirrors REST endpoint | Notes |
|---|---|---|
listCategories | GET /api/intelligence/top | Index — agent self-discovery. |
topStores | GET /api/intelligence/top/top-stores | Wraps getTopItems("top-stores", …). |
topAds | GET /api/intelligence/top/top-ads | |
topEmails | GET /api/intelligence/top/top-emails | |
topAdvertorials | GET /api/intelligence/top/top-advertorials | |
topProductPages | GET /api/intelligence/top/top-product-pages | |
topSalesPages | GET /api/intelligence/top/top-sales-pages | |
topCartPages | GET /api/intelligence/top/top-cart-pages | |
topSections | GET /api/intelligence/top/top-sections | |
topBlogs | GET /api/intelligence/top/top-blogs | |
topThemes | GET /api/intelligence/top/top-themes | |
topApps | GET /api/intelligence/top/top-apps | |
topMarkets | GET /api/intelligence/top/top-markets | |
topReviewsVendors | GET /api/intelligence/top/top-reviews-vendors | |
topPopups | GET /api/intelligence/top/top-popups | |
topSocial | GET /api/intelligence/top/top-social | |
inspectTheme | POST /api/intelligence/inspect/theme | One-shot probe on a single domain. |
inspectApps | POST /api/intelligence/inspect/apps | |
inspectAds | POST /api/intelligence/inspect/ads | |
inspectEmails | POST /api/intelligence/inspect/emails | |
searchCanonical | (no public REST equivalent yet) | Power-tool — fetch the full canonical record for a domain. Auth-gated. |
Transport
Livre le 5 septembre 2026 (
integrations/0230). Le dispatcher JSON-RPC ecrit a la main a ete remplace parMcpServer+WebStandardStreamableHTTPServerTransportdu SDK officiel, sans etat (aucunMcp-Session-Id). Ce qui ne marchait pas avant : un client conforme envoie toujoursAccept: application/json, text/event-stream, et l'ancienne route lisait cet en-tete comme « streame-moi », donc chaquetools/callrepondait des evenementstool_start/donequi ne sont pas des messages JSON-RPC ;notifications/initialized— le deuxieme message de tout handshake — recevait-32601; et la version annoncee etait2024-11-05. Le produit ne fonctionnait qu'avec un client maison.Le manifeste a demenage :
GET /api/mcp/intelligencesert desormais le transport (405 sur un serveur sans etat), et le manifeste de decouverte est sur/api/mcp/intelligence/manifest.llms.txtet la fiche marketplace nomment ce chemin.
- HTTP — reuse the pattern at
src/app/api/mcp/[storeId]/route.tsand itsbuild-server.ts. Mount at/api/mcp/intelligenceso external clients can declare the endpoint with their preferred client. - stdio — planned, nothing on disk: wrap the same handler module for desktop clients that prefer stdio (Claude desktop today).
- Reuse the OAuth / API-key gating in
src/app/api/mcp/[storeId]/auth.tsandsrc/lib/security/mcp-scopes.ts.
Ces trois lignes ont nomme, jusqu'en septembre 2026, trois fichiers qui n'ont jamais existe :
src/features/shopify/mcp/http.ts,src/features/shopify/mcp/security.tsetsrc/features/intelligence/mcp/stdio.ts. Le serveur MCP vit soussrc/app/api/mcp/, etsrc/features/shopify/mcp/ne contient qu'un sous-repertoireshopify/(le client Admin GraphQL). « Reuse the pattern at X » sur un X inexistant coute plus qu'une phrase fausse : c'est une instruction d'implementation qui envoie lire un fichier vide.
Quotas
| Audience | Throughput | Auth |
|---|---|---|
| Anonymous IP | 60 reads / min, 30 inspects / min | None (matches REST today) |
| Free account | 600 reads / min, 300 inspects / min | API key in Authorization |
| Paid plan | 6000 reads / min, 3000 inspects / min | API key + plan check |
| Enterprise | Negotiated | API key + signed contract |
Ce qui tourne reellement (20 aout 2026)
Le tableau ci-dessus est la cible ; voici l'etat livre, pour qu'on n'ait pas a lire le code pour repondre a « une cle sert a quoi ? ».
| Surface | Sans cle | Avec cle bei_ |
|---|---|---|
/api/mcp/intelligence (Streamable HTTP, SDK officiel) | 60 req/min par IP | 6000 req/min par organisation |
REST /api/intelligence/* (16 routes gardees par guardIntelligenceRoute) | plafond propre a la route (20 a 120 req/min) par IP | le meme plafond x10, par organisation |
Trois proprietes tiennent desormais sur les deux surfaces, parce qu'elles
partagent le meme resolveur (lib/security/intelligence-api-key.ts) :
- Une cle revoquee est refusee. Avant, le REST ignorait purement les cles
et le MCP retrogradait silencieusement en tier public : dans les deux cas,
revoquer une cle fuitee ne changeait rien d'observable. Un token present mais
inconnu ou revoque recoit maintenant un 401 avec
WWW-Authenticate. - Le bucket est l'ORGANISATION, pas l'IP — et pas la cle. Les agents, la
CI et les runtimes serverless partagent des adresses : un porteur de cle
etait puni pour du trafic qui n'etait pas le sien. Le bucket a d'abord ete
caller.keyId, ce qui faisait suivre le quota a la credential : emettre une deuxieme cle doublait le plafond, une dixieme le multipliait par dix, et l'emission est en libre-service depuis le tableau de bord. Depuissecurity-identity/0387les deux surfaces bucketisent surcaller.orgId.IntelligenceApiKey.orgIdest NOT NULL : aucune cle deja emise n'est a reemettre, la seule chose qui change pour un consommateur mono-cle est le NOM du seau, donc une remise a zero de sa fenetre au deploiement. Le plafond de 20 cles actives par org (intelligence/0317) reste, mais il n'est plus qu'une mesure d'hygiene : il ne borne plus un debit. lastUsedAtest ecrit au plus une fois par 5 min, donc le dashboard peut montrer l'usage sans transformer une API de lecture en API d'ecriture.
Pas de gate par plan (ligne « Free » vs « Paid » du tableau cible) : elle
n'existe pas encore, et l'ecrire ici comme si elle existait serait exactement
le genre de doc qui ment. Les lectures publiques restent publiques : c'est un
choix produit (donnees publiques par defaut, llms.txt qui invite les crawlers
IA), pas un oubli. « Hub public » ici designe la POSTURE d'acces, pas une page :
/intelligence et /intelligence/<category> sont des 308 vers
/features/intelligence depuis que le moteur browse/rank vit dans le Hub OS de
la home (intelligence/0240) ; ce sont des regles de next.config.mjs depuis
growth-web/3018, limitees aux quinze slugs du registre. La fiche d'un store a
UNE URL, /intelligence/stores/<domain> (intelligenceStorePath), et c'est
elle que les outils MCP rendent ; les quinze formes /<category>/<domain> y
redirigent pour toujours.
Module layout (propose en 2026-05, jamais construit)
Ce layout n'existe pas : src/features/intelligence/ n'a jamais ete cree. Le
serveur, son catalogue d'outils et son auth vivent dans
src/app/api/mcp/intelligence/route.ts.
Il est garde ici comme trace de la proposition, pas comme carte du code.
src/features/intelligence/mcp/
├── server.ts # MCP server factory (mirrors features/shopify/mcp/shopify/server.ts)
├── tools/ # One file per tool — each wraps an aggregator/inspector call
│ ├── top-stores.ts
│ ├── top-ads.ts
│ ├── …
│ ├── inspect-theme.ts
│ └── search-canonical.ts
├── http.ts # HTTP transport
├── stdio.ts # stdio entry-point
└── security.ts # OAuth/API-key adapter
Acceptance criteria
claude mcp add --transport http boostecom-intelligence https://boostecom.app/api/mcp/intelligenceconnects, lists tools, returns sample data. Le transport est conforme depuisintegrations/0230;src/app/api/mcp/intelligence/route.test.tsjoue le handshake complet (initialize->notifications/initialized->tools/list->tools/call) avec l'en-teteAcceptqu'un vrai client envoie. Reste a le confirmer une fois contre un client reel.- The marketplace listing at
/marketplace/mcp/boostecom-intelligenceis updated with the canonical endpoint URLs. - The TODO in
/llms.txtreferencing this doc is removed. - Rate limits + auth observed in production for one week without alerting incidents.
- An
examples/folder ships with prompt + tool-call samples for Claude, Cursor and Continue.
Out of scope
- Write tools (mutate canonical record / trigger scans): handled separately because they need stricter auth, cost-accounting, and prepay credits.
- Streaming SSE transport — defer until at least one production consumer asks for it.
Owner / timing
- Owner: TBD (likely the Intelligence pod once the REST + UI ship)
- Estimate: 2-3 dev days for the HTTP transport, +1 day for stdio, +1 day for auth/quotas wiring.
- Trigger: at least one of (a) a paying customer asks for the MCP, (b) the REST surface clears 10k req/day stable, (c) a partner integration commits to it.
Surface agents (octobre 2026)
Ce que le serveur dit a un agent, et comment il le dit. Tout vit dans
src/app/api/mcp/intelligence/.
- Regle de lecture.
initializerenvoieinstructions(agent-notes.ts) : null,lockedetunknownne sont pas zero, nommer la couche (L1 / L2 / L4) et la source, une valeur L4 est une estimation, ne jamais inventer. La meme phrase (NULL_NOTE) termine la description de CHAQUE outil ;tool-catalog.test.tsechoue si un outil n'en porte pas. - Outils de suivi (lecture seule).
list_watched_storesetstore_changeslisent la liste de suivi de l'ORGANISATION de la cle (StoreTracker,StoreAnomaly,CatalogDelta) sur les N derniers jours. Ils exigent la porteeread:tracker(keyHasScope: l'anonyme ne la passe pas, contrairement aread:intelligence) et repondentkey_required/insufficient_scopeplutot qu'une liste vide. Un store suivi dont la fiche n'est pas publique est liste avecintelligence.available: false, sans dire pourquoi. Chaque sortie passe par la porte de champs : mouvements d'annonces (tier ads), de promo (commerce) et journal produit par produit (products) sontdetails: nulllocked+required_planen dessous.
- Etat de collecte du trafic. La projection hub (
hubdeinspectDomain, commelookup?rich=1ethub/scan) portetraffic_collection: { state: "measured" | "no_coverage" | "never", checked_at }: l'issue de la derniere collecte qui a reellement atteint la source.no_coveragepermet de dire « la source ne couvre pas ce store » (date),neverseulement « pas encore collecte », jamais zero. Public sur tous les plans, comme la feuille canoniquetraffic.collection(field-gate.ts). Contrat :docs/audits/2026-09-10-spy-ext-coherence.md§D. - Cles. Une cle est emise avec
read:intelligenceseul ;read:trackerse demande par son nom, dans une liste fermee (api-keys/route.ts). Aucune portee d'ecriture ne peut etre stockee. - Quotas. Chaque reponse MCP porte
X-RateLimit-Limit,-Remaining,-Reset(etRetry-Afterau refus). Un lot JSON-RPC de N messages depense N coups, plafonne (limits.ts). - Budget quotidien de fiches completes, MCP compris. Le quota ci-dessus
compte des REQUETES ; un second budget compte les FICHES completes servies,
par organisation et par jour (
DAILY_FULL_READS: free 0, Pro 5 000, Max 20 000 ; alerte de rafale a 500 par heure avec courriel a l'operateur). Il ne s'appliquait qu'aux routes REST du hub (lookup,hub/stores,hub/scan) : une cle payante pouvait donc paginer tout le catalogue par MCP sans jamais l'entamer. Il s'applique maintenant aux deux portes, via la meme fonction de comptage (chargeFullReadsdelib/hub/read-budget.ts) : l'alerte, le courriel et les fenetres glissantes ne sont pas dupliques.- Ce qui compte pour une fiche (
api/mcp/intelligence/read-budget.ts) :searchStoreIntelligenceetinspectDomain(1 chacun),getStoreGraph,predictStoreTrajectory,getSupplierIntel(1 vue payante par magasin), un element degetTopStoresquand le plan ouvre une metrique payante de la categorie (CA, depense pub, valeur du catalogue), un magasin suivi dont le fluxstore_changesporte une charge utile reservee a un palier. Ne comptent PAS : le palier gratuit (il ne lit jamais de fiche complete),listKnownStores,searchSimilarStores,list_watched_stores(domaine, couche, date : l'apercu),findEmergingNichesetgetWinningAngles(pas des fiches de magasin). Le MCP/api/mcp/[storeId]ne lit que le magasin du marchand connecte : hors perimetre. - Identite :
readBudgetIdentity, donc l'ORGANISATION de la cle (une deuxieme cle n'achete pas un deuxieme budget). Ce endpoint ne resout un plan payant que depuis une clebei_; le repli sur l'utilisateur de la session ne servirait qu'a un futur appelant OAuth. - Lot : un compteur par requete HTTP est partage par tous les appels d'outils du lot, donc un lot qui renvoie N fiches en depense N, repartis comme ils viennent ; le quota de requetes (un coup par message) est inchange.
- Budget epuise : ce n'est pas une erreur. Les fiches reviennent en
apercu gratuit avec
access.reason: "daily_read_budget", le resultat porte un blocread_budget(noteREAD_BUDGET_NOTE, dite pour qu'un modele ne lise pas l'apercu comme des zeros) et la reponse l'en-teteX-Intelligence-Read-Budget: exhausted, comme sur le REST. Un classement ou un flux dont le budget tombe a mi-liste est resservi EN ENTIER comme le palier gratuit : tronquer la fin garderait l'ordre paye de la tete. - Panne : Redis injoignable,
rateLimitne leve pas et retombe sur un compteur par instance (durable: false) ; le budget continue de compter, en plus lache, comme sur le REST (limite anti-abus, pas garde de depense). Une exception inattendue de la couche budget ferme vers l'apercu (pas d'erreur d'outil, qui ferait reessayer l'agent).
- Ce qui compte pour une fiche (
/SKILL.md. Document Agent Skills genere (skill-doc.ts) a partir des memes constantes que celles que le limiteur et la porte de champs lisent : il ne peut pas deriver.