story-theme-mcp 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,7 +63,7 @@ Le MCP ne contient pas le thème : au démarrage, il demande à l'espace membre
63
63
  | Livrer | `export_theme` (zip à importer + check-list), `import_theme` (auditer un thème téléchargé d'une boutique) |
64
64
  | Passer en 4.x | `migrate_v3` : une boutique en Story Thème 3.7 ou avant, reconstruite en 4.x avec son contenu (textes, photos, avis, FAQ, produits, couleurs, polices, logo, menus), section par section — ce que la mise à jour de l'espace membre ne sait pas faire |
65
65
  | Vos boutiques (Theme Access) | `list_shops` (et la marche à suivre pour brancher une boutique), `pull_from_shop` (relire le thème de la boutique), `push_to_shop` (écrire le projet dans un thème non publié, sans zip), `update_theme` (mettre à jour le Story Thème dans un thème neuf non publié) — la boutique se branche une fois depuis l'espace membre avec un mot de passe Theme Access, qui n'ouvre que ses thèmes |
66
- | L'appli privée Story Thème | `app_status`, `app_reviews` (import CSV, modération, réponses), `app_ab_tests`, `app_offers` (la remise des offres du thème), `app_discount_codes`, `shops_overview`, `shop_graphql` — sur les boutiques où l'équipe Story Thème a installé l'appli |
66
+ | L'appli Story Thème (Story Theme Apps, gratuite) | `app_status`, `app_reviews` (import CSV, modération, réponses), `app_ab_tests`, `app_offers` (la remise des offres du thème), `app_discount_codes`, `shops_overview`, `shop_graphql` — sur les boutiques où le marchand a installé l'appli (depuis son espace membre) |
67
67
 
68
68
  Prompts prêts à l'emploi : `creer-boutique`, `refaire-une-page`, `auditer-un-theme`. Les guides sont aussi exposés en ressources (`storytheme://guides/<sujet>`).
69
69
 
@@ -74,7 +74,7 @@ Prompts prêts à l'emploi : `creer-boutique`, `refaire-une-page`, `auditer-un-t
74
74
  - **Aucun texte d'exemple livré** : après composition, chaque page est relue avec les règles de `list_texts`, dans les quatorze langues du thème ; un texte d'exemple restant part avec son bloc, ou la section part, et c'est dit. Sans annonce de la marque, la barre d'annonce est masquée plutôt que d'afficher les siennes ; le HTML glissé dans un texte est nettoyé.
75
75
  - **Revue design** : textes d'exemple ou en anglais laissés sur une boutique française, avis d'exemple à remplacer, faux avis et faux chiffres des presets, bouton sans lien, plusieurs `<h1>`, contrastes insuffisants (WCAG AA, boutons compris), polices dépréciées par Shopify (Futura → Jost…), compte à rebours qui redémarre et stock simulé (pratiques commerciales trompeuses), pop-ups multiples, rythme des palettes.
76
76
  - **Jamais le code du thème** : seuls `templates/*.json`, `sections/<groupe>.json` et `config/settings_data.json` sont modifiables, dans un dossier de projet. Le Liquid, le CSS et le JS du thème ne sont jamais touchés, ni en local ni à distance.
77
- - **Écrire dans une boutique reste encadré** : `push_to_shop` n'envoie que les fichiers du projet, refuse une boutique qui ne tourne pas sur un Story Thème de la même version majeure, n'écrit dans le thème publié que des fichiers nommés (`files`, ex. un modèle B de test A/B) avec confirmation explicite, jamais le projet entier, et ne supprime jamais rien à distance. Les thèmes s'ouvrent par Theme Access (mot de passe chiffré dans l'espace membre, révocable par le marchand) ; l'appli privée, seulement sur les boutiques dont le compte a prouvé la propriété. Chaque accès est journalisé.
77
+ - **Écrire dans une boutique reste encadré** : `push_to_shop` n'envoie que les fichiers du projet, refuse une boutique qui ne tourne pas sur un Story Thème de la même version majeure, n'écrit dans le thème publié que des fichiers nommés (`files`, ex. un modèle B de test A/B) avec confirmation explicite, jamais le projet entier, et ne supprime jamais rien à distance. Les thèmes s'ouvrent par Theme Access (mot de passe chiffré dans l'espace membre, révocable par le marchand) ; l'appli, seulement sur les boutiques dont le compte a prouvé la propriété. Chaque accès est journalisé.
78
78
  - **Historique** : chaque écriture est précédée d'un instantané ; `undo` revient en arrière autant de fois que nécessaire.
79
79
  - **Export bloqué** tant qu'une erreur bloquante reste ; signalé « pas prêt à publier » tant qu'un point 🔴 reste.
80
80
 
