Agents IA (MCP)
graal expose un serveur MCP (Model Context Protocol) : un agent IA s’y branche et pilote la plateforme avec les droits du compte qu’il porte, pas avec les siens. Le serveur ne parle pas à la base de données : il traduit MCP vers l’API REST de graal, en portant l’identité de l’appelant.
Une précision qui compte avant tout le reste : la plateforme et les données restent chez vous, mais ce que les outils renvoient à l’agent passe par le modèle de langage que vous avez choisi. Si ce modèle est hébergé par un tiers, la sortie de données est votre décision, pas un effet de bord. Voir Souveraineté et architecture.
Les outils
Section intitulée « Les outils »Des outils de lecture, des outils d’écriture, et aucun outil destructif activé par défaut.
| Outil | Ce qu’il rend |
|---|---|
list_projects |
Les projets du tenant |
list_jobs |
Les jobs d’un projet ou du tenant (filtre par type, pagination) |
get_job |
La définition complète d’un job |
get_run |
L’état d’une exécution — sans identifiant, la plus récente du job |
get_run_logs |
Le journal d’un run, suivi incrémental par curseur |
list_catalog |
Le catalogue, couche par couche : couches → bases → tables → champs |
list_bucket_files |
Les buckets, ou le contenu d’un chemin |
get_costs |
Les coûts du tenant ou d’un projet sur une période |
Écriture
Section intitulée « Écriture »| Outil | Ce qu’il fait |
|---|---|
upload_code |
Téléverse un fichier de code dans les librairies du tenant |
create_job |
Crée un job dans un projet (Python, Spark, low-code ou bash) |
run_job |
Lance une exécution, sans attendre son résultat |
schedule_job |
Pose ou remplace la planification cron d’un job |
Pourquoi aucun outil ne supprime
Section intitulée « Pourquoi aucun outil ne supprime »C’est une décision d’architecture, pas un oubli, et elle est tenue à trois endroits du code plutôt que par une convention :
- le type des opérations du serveur n’admet que
GET,POSTetPATCH— un appelDELETEne compile pas ; - tous les outils sont annoncés au protocole avec
destructiveHint: false; - retirer une planification, supprimer un job ou un fichier reste un geste humain, dans la console.
Un agent peut donc créer, lancer et planifier du travail, et vous pouvez toujours revenir en arrière vous-même. Un agent qui se trompe encombre ; il ne détruit pas.
Les deux modes d’authentification
Section intitulée « Les deux modes d’authentification »| Mode | Qui détient le secret | D’où vient le tenant | Pour quoi |
|---|---|---|---|
| Jeton présenté | personne : l’agent apporte son jeton, le serveur le relaie | du realm porté par le jeton | l’usage normal, seul mode admis hors machine locale |
| Application graal | le serveur, avec les identifiants d’une « Application graal » par tenant | d’un en-tête ou de sa configuration | poste local : démonstration, mise au point |
Quatre garde-fous, dans cet ordre :
- Un jeton ne sort jamais de son tenant. L’émetteur (
iss) du jeton doit valoir exactement<url Keycloak>/realms/<realm du tenant>, vérifié avant le premier appel à l’API. - Le tenant n’est jamais un paramètre d’outil. Il vient de la session et part en en-tête ; un agent ne peut pas changer de tenant en changeant un argument.
- Le mode « Application graal » refuse de démarrer ailleurs que sur l’interface locale
(
127.0.0.1,::1,localhost) : sur un port exposé, quiconque l’atteint obtiendrait les droits de l’agent.GRAAL_MCP_REQUIRE_BEARER=1coupe entièrement ce mode. - La frontière de sécurité est le RBAC par projet de l’API, pas le serveur MCP. Restreindre un
agent à un projet par sa configuration (
GRAAL_MCP_PROJECT_ID) est un confort ; les droits réels sont ceux du compte derrière le jeton.
Ce que l’agent laisse comme trace
Section intitulée « Ce que l’agent laisse comme trace »Chaque écriture réussie est attribuée et notifiée :
- le job créé porte les étiquettes
graal.systems/created-by: agentetgraal.systems/agent: agent-mcp; - l’exécution lancée porte l’initiateur
agent-mcp; - une notification part vers le propriétaire du projet touché, plus les destinataires configurés. Une notification en échec n’annule pas l’action : le résultat rendu à l’agent dit explicitement si elle est passée.
Autrement dit, « qui a lancé ce run ? » a une réponse, portée par le run lui-même.
Le journal d’audit de la plateforme relie en plus chaque action à son acteur, humain ou agent (voir sécurité et gouvernance).
Brancher un agent
Section intitulée « Brancher un agent »Le serveur écoute en Streamable HTTP sur 127.0.0.1:7332 par défaut : point d’entrée
POST /mcp, vivacité GET /healthz (qui ne touche pas à l’API). Un transport stdio existe
aussi, pour un agent lancé en sous-processus.
Côté client MCP, la configuration tient en quelques lignes :
{ "mcpServers": { "graal": { "type": "http", "url": "http://127.0.0.1:7332/mcp", "headers": { "X-Graal-Tenant": "mon-tenant" } } }}En mode « jeton présenté », ajouter un en-tête Authorization: Bearer <jeton> : le tenant est alors
déduit du realm du jeton et l’en-tête X-Graal-Tenant devient inutile.
Pour lister les outils et l’opération REST derrière chacun sans rien démarrer :
graal-mcp --tools.
Configuration
Section intitulée « Configuration »| Variable | Rôle |
|---|---|
GRAAL_API_URL |
Racine de l’API, préfixe /api/v1 compris |
GRAAL_KEYCLOAK_URL |
Origine publique de Keycloak, qui sert à calculer l’émetteur attendu |
GRAAL_MCP_TENANT, GRAAL_MCP_REALM |
Le tenant servi et son realm |
GRAAL_MCP_CLIENT_ID, GRAAL_MCP_CLIENT_SECRET |
L’« Application graal » du tenant (mode Application) |
GRAAL_MCP_TENANTS |
La même chose en JSON, pour servir plusieurs tenants |
GRAAL_MCP_PROJECT_ID |
Restreint l’agent à un projet (confort, pas une isolation) |
GRAAL_MCP_NOTIFY_TO |
Destinataires supplémentaires des notifications |
GRAAL_MCP_REQUIRE_BEARER |
À 1, seul le mode « jeton présenté » est accepté |
GRAAL_MCP_HOST, GRAAL_MCP_PORT |
Interface et port d’écoute (défaut 127.0.0.1:7332) |
Aucune de ces variables ne contient un secret d’utilisateur : le serveur n’en stocke aucun, et il ne conserve un jeton en mémoire que le temps de sa validité.
Erreurs, et comment un agent doit les lire
Section intitulée « Erreurs, et comment un agent doit les lire »Toutes les erreurs sont rendues sous la même forme, avec une catégorie stable que l’agent peut
exploiter : feature_disabled, unauthorized, forbidden, not_found, api_error, auth_error,
config_error, unknown_tenant, out_of_scope, precondition_failed, transport_error.
Le cas à connaître est le premier : une fonction désactivée sur l’installation répond 501 feature_disabled, jamais 404, et le message dit à l’agent de ne pas réessayer. Un 404 signifie
donc vraiment « cette ressource n’existe pas », ce qui rend les deux cas distinguables sans
deviner.
Brancher un client
Section intitulée « Brancher un client »Le serveur parle MCP sur HTTP. Dans un client compatible (Claude Code, Claude Desktop, ou tout autre client MCP), la déclaration tient en quelques lignes :
{ "mcpServers": { "graal": { "type": "http", "url": "https://mcp.example.com/mcp", "headers": { "X-Graal-Tenant": "votre-locataire" } } }}Deux modes d’authentification, et le choix décide de qui agit :
| Mode | Comment | Le locataire vient de | Quand s’en servir |
|---|---|---|---|
| Compte de service | Le serveur porte les identifiants d’une application, et le client nomme le locataire par X-Graal-Tenant |
l’en-tête | Un agent qui travaille pour une équipe, sur un locataire donné |
| Jeton présenté | Le client ajoute "Authorization": "Bearer <jeton>" dans headers |
le domaine du jeton | Un agent qui agit pour le compte d’une personne, avec exactement ses droits |
Ce qu’un agent peut faire, concrètement
Section intitulée « Ce qu’un agent peut faire, concrètement »Une fois branché, l’agent dispose de tous les outils. Une demande comme « prépare un job qui agrège la consommation régionale et planifie-le tous les matins à 6 h » se traduit chez lui en :
list_projects → trouver le projetupload_code → déposer le script dans le bucket du projetcreate_job → créer le job (python, spark, bash ou lowcode — rien d'autre)run_job → lancer une première exécutionget_run · get_run_logs → suivre, et lire les logs par curseurschedule_job → poser le cronChaque écriture pousse une notification au propriétaire du projet et allume le badge « Agent » dans la console. Vous n’avez pas à demander à l’agent ce qu’il a fait : c’est écrit.
Les garde-fous de l’agent
Section intitulée « Les garde-fous de l’agent »- Aucune suppression. Aucun outil de suppression n’est activé, et un test refuse qu’on en
ajoute un : aucun outil ne peut s’adosser à une opération
DELETEni s’appelerdelete_*. - Un type de job connu.
create_jobn’accepte quepython,spark,bashetlowcode, et refuse avant tout appel réseau. - Aucune valeur inventée. Si le type d’instance ou l’identité ne peut pas être déduit de ce que la plateforme connaît, l’outil s’arrête et nomme le geste humain attendu plutôt que de forcer l’écriture.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Installation — ce qu’il faut pour faire tourner la plateforme
- Souveraineté et architecture
- Sécurité et gouvernance
- Page publique : Agents IA