DéveloppeursOutils MCP et scopes

Outils MCP et scopes

Les 22 outils qu'un client peut recevoir, les 11 scopes qui les ouvrent, et les droits Shopify que chacun exige.

22 outils répartis sur 11 scopes. Les deux chiffres sont dérivés du catalogue de scopes du dépôt : cette page ne peut donc pas s'écarter de ce qu'un client peut réellement recevoir.

Le catalogue comprend aussi des outils réservés à l'équipe BoostEcom. Ils sont retirés de votre écran de consentement et revérifient le rôle de l'appelant à chaque appel : aucune autorisation de cette page n'en ouvre un, et ils ne sont pas comptés ci-dessus.

Le catalogue

ScopeFamilleOutilsDroit Shopify requis
boostecom:store.readrelaygetShopInfo, getStoreContext, introspectSchemaaucun
boostecom:catalog.readrelaylistProducts, getProductread_products ou write_products
boostecom:orders.readrelaylistOrdersread_orders ou write_orders
boostecom:content.readrelaylistPagesread_content ou write_content
boostecom:metadata.readrelaygetMetafields, listMetaobjectDefinitions, listMetaobjectsaucun (Shopify contrôle à chaque requête)
boostecom:themes.readrelaylistThemes, getTheme, runAuditread_themes, write_themes ou write_theme_code
boostecom:analytics.readrelayrunShopifyQLread_analytics ou read_reports
boostecom:graphql.readrelayshopifyAdminGraphQLaucun
boostecom:studio.readnativegetStudioSection, getStudioProduction, listStudioGenerations, getStudioPricingaucun (voir plus bas)
boostecom:intelligence.readnativegetStoreIntelligenceaucun (voir plus bas)
boostecom:docs.readpublicsearchDocs, getDocaucun (rien à accorder)

Pourquoi boostecom:metadata.read n'exige aucun droit Shopify

L'accès à un métachamp dépend de la ressource à laquelle il est rattaché : un métachamp de produit exige read_products, celui d'une commande read_orders. Aucun droit unique ne couvre toute la famille, et en imposer un ici ferait refuser une Custom App parfaitement capable de répondre. C'est donc Shopify qui refuse, requête par requête : une boutique dont l'app n'a pas read_metaobjects reçoit, via listMetaobjects, le refus de Shopify avec sa raison, au lieu d'un outil qui n'apparaît jamais.

N'importe lequel des droits Shopify listés suffit pour une ligne. Un tiret signifie que Shopify n'a pas son mot à dire : soit l'outil n'exige aucun droit particulier, soit Shopify contrôle à chaque requête.

Les trois familles

Rien de cosmétique : la famille décide à qui un outil répond.

relay atteint Shopify par le pont. Un bearer statique bst_mcp_ la satisfait, parce que la clé est limitée à la boutique et que la détenir vaut autorisation.

native atteint un système qui appartient à BoostEcom. Elle exige un appelant identifié : une clé statique ne la satisfait donc jamais. La raison mérite d'être dite clairement : getStudioSection protège une ressource dont la permission dépend d'une ligne OrganizationMember. Sans utilisateur, il n'y a personne à vérifier, et une permission invérifiable doit refuser, jamais laisser passer.

public atteint quelque chose de déjà lisible sans session. La famille en elle-même admettrait une clé statique, puisqu'il n'y a aucune permission à vérifier : searchDocs renvoie ce que /docs sert à un inconnu. Une clé statique n'obtient pourtant pas ces outils aujourd'hui : elle ne porte aucune chaîne de scopes, donc elle ne couvre que la famille relay, dont boostecom:docs.read ne fait jamais partie. Ces outils atteignent un client par OAuth, une fois que l'utilisateur a approuvé le scope.

Cette dernière famille répond honnêtement à une question évidente : si la documentation est publique, que protège son scope ? Rien. Il permet à un client de refuser les deux outils pour garder une liste d'outils courte, et il les fait figurer sur l'écran de consentement, où vous voyez ce que vous acceptez. Une déclaration d'intention, pas une barrière.

Pourquoi studio.read affiche une colonne Shopify vide

shopify: [] sur un scope native ne veut pas dire « n'exige aucune permission ». Cela veut dire que Shopify n'a pas son mot à dire. Le contrôle repose sur la permission studio.* de l'appelant, vérifiée section par section au moment de l'appel : la même vérification que celle de la génération d'images et de vidéos.

Le scope est proposé à tout utilisateur sur l'écran de consentement, contrairement à un scope relay que la Custom App d'une boutique ne peut pas satisfaire. C'est voulu : un droit Shopify est un plafond infranchissable qui ne bouge qu'en reconnectant l'app, alors qu'une permission Studio est une appartenance qui peut changer dès demain. Refuser le scope au moment du consentement figerait une autorisation de longue durée face à une permission que l'utilisateur obtiendra peut-être bientôt ; la vérification à chaque appel, elle, répond correctement dans les deux cas.

Ce que lisent les quatre outils Studio, et ce qu'aucun ne fait