@@ -106,7 +106,7 @@ Prompts prêts à l'emploi : `creer-boutique`, `refaire-une-page`, `auditer-un-t
106
106
 
107
107
  ## Limites
108
108
 
109
- Le MCP ne publie jamais un thème : il écrit dans un thème non publié, le marchand vérifie et publie lui-même. Sans l'appli Story Apps installée sur la boutique, il fabrique seulement un zip à importer. Il ne crée ni produits, ni collections, ni menus, ni images, ni réductions par lui-même : `shop_graphql` le permet quand une boutique est connectée, sinon la check-list les liste. Et il ne remplace pas une vérification visuelle dans l'éditeur Shopify.
109
+ Le MCP ne publie jamais un thème : il écrit dans un thème non publié, le marchand vérifie et publie lui-même. Sans l'appli Story Theme Apps installée sur la boutique, il fabrique seulement un zip à importer. Il ne crée ni produits, ni collections, ni menus, ni images, ni réductions par lui-même : `shop_graphql` le permet quand une boutique est connectée, sinon la check-list les liste. Et il ne remplace pas une vérification visuelle dans l'éditeur Shopify.
110
110
 
111
111
  ## Développement (New Story)
112
112
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "story-theme-mcp",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "Serveur MCP du Story Thème : votre assistant IA connaît le thème Shopify Story par cœur et construit des boutiques propres et professionnelles.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -217,7 +217,7 @@ Formats conseillés :
217
217
  limites: {
218
218
  title: 'Ce que le MCP (V1) ne fait pas',
219
219
  body: `- Il ne publie jamais un thème : il écrit dans un thème NON publié (push_to_shop) ou fabrique un zip à importer (export_theme) ; le marchand vérifie et publie lui-même.
220
- - Sans l'appli Story Apps sur la boutique, il n'a accès à rien d'elle : ni ses produits, ni ses thèmes. Appelez list_shops pour le savoir.
220
+ - Sans l'appli Story Theme Apps sur la boutique, il n'a accès à rien d'elle : ni ses produits, ni ses thèmes. Appelez list_shops pour le savoir.
221
221
  - Il ne crée pas de lui-même produits, collections, menus, pages, réductions ni images : avec une boutique connectée, shop_graphql le permet ; sinon la check-list les liste.
222
222
  - Il ne modifie jamais le code du thème (Liquid, CSS, JS) : seulement les modèles, les groupes de sections et les réglages, comme l'éditeur de thème.
223
223
  - Il ne garantit pas le rendu visuel : prévisualisez toujours dans l'éditeur Shopify avant de publier.`,
package/src/server.js CHANGED
@@ -107,12 +107,12 @@ Si le marchand tourne sur le Story Thème 3.7 ou avant (pull_from_shop le détec
107
107
 
108
108
  **Mise à jour** (boutique branchée déjà en 4.x) : update_theme({ shops }) crée un thème NON publié avec la dernière version du Story Thème et y recopie les modèles, les groupes de sections et les réglages de la boutique. Dites au marchand ce qui a été écarté (sections ou réglages que la nouvelle version n'a plus), et que les textes modifiés dans les fichiers de langue et le code ajouté à la main ne suivent pas. Il prévisualise et publie lui-même. En 3.x : migrate_v3.
109
109
 
110
- **L'appli Story Thème** est privée et gratuite pour les clients du thème 4.0+ : l'équipe Story Thème l'installe boutique par boutique. Elle ajoute les avis clients, les tests A/B, les offres cumulables et récompenses panier, et les codes promo. Sur une boutique branchée où elle est installée, commencez par app_status, puis :
110
+ **L'appli Story Theme Apps** est gratuite : le marchand l'installe lui-même depuis son espace membre (page MCP & Appli). Elle ajoute les avis clients, les tests A/B, les offres cumulables et récompenses panier, et les codes promo. Sur une boutique branchée où elle est installée, commencez par app_status, puis :
111
111
  - app_reviews : importer un export CSV (Judge.me, Loox…), ajouter, modérer, répondre aux avis ;
112
112
  - app_ab_tests : opposer deux modèles de page. Le modèle B doit exister dans le thème PUBLIÉ : composez-le (compose_page, edit_template), puis, avec l'accord du marchand, envoyez CE SEUL fichier : push_to_shop({ shops, theme: <thème publié>, files: ["templates/product.offre-b.json"], confirm: true }) — un modèle en plus ne change aucune page en ligne. Suivez les résultats (14 jours au moins), puis appliquez le gagnant ;
113
113
  - app_offers : les paliers et lots se règlent dans le thème (offres de la fiche produit), l'appli applique la remise au panier : activate la met en place, diagnostic dit pourquoi une offre ne s'applique pas ;
114
114
  - app_discount_codes : créer un code promo cumulable avec les offres.
115
- Les actions irréversibles et celles sur plusieurs boutiques demandent confirm: true : décrivez ce qui va se passer et attendez le oui du marchand. Appli pas installée ? Il la demande depuis son espace membre (page MCP & Appli > « Demander l'appli pour ma boutique ») ; en attendant, dites-lui ce qu'il faudra régler.
115
+ Les actions irréversibles et celles sur plusieurs boutiques demandent confirm: true : décrivez ce qui va se passer et attendez le oui du marchand. Appli pas installée ? Il l'installe depuis son espace membre (page MCP & Appli > « Installer l'appli », ou « Demander l'appli » tant que l'installation en un clic n'est pas ouverte) ; en attendant, dites-lui ce qu'il faudra régler.
116
116
 
117
117
  ## 6. Après la V1
118
118
 
@@ -1649,7 +1649,7 @@ Read the file first (read_file) to get ids.`,
1649
1649
  );
1650
1650
  }
1651
1651
 
1652
- // Boutiques du compte, via l'appli Shopify Story Apps (src/shops/).
1652
+ // Boutiques du compte, via l'appli Shopify Story Theme Apps (src/shops/).
1653
1653
  registerShopTools(server, config, { ctx });
1654
1654
 
1655
1655
  return server;
@@ -6,14 +6,14 @@
6
6
  import { z } from 'zod';
7
7
  import { formatApp } from './format.js';
8
8
 
9
- // Ce qu'il faut dire au marchand quand l'appli manque : il ne peut pas l'installer seul.
10
- // Où le marchand demande l'appli : d'abord son espace membre, l'e-mail en secours.
9
+ // Ce qu'il faut dire au marchand quand l'appli manque : il l'installe lui-même, depuis son espace
10
+ // membre (bouton « Installer l'appli » ; « Demander l'appli » tant que Shopify ne l'a pas validée).
11
11
  export const DEMANDER_APPLI =
12
- "depuis son espace membre, page MCP & Appli > « Demander l'appli pour ma boutique » (https://story-theme.com/mcp) — à défaut, par e-mail à contact@story-theme.com";
12
+ "depuis son espace membre, page MCP & Appli (https://story-theme.com/mcp) : « Installer l'appli », gratuite, en un clic — ou « Demander l'appli » si l'installation en un clic n'y est pas encore ouverte ; à défaut, contact@story-theme.com";
13
13
 
14
- export const APPLI_ABSENTE = `L'appli privée Story Thème n'est pas installée sur cette boutique, ou la boutique n'est pas branchée par Theme Access dans l'espace membre. L'appli ne s'installe pas depuis l'App Store : c'est Story Thème qui l'installe (gratuit pour les clients du Story Thème 4.0+). Dites au marchand de la demander ${DEMANDER_APPLI}, et de brancher sa boutique avec Theme Access (même page). En attendant, ses thèmes restent accessibles : pull_from_shop, push_to_shop, update_theme.`;
14
+ export const APPLI_ABSENTE = `L'appli Story Theme Apps n'est pas installée sur cette boutique, ou la boutique n'est pas branchée par Theme Access dans l'espace membre. Elle est gratuite : dites au marchand de l'installer ${DEMANDER_APPLI}, et de brancher sa boutique avec Theme Access (même page). En attendant, ses thèmes restent accessibles : pull_from_shop, push_to_shop, update_theme.`;
15
15
 
16
- const PREREQUIS = `Nécessite l'appli privée Story Thème installée sur la boutique (installée par Story Thème, pas depuis l'App Store) et la boutique branchée par Theme Access ; sinon, le marchand demande l'appli ${DEMANDER_APPLI}. Story Thème 4.0+ publié et licence active exigés.`;
16
+ const PREREQUIS = `Nécessite l'appli Story Theme Apps (gratuite) installée sur la boutique et la boutique branchée par Theme Access ; sinon, le marchand l'installe ${DEMANDER_APPLI}. Réglage par l'assistant : Story Thème 4.0+ publié et licence active.`;
17
17
 
18
18
  const cibles = z
19
19
  .union([z.string(), z.array(z.string())])
@@ -31,7 +31,7 @@ export function registerAppTools(server, { client, ok, fail }) {
31
31
  const data = await client.app(module, { shops: shops ?? 'all', ...reste });
32
32
  return ok(formatApp(data), data);
33
33
  } catch (e) {
34
- if (/sans Story Apps/.test(e.message)) return fail(`${e.message}\n\n${APPLI_ABSENTE}`);
34
+ if (/sans Story (Theme )?Apps/.test(e.message)) return fail(`${e.message}\n\n${APPLI_ABSENTE}`);
35
35
  return fail(e.message);
36
36
  }
37
37
  };
@@ -40,7 +40,7 @@ export function registerAppTools(server, { client, ok, fail }) {
40
40
  'app_status',
41
41
  {
42
42
  title: "État de l'appli Story Thème",
43
- description: `État des modules de l'appli privée Story Thème sur une ou plusieurs boutiques : thème publié et sa version (mise à jour disponible ?), licence, avis (publiés, à modérer, bloc d'avis présent dans la fiche produit), tests A/B (en cours, intégration « Tests A/B Story » activée dans le thème), offres cumulables (remise automatique active ?), demandes RGPD en attente. À appeler avant de régler l'appli. ${PREREQUIS}`,
43
+ description: `État des modules de l'appli Story Thème sur une ou plusieurs boutiques : thème publié et sa version (mise à jour disponible ?), licence, avis (publiés, à modérer, bloc d'avis présent dans la fiche produit), tests A/B (en cours, intégration « Tests A/B Story » activée dans le thème), offres cumulables (remise automatique active ?), demandes RGPD en attente. À appeler avant de régler l'appli. ${PREREQUIS}`,
44
44
  inputSchema: { shops: cibles },
45
45
  annotations: { readOnlyHint: true, openWorldHint: true },
46
46
  },
@@ -64,7 +64,7 @@ export function registerAppTools(server, { client, ok, fail }) {
64
64
  'app_reviews',
65
65
  {
66
66
  title: 'Avis clients (appli Story Thème)',
67
- description: `Avis clients de l'appli privée Story Thème. Les avis publiés remplissent les étoiles natives du thème (reviews.rating, aussi lues par Google), le bloc d'avis et le mur d'avis. Actions : summary (par défaut : chiffres, produits les plus notés, avis à modérer, réglages) ; list (status all|published|pending|hidden, product, rating, limit, offset) ; add (reviews : jusqu'à 100 avis RÉELS, publish false pour les mettre en modération ; un avis renvoyé n'est pas doublé) ; import_csv (csv : le texte d'un export Judge.me, Loox, Shopify Product Reviews, Ali Reviews ou du modèle Story) ; publish / hide / pending (ids, ou all_pending: true pour tout publier) ; delete (ids, définitif, confirm: true) ; reply (id, reply) ; pin (id, pinned) ; settings (autoPublishMin 0 = tout modérer ou 1-5, allowPhotos, verifiedOnly). N'ajoutez JAMAIS d'avis inventés : uniquement de vrais avis de clients (reçus par e-mail, exportés d'une autre appli). Les e-mails des clients ne sont jamais renvoyés. ${PREREQUIS}`,
67
+ description: `Avis clients de l'appli Story Thème. Les avis publiés remplissent les étoiles natives du thème (reviews.rating, aussi lues par Google), le bloc d'avis et le mur d'avis. Actions : summary (par défaut : chiffres, produits les plus notés, avis à modérer, réglages) ; list (status all|published|pending|hidden, product, rating, limit, offset) ; add (reviews : jusqu'à 100 avis RÉELS, publish false pour les mettre en modération ; un avis renvoyé n'est pas doublé) ; import_csv (csv : le texte d'un export Judge.me, Loox, Shopify Product Reviews, Ali Reviews ou du modèle Story) ; publish / hide / pending (ids, ou all_pending: true pour tout publier) ; delete (ids, définitif, confirm: true) ; reply (id, reply) ; pin (id, pinned) ; settings (autoPublishMin 0 = tout modérer ou 1-5, allowPhotos, verifiedOnly). N'ajoutez JAMAIS d'avis inventés : uniquement de vrais avis de clients (reçus par e-mail, exportés d'une autre appli). Les e-mails des clients ne sont jamais renvoyés. ${PREREQUIS}`,
68
68
  inputSchema: {
69
69
  shops: cibles,
70
70
  action: z.enum(['summary', 'list', 'add', 'import_csv', 'publish', 'hide', 'pending', 'delete', 'reply', 'pin', 'settings']).optional(),
@@ -95,7 +95,7 @@ export function registerAppTools(server, { client, ok, fail }) {
95
95
  'app_ab_tests',
96
96
  {
97
97
  title: 'Tests A/B (appli Story Thème)',
98
- description: `Tests A/B de l'appli privée Story Thème : la moitié des visiteurs (réglable) voit un autre modèle de page, servi par ?view=. Actions : list (par défaut : tests, visiteurs, taux d'ajout au panier et de conversion, verdict en une phrase, jours restants) ; templates (modèles B disponibles dans le thème PUBLIÉ, et si l'intégration « Tests A/B Story » est activée) ; create (template product|collection|index|page, view = suffixe du modèle B, ex. "offre-b" pour templates/product.offre-b.json ; handles : pages visées, toutes par défaut ; split 10-90 ; goal conversion|add_to_cart ; autoStop ; name) ; start / stop (id, winner A|B) ; apply_winner (id, confirm: true : les pages visées passent sur le modèle B) ; delete (id, confirm: true). Le modèle B doit exister dans le thème PUBLIÉ : le composer dans le projet (compose_page / edit_template, ex. templates/product.offre-b.json), puis, après accord explicite du marchand, n'envoyer QUE ce fichier : push_to_shop({ shops, theme: <identifiant du thème publié>, files: ["templates/product.offre-b.json"], confirm: true }) — jamais le projet entier dans le thème publié (un modèle en plus ne change aucune page) ; ou le marchand le crée lui-même dans l'éditeur Shopify (Modèles > Créer un modèle). Puis create. Le marchand active l'intégration « Tests A/B Story » dans l'éditeur de thème (Paramètres du thème > Intégrations d'applis). Conclure après 14 jours au moins. ${PREREQUIS}`,
98
+ description: `Tests A/B de l'appli Story Thème : la moitié des visiteurs (réglable) voit un autre modèle de page, servi par ?view=. Actions : list (par défaut : tests, visiteurs, taux d'ajout au panier et de conversion, verdict en une phrase, jours restants) ; templates (modèles B disponibles dans le thème PUBLIÉ, et si l'intégration « Tests A/B Story » est activée) ; create (template product|collection|index|page, view = suffixe du modèle B, ex. "offre-b" pour templates/product.offre-b.json ; handles : pages visées, toutes par défaut ; split 10-90 ; goal conversion|add_to_cart ; autoStop ; name) ; start / stop (id, winner A|B) ; apply_winner (id, confirm: true : les pages visées passent sur le modèle B) ; delete (id, confirm: true). Le modèle B doit exister dans le thème PUBLIÉ : le composer dans le projet (compose_page / edit_template, ex. templates/product.offre-b.json), puis, après accord explicite du marchand, n'envoyer QUE ce fichier : push_to_shop({ shops, theme: <identifiant du thème publié>, files: ["templates/product.offre-b.json"], confirm: true }) — jamais le projet entier dans le thème publié (un modèle en plus ne change aucune page) ; ou le marchand le crée lui-même dans l'éditeur Shopify (Modèles > Créer un modèle). Puis create. Le marchand active l'intégration « Tests A/B Story » dans l'éditeur de thème (Paramètres du thème > Intégrations d'applis). Conclure après 14 jours au moins. ${PREREQUIS}`,
99
99
  inputSchema: {
100
100
  shops: cibles,
101
101
  action: z.enum(['list', 'templates', 'create', 'start', 'stop', 'apply_winner', 'delete']).optional(),
@@ -119,7 +119,7 @@ export function registerAppTools(server, { client, ok, fail }) {
119
119
  'app_offers',
120
120
  {
121
121
  title: 'Offres cumulables (appli Story Thème)',
122
- description: `Offres cumulables de l'appli privée Story Thème. CE QUI VIT DANS LE THÈME (à régler avec edit_template / push_to_shop) : les offres par paliers (blocs « Offres produit » _offer de la fiche produit : quantité, articles offerts, remise, cadeaux), les bundles (section « Bundle builder », paliers _bundle-tier) et les récompenses du panier (bloc _cart-rewards du tiroir panier : livraison offerte, cadeaux dès un montant). CE QUI VIT DANS L'APPLI : une remise automatique (fonction Shopify « Offres et bundles Story Thème ») qui applique ces offres SANS code et se cumule avec les codes des clients ; elle relit le thème publié à chaque modification. Actions : read (par défaut : ce que le thème règle, état de la remise, désynchronisation, offres qui portent encore un code promo inutile) ; activate (crée la remise automatique, ou la met à jour et la RÉACTIVE si elle a été arrêtée) ; diagnostic (réductions actives qui empêchent le cumul) ; make_combinable (ids facultatif : rend ces réductions cumulables avec les remises produit) ; deactivate (confirm: true : les offres ne s'appliquent plus). Sans activate, les offres du thème s'affichent mais ne remisent rien. ${PREREQUIS}`,
122
+ description: `Offres cumulables de l'appli Story Thème. CE QUI VIT DANS LE THÈME (à régler avec edit_template / push_to_shop) : les offres par paliers (blocs « Offres produit » _offer de la fiche produit : quantité, articles offerts, remise, cadeaux), les bundles (section « Bundle builder », paliers _bundle-tier) et les récompenses du panier (bloc _cart-rewards du tiroir panier : livraison offerte, cadeaux dès un montant). CE QUI VIT DANS L'APPLI : une remise automatique (fonction Shopify « Offres et bundles Story Thème ») qui applique ces offres SANS code et se cumule avec les codes des clients ; elle relit le thème publié à chaque modification. Actions : read (par défaut : ce que le thème règle, état de la remise, désynchronisation, offres qui portent encore un code promo inutile) ; activate (crée la remise automatique, ou la met à jour et la RÉACTIVE si elle a été arrêtée) ; diagnostic (réductions actives qui empêchent le cumul) ; make_combinable (ids facultatif : rend ces réductions cumulables avec les remises produit) ; deactivate (confirm: true : les offres ne s'appliquent plus). Sans activate, les offres du thème s'affichent mais ne remisent rien. ${PREREQUIS}`,
123
123
  inputSchema: {
124
124
  shops: cibles,
125
125
  action: z.enum(['read', 'activate', 'diagnostic', 'make_combinable', 'deactivate']).optional(),
@@ -135,7 +135,7 @@ export function registerAppTools(server, { client, ok, fail }) {
135
135
  'app_discount_codes',
136
136
  {
137
137
  title: 'Codes promo (appli Story Thème)',
138
- description: `Codes promo Shopify créés par l'appli privée Story Thème. Actions : list (par défaut ; query pour filtrer) ; create (code, type percentage|fixed, value : 10 = -10 % ou 10 € de remise ; facultatif : title, minimumSubtotal, startsAt / endsAt AAAA-MM-JJ, usageLimit, oncePerCustomer, products OU collections = handles visés, combinesWith) ; deactivate (id ou code : mis en pause, réactivable dans Shopify). Par défaut un code se cumule avec les remises produit (offres du thème appliquées par l'appli) et la livraison offerte, pas avec les autres codes. Pour les offres par paliers du thème, pas de code : app_offers. ${PREREQUIS}`,
138
+ description: `Codes promo Shopify créés par l'appli Story Thème. Actions : list (par défaut ; query pour filtrer) ; create (code, type percentage|fixed, value : 10 = -10 % ou 10 € de remise ; facultatif : title, minimumSubtotal, startsAt / endsAt AAAA-MM-JJ, usageLimit, oncePerCustomer, products OU collections = handles visés, combinesWith) ; deactivate (id ou code : mis en pause, réactivable dans Shopify). Par défaut un code se cumule avec les remises produit (offres du thème appliquées par l'appli) et la livraison offerte, pas avec les autres codes. Pour les offres par paliers du thème, pas de code : app_offers. ${PREREQUIS}`,
139
139
  inputSchema: {
140
140
  shops: cibles,
141
141
  action: z.enum(['list', 'create', 'deactivate']).optional(),
@@ -1,4 +1,4 @@
1
- // Client de la passerelle multi-boutiques de Story Apps (l'appli Shopify du Story Thème).
1
+ // Client de la passerelle multi-boutiques de Story Theme Apps (l'appli Shopify du Story Thème).
2
2
  // Le jeton est celui du MCP (STORY_MCP_TOKEN) : aucune clé Shopify n'est jamais stockée ici.
3
3
 
4
4
  const DEFAULT_APPS = 'https://apps.story-theme.com';
@@ -24,7 +24,7 @@ export function createShopsClient({ token, base = appsBase(), fetchImpl = global
24
24
  signal: AbortSignal.timeout(30000),
25
25
  });
26
26
  } catch {
27
- throw new ShopsError('Story Apps injoignable. Vérifiez votre connexion, puis réessayez.');
27
+ throw new ShopsError('Story Theme Apps injoignable. Vérifiez votre connexion, puis réessayez.');
28
28
  }
29
29
  const data = await res.json().catch(() => ({}));
30
30
  if (!res.ok) throw new ShopsError(data.error || `Erreur ${res.status}`);
@@ -34,7 +34,7 @@ export function createShopsClient({ token, base = appsBase(), fetchImpl = global
34
34
  list: ({ overview = false } = {}) => appel(`/mcp/shops${overview ? '?overview=1' : ''}`),
35
35
  graphql: ({ shops, query, variables, confirm }) =>
36
36
  appel('/mcp/graphql', { method: 'POST', body: JSON.stringify({ shops, query, variables, confirm }) }),
37
- // Les modules de l'appli privée Story Thème : status, reviews, ab, offers, discounts.
37
+ // Les modules de l'appli Story Thème : status, reviews, ab, offers, discounts.
38
38
  app: (module, corps) => appel(`/mcp/app/${encodeURIComponent(module)}`, { method: 'POST', body: JSON.stringify(corps) }),
39
39
  };
40
40
  }
@@ -135,7 +135,7 @@ export function registerDirectTools(server, config, { ctx, ok, garde }) {
135
135
  ...lignes,
136
136
  '',
137
137
  branchees
138
- ? '● branchée (Theme Access) = ses THÈMES sont accessibles : push_to_shop (lister, écrire, créer), pull_from_shop (relire), update_theme (mise à jour du Story Thème), migrate_v3 (3.x → 4.x). Avec l’appli privée Story Thème installée en plus : app_status, app_reviews, app_ab_tests, app_offers, app_discount_codes. Ses produits, collections, pages et menus passent par le connecteur Shopify officiel du marchand.'
138
+ ? '● branchée (Theme Access) = ses THÈMES sont accessibles : push_to_shop (lister, écrire, créer), pull_from_shop (relire), update_theme (mise à jour du Story Thème), migrate_v3 (3.x → 4.x). Avec l’appli Story Thème installée en plus : app_status, app_reviews, app_ab_tests, app_offers, app_discount_codes. Ses produits, collections, pages et menus passent par le connecteur Shopify officiel du marchand.'
139
139
  : '',
140
140
  // Une seule boutique branchée sur trois, c'est deux marchands qui ignorent encore
141
141
  // que c'est possible : la marche à suivre reste affichée tant qu'il en manque une.
@@ -17,7 +17,7 @@ export function formatShopList(data) {
17
17
  const lignes = [BANDEAU, `Compte : ${data.account?.email || '?'} · ${shops.length} boutique${shops.length > 1 ? 's' : ''} connectée${shops.length > 1 ? 's' : ''}`, ''];
18
18
  if (!shops.length) {
19
19
  lignes.push(
20
- "Aucune boutique connectée. Pour en connecter une : installez l'appli Story Apps sur la boutique (depuis l'App Store Shopify ou l'espace Story Thème), et vérifiez qu'elle est déclarée dans votre espace membre (Boutiques).",
20
+ "Aucune boutique connectée. Pour en connecter une : installez l'appli Story Theme Apps sur la boutique (depuis l'espace membre Story Thème, page MCP & Appli), et branchez la boutique avec Theme Access (même page).",
21
21
  );
22
22
  return lignes.join('\n');
23
23
  }
@@ -38,7 +38,7 @@ export function formatOverview(data) {
38
38
  lignes.push(` ${n(s.products)} produits · ${n(s.collections)} collections`);
39
39
  const m = s.modules || {};
40
40
  lignes.push(
41
- ` Story Apps : ${n(m.reviews)} avis${m.reviewsPending ? ` (${m.reviewsPending} à modérer)` : ''} · ${n(m.abTests)} test${m.abTests > 1 ? 's' : ''} A/B · offres cumulables ${m.offers ? 'actives' : 'non activées'}`,
41
+ ` Story Theme Apps : ${n(m.reviews)} avis${m.reviewsPending ? ` (${m.reviewsPending} à modérer)` : ''} · ${n(m.abTests)} test${m.abTests > 1 ? 's' : ''} A/B · offres cumulables ${m.offers ? 'actives' : 'non activées'}`,
42
42
  );
43
43
  if (s.errors?.length) lignes.push(` ⚠️ ${s.errors.map((e) => e.message).join(' · ')}`);
44
44
  }
@@ -65,7 +65,7 @@ const LIBELLES = {
65
65
  discounts: 'Codes promo',
66
66
  };
67
67
 
68
- /** Résultat d'un module de l'appli privée, boutique par boutique (message rédigé par l'appli). */
68
+ /** Résultat d'un module de l'appli, boutique par boutique (message rédigé par l'appli). */
69
69
  export function formatApp(data) {
70
70
  const res = data.results || [];
71
71
  const reussis = res.filter((r) => r.ok).length;
@@ -1,5 +1,5 @@
1
1
  // Outils « multi-boutiques » du MCP Story Thème : lire et modifier TOUTES les boutiques d'un
2
- // client en même temps, sans se déconnecter, via l'appli Shopify Story Apps.
2
+ // client en même temps, sans se déconnecter, via l'appli Shopify Story Theme Apps.
3
3
  //
4
4
  // Branchement : dans src/server.js, juste avant `return server;` de createServer :
5
5
  // registerShopTools(server, config);
@@ -22,9 +22,9 @@ const garde = (fn) => async (args) => {
22
22
  try {
23
23
  return await fn(args || {});
24
24
  } catch (e) {
25
- if (e instanceof ShopsError && /sans Story Apps/.test(e.message)) {
25
+ if (e instanceof ShopsError && /sans Story (Theme )?Apps/.test(e.message)) {
26
26
  // La boutique est sans doute branchée par Theme Access : l'outil n'est pas le bon.
27
- return fail(`${e.message}\nSi elle est branchée par Theme Access (● dans list_shops) sans l'appli privée Story Thème, seuls ses thèmes sont accessibles : pull_from_shop, push_to_shop, update_theme, migrate_v3. Pour les avis, tests A/B, offres et codes promo, le marchand demande l'appli ${DEMANDER_APPLI}. Pour ses produits, collections, pages et menus : le connecteur Shopify officiel du marchand.`);
27
+ return fail(`${e.message}\nSi elle est branchée par Theme Access (● dans list_shops) sans l'appli Story Thème, seuls ses thèmes sont accessibles : pull_from_shop, push_to_shop, update_theme, migrate_v3. Pour les avis, tests A/B, offres et codes promo, le marchand demande l'appli ${DEMANDER_APPLI}. Pour ses produits, collections, pages et menus : le connecteur Shopify officiel du marchand.`);
28
28
  }
29
29
  return fail(e.message);
30
30
  }
@@ -44,7 +44,7 @@ export function registerShopTools(server, config, { fetchImpl, ctx } = {}) {
44
44
  {
45
45
  title: 'Vos boutiques',
46
46
  description:
47
- "Lists every Shopify store of this Story Theme account that has the Story Apps app installed: name, domain, handle, theme version, licence. Call it first before any multi-store work. Stores are reached through Story Apps: no Shopify key needed.",
47
+ "Lists every Shopify store of this Story Theme account that has the Story Theme Apps app installed: name, domain, handle, theme version, licence. Call it first before any multi-store work. Stores are reached through Story Theme Apps: no Shopify key needed.",
48
48
  annotations: { readOnlyHint: true, openWorldHint: true },
49
49
  },
50
50
  garde(async () => {
@@ -58,7 +58,7 @@ export function registerShopTools(server, config, { fetchImpl, ctx } = {}) {
58
58
  {
59
59
  title: "Vue d'ensemble des boutiques",
60
60
  description:
61
- 'Only for stores where the private Story Theme app (Story Apps) is installed. Key figures in one call: products, collections, Shopify plan, theme version and pending update, licence, and Story Apps modules (reviews, pending reviews, A/B tests, stackable offers). A store connected with Theme Access only, without the app, is NOT reachable here: app_status says what to tell the merchant.',
61
+ 'Only for stores where the Story Theme Apps app is installed. Key figures in one call: products, collections, Shopify plan, theme version and pending update, licence, and Story Theme Apps modules (reviews, pending reviews, A/B tests, stackable offers). A store connected with Theme Access only, without the app, is NOT reachable here: app_status says what to tell the merchant.',
62
62
  annotations: { readOnlyHint: true, openWorldHint: true },
63
63
  },
64
64
  garde(async () => {
@@ -72,7 +72,7 @@ export function registerShopTools(server, config, { fetchImpl, ctx } = {}) {
72
72
  {
73
73
  title: 'Requête sur une ou plusieurs boutiques',
74
74
  description:
75
- 'Only for stores where the private Story Theme app (Story Apps) is installed — NOT for a store connected with Theme Access only, which only opens its themes (use pull_from_shop / push_to_shop; for products, collections, pages, menus and discounts, use the merchant\'s official Shopify connector). Runs one Shopify Admin GraphQL operation on one, several or all Story Apps stores, in parallel, within the app scopes. For reviews, A/B tests, offers and discount codes prefer the app_* tools. A mutation on several stores needs confirm: true, only after the user explicitly agreed. Every access is logged.',
75
+ 'Only for stores where the Story Theme Apps app is installed — NOT for a store connected with Theme Access only, which only opens its themes (use pull_from_shop / push_to_shop; for products, collections, pages, menus and discounts, use the merchant\'s official Shopify connector). Runs one Shopify Admin GraphQL operation on one, several or all Story Theme Apps stores, in parallel, within the app scopes. For reviews, A/B tests, offers and discount codes prefer the app_* tools. A mutation on several stores needs confirm: true, only after the user explicitly agreed. Every access is logged.',
76
76
  inputSchema: {
77
77
  shops: cibleSchema,
78
78
  query: z.string().describe('Requête ou mutation GraphQL Admin.'),
@@ -87,7 +87,7 @@ export function registerShopTools(server, config, { fetchImpl, ctx } = {}) {
87
87
  }),
88
88
  );
89
89
 
90
- // Les modules de l'appli privée (avis, A/B, offres, codes promo) : seulement la passerelle.
90
+ // Les modules de l'appli (avis, A/B, offres, codes promo) : seulement la passerelle.
91
91
  registerAppTools(server, { client, ok, fail });
92
92
 
93
93
  // L'envoi direct suppose un projet sous la main : seul le serveur complet passe `ctx`.
package/src/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // Version du serveur MCP. Ici et dans package.json — les deux doivent être identiques
2
2
  // (npm test le vérifie), et rien d'autre ne la redéclare.
3
- export const VERSION = '1.7.0';
3
+ export const VERSION = '1.7.2';