Fonctions IA
Chaque action IA dans cmssy est une définition d'outil soumise à permissions, partagée par le serveur MCP et l'assistant intégré.
cmssy offre deux voies pour laisser une IA agir sur vos contenus : le serveur MCP, auquel se connectent des clients externes comme Claude, et l'assistant intégré au tableau de bord cmssy.
Ce ne sont pas deux implémentations. Les deux sont des transports au-dessus du même noyau d'outils : une capacité ajoutée une fois apparaît dans les deux, avec le même comportement et les mêmes contrôles de permissions.
Ce qu'est un outil
Un outil est un objet simple. En voici un vrai, en entier :
import { z } from "zod";
import type { AiTool, PageSummary } from "../types.js";
const inputSchema = z.object({
search: z
.string()
.optional()
.describe("Optional text to filter pages by name or slug"),
});
export const listPagesTool: AiTool<Input, Output> = {
name: "list_pages",
description:
"List the workspace's pages (id, name, slug, published), optionally filtered by a search string.",
inputSchema,
requiredPermissions: ["pages:view"],
execute: async ({ search }, ops) => {
const items = await ops.pages.list(search);
return { count: items.length, items };
},
};Cinq champs, et chacun mérite sa place :
name- ce que le modèle appelle.description- ce que le modèle lit pour décider s'il appelle. C'est de la surface de prompt, pas un commentaire de code ; une description vague donne un outil que personne n'utilise correctement.inputSchema- un schéma zod. Il valide l'appel et sert aussi de JSON Schema côté client : les deux ne peuvent jamais diverger.requiredPermissions- vérifié avant l'exécution.execute- le travail réel, avec l'entrée validée et un objetops.
Pourquoi ops est injecté
execute n'importe jamais de client, n'ouvre jamais de connexion et ne lit jamais de variable d'environnement. Il reçoit ops et appelle ses méthodes.
Ce seul choix rend le noyau neutre vis-à-vis du transport. Le serveur MCP fournit un ops adossé à un jeton API ; l'assistant intégré en fournit un adossé à la session de la personne connectée. L'outil ne voit pas la différence, et aucun des deux ne peut recevoir par accident des capacités que l'autre n'a pas.
Les permissions s'appliquent ici, pas en bordure
requiredPermissions vit sur l'outil : la vérification a lieu au même endroit, quel que soit l'appelant.
C'est important car les deux transports s'authentifient différemment. Un client MCP présente un jeton avec des scopes ; l'assistant agit comme un membre connecté avec un rôle. Si chaque transport portait sa propre logique de permissions, ils divergeraient - et cette divergence serait une élévation de privilèges, pas un bug d'affichage.
Conséquence pratique : un client IA ne peut jamais faire plus que l'identifiant qui le porte. Donnez à Claude un jeton en lecture seule et il listera et lira ; il refusera de publier parce que l'outil refuse, non parce qu'on a gentiment demandé au modèle.
Ce que couvrent les outils
Le registre est large - pages et blocs, modèles et enregistrements, médias et dossiers, formulaires et soumissions, membres et rôles, webhooks, ainsi que toute la surface commerce : produits, paniers, commandes, remises et pipelines de commandes.
La forme est cohérente : list_* et get_* pour lire, create_* / update_* / delete_* pour écrire, plus des verbes pour les transitions d'état comme publish_page, unpublish_page, revert_to_published et promote_dev_draft.
Rien dans cet ensemble ne touche à votre code. Aucun outil n'écrit un fichier, ne modifie un composant ni n'ouvre une pull request : l'IA édite le contenu, les schémas de blocs restent dans votre dépôt, en revue.
Brouillons de développement
Pour un problème précis - essayer un type de bloc pas encore déployé - il existe un paramètre et un outil.
Les outils d'écriture acceptent un target valant "devDraft", qui modifie votre calque personnel plutôt que le brouillon partagé. L'aperçu de personne d'autre ne change. Quand le bloc part en production, promote_dev_draft déplace votre calque sur le brouillon partagé.
Sans cela, expérimenter avec un bloc non déployé reviendrait à poser sur un brouillon partagé du contenu qui s'affiche comme rien pour tous les collègues.
Étapes suivantes
- Serveur MCP - connecter un client IA externe.
- Jetons API - les scopes derrière
requiredPermissions. - Membres et rôles - ce dont hérite l'assistant intégré.