getStudioSection lit une section des données de production créative : concepts, qc ou cockpit. Chaque section a sa propre permission, et une section que vous n'avez pas le droit de lire répond comme si elle n'existait pas. Seule la première s'ouvre par une permission studio.* qu'un marchand peut détenir ; les deux autres relèvent de permissions internes à BoostEcom (l'interface opérateur qui les affichait a été retirée le 2026-10-08) et répondent donc comme absentes.

getStudioProduction lit le tableau de production de la boutique à laquelle la connexion est limitée : ce qui est en cours, les rendus, les concepts et l'économie. Un bloc que vous n'avez pas le droit de lire est absent, jamais désactivé, et la réponse porte un deniedCount au lieu de laisser croire que la marque ne produit rien.

listStudioGenerations lit le journal des générations : chaque rendu demandé par la boutique, depuis le chat ou un Workflow (voir Images et vidéos), son état réel, son modèle et l'URL de son artefact. Il ne renvoie jamais de pourcentage, parce que le fournisseur ne publie aucune progression et qu'une barre inventée vaut moins qu'un état. Les champs de coût (chargedCostUsd, estimatedCostUsd) exigent une seconde permission, studio.economics.read, et sont retirés de la réponse sans elle, plutôt que mis à zéro : un zéro se lirait « gratuit ».

getStudioPricing indique ce que coûte une génération avant que vous la demandiez, par mode du composeur, en dollars US. La grille tarifaire est choisie côté serveur à partir de l'organisation à laquelle appartient la boutique, jamais à partir d'un argument.

Aucun n'écrit, et aucun outil MCP ne lance de génération. Une génération coûte de l'argent : la placer derrière une autorisation durable qu'un agent peut exercer sans surveillance est une décision qui a un prix, pas un ajout fait en passant. Tant que cette décision n'est pas prise, il n'existe pas de scope studio.write, et un scope qu'on ne peut pas exercer n'a rien à faire sur un écran de consentement.

Le scope hérité mcp

Les clients qui ont donné leur consentement avant l'existence du catalogue détiennent un seul scope, mcp. Il couvre la famille relay, et elle seule, pour toujours : il a été accordé quand le catalogue se limitait au pont Shopify, il ne peut donc pas signifier autre chose. Il n'atteint ni les outils native, ni les outils public.

Lire la documentation depuis un client

searchDocs prend une question en langage courant et renvoie les passages qui y répondent, chacun avec un lien direct vers la section exacte. Les ancres viennent de la fonction même qui les affiche : elles mènent donc au bon endroit. getDoc prend un slug issu de ces résultats et renvoie la page complète.

Ces outils existent pour une raison : un agent à qui l'on demande comment fonctionne la période de séquestre peut soit lire la page qui l'explique, soit la deviner, et c'est en devinant qu'une mauvaise réponse assurée finit chez un marchand.

Une page qu'un admin a retirée du CMS répond « introuvable », comme un slug qui n'a jamais existé : l'outil n'est donc pas un index de ce qui a été publié un jour.

Ce que BoostEcom sait de votre propre boutique

getStoreIntelligence indique, pour la boutique à laquelle la connexion est limitée, ce que la plateforme a observé sur son domaine : trafic, économie déduite, catalogue, stack technique, créas publicitaires, rythme des avis, audience sociale, marque et maturité agentique.

Chaque champ porte son unit, et ce n'est pas décoratif. visitsChange est un ratio signé ; momGrowth s'exprime en points. Les deux s'affichent « −19,9 % », et confondre l'un avec l'autre passe inaperçu. Un champ que la plateforme n'a pas observé garde sa place avec la valeur null et, quand la fiche l'indique, une raison d'absence : une absence est une information, jamais un chiffre qu'on fait disparaître en douce.

Restreignez la réponse avec sections (traffic, economics, catalog, stack, ads, reviews, audience, brand, agentic) ; omettez ce paramètre pour tout obtenir. Une boutique encore sans fiche répond observed: false plutôt qu'une fiche vide, pour que « rien d'observé » ne soit jamais confondu avec « zéro ».

L'outil lit la même fiche, avec le même lecteur, que le panneau Store details de votre tableau de bord et que l'extension navigateur. Une question, un chiffre, quel que soit celui qui demande.

Comme la fiche appartient à la boutique, la réponse dépend de qui la demande : le relais a déjà vérifié, à l'entrée, que vous faites partie de l'organisation qui la détient. Une boutique dont la fiche est privée répond intégralement à son propre marchand.

Passerelle GraphQL

shopifyAdminGraphQL est une passerelle vers l'API Admin GraphQL de Shopify, associée à introspectSchema pour découvrir le schéma. Le modèle de permissions propre à Shopify s'applique à chaque requête : le pont ne l'élargit pas.

Format des scopes dans les échanges

Les scopes circulent sous forme de chaîne séparée par des espaces ou des virgules. La liste annoncée dans les métadonnées du serveur d'autorisation est le scope hérité plus les 12 scopes du catalogue : les 11 ci-dessus, et 1 réservé à l'équipe BoostEcom.