Chapitre 4 — Primitives du client : comportements agentiques et contrôle

Publié le: 2026-04-02 Dernière mise à jour le: 2026-06-12 Version: 1

Chapitre 4 — Primitives du client : comportements agentiques et contrôle

Quatrième billet de la tournée chapitre par chapitre de LLM Primer IV : Concevoir la cognition de l'IA avec MCP. Les primitives du serveur exposent ce que le serveur peut offrir ; les primitives du client exposent ce que l'hôte veut bien prêter en retour — et chaque prêt est une capacité que l'utilisateur accorde et un risque que l'hôte accepte.


Pourquoi ce chapitre existe

Un serveur qui n'expose que des ressources, des prompts et des outils ne sait rien de son hôte : ni le modèle qu'il fait tourner, ni les fichiers qu'il peut voir, ni si l'utilisateur est même au clavier. Pour de nombreuses intégrations, ce mur est intentionnel. Pour des catégories entières de comportement utile, il est trop haut. Un serveur qui doit résumer un long document ne devrait pas avoir à livrer son propre LLM. Un serveur qui veut opérer sur un projet devrait savoir lequel. Un serveur qui a besoin de la permission de l'utilisateur pour une étape destructive devrait pouvoir la demander. Les primitives du client sont la façon dont MCP perce de petits trous contrôlés à travers le mur.

Les trois primitives — Sampling, Roots, Elicitation — étendent chacune la portée du serveur dans le territoire de l'hôte, d'une manière précise et négociée. Chacune est aussi une surface de sécurité que l'hôte accepte au nom de son utilisateur, et chacune se compose avec les autres pour produire un comportement plus agentique que la somme de ses parties.

En une ligne : Sampling laisse le serveur utiliser le modèle de l'hôte, Roots dit au serveur dans quelle portée il travaille, et Elicitation lui permet de poser une question à l'utilisateur — chacune un prêt délibéré, chacune un risque délibéré.

4.1 Sampling : emprunter le cerveau de l'hôte

Avec le sampling activé, un serveur peut demander à l'hôte de lancer un appel d'inférence et de lui retourner le résultat. Il ne livre aucun modèle, ne détient aucune clé d'API, et n'apprend jamais quel modèle l'hôte a réellement utilisé — il envoie des messages plus des préférences souples (coût, vitesse, intelligence), et l'hôte fait l'appel. Du point de vue du serveur, l'hôte est devenu un endpoint LLM générique.

Le levier est réel. Un serveur de magasin documentaire peut faire tourner de petites étapes de raisonnement à l'intérieur de sa propre logique — récupérer, classer, comparer — sans fuir de connaissance de domaine vers l'hôte ni livrer lui-même de l'inférence. Le risque est tout aussi réel. Un serveur malveillant peut utiliser le modèle de l'hôte — et le budget de l'utilisateur — pour faire un travail que l'utilisateur n'a jamais approuvé. L'attaque classique est une charge de sampling déguisée en instruction utilisateur. L'hôte est la seule ligne de défense, ce qui explique pourquoi les hôtes matures refusent par défaut le sampling à moins que l'utilisateur ne l'ait activé pour ce serveur précis, exposent le prompt de chaque appel à l'inspection, plafonnent les appels par session, et facturent le coût sur le portefeuille de l'utilisateur plutôt que sur celui du serveur.

Un souci plus subtil : le sampling peut encapsuler une boucle agentique interne. Pour l'hôte, cela ressemble à un seul appel de sampling ; à l'intérieur du serveur, tout un sous-agent a tourné. Le patron à nommer est le sous-agent borné — l'utilisateur accorde un budget de N appels, T secondes, X euros ; le serveur fait ce qu'il veut dans cette enveloppe et renvoie soit un résultat soit un résultat partiel gracieux. Le sampling ne donne pas non plus au serveur l'accès à la conversation ; il ne voit que ce qu'il a envoyé, et un hôte qui glisserait du contexte de conversation dans des charges de sampling aurait affaibli la frontière de confiance quelle que soit son intention.

4.2 Roots : frontières du système de fichiers et portée de projet

Un root est un URI — généralement file://, bien que la spec soit générale — que l'hôte a déclaré être dans la portée. Le serveur appelle roots/list et demande « avec quoi est-ce que je travaille ? » L'hôte annonce une capacité roots à l'initialisation et émet notifications/roots/list_changed lorsque l'utilisateur change de projet. La liste n'est qu'une liste ; pas de langage de permissions imbriqué, pas de motifs glob, pas de règles include/exclude.

La grossièreté est délibérée, et elle reflète un choix de conception MCP qui vaut la peine d'être compris. Un langage de permissions fin au niveau du protocole crée un faux sentiment de sécurité : les utilisateurs lisent une longue liste de portées et supposent que le protocole les fait respecter, alors qu'en réalité le protocole ne peut pas empêcher un serveur de se mal comporter d'une manière que le langage n'a jamais anticipée. Une primitive grossière adossée à une isolation externe — frontières de processus, montages de conteneur, contrôle d'accès au niveau OS — est honnête sur l'endroit où vit réellement la mise en application. Les roots sont un système d'honneur au niveau du protocole, rendu applicable au niveau de l'exécution quand le sandboxing entre en jeu.

Deux conséquences pratiques. D'abord, quand les roots changent, les serveurs bien élevés abandonnent l'état en cache attaché à l'ancien root — index, AST parsés, abonnements de fichiers surveillés — sinon ils fuient de l'état entre frontières de projet. Ensuite, les roots bornent ce que le serveur devrait regarder, pas ce qu'il a le droit de faire. Un fichier sensible à l'intérieur d'un root accordé — un dump de credentials, un fichier d'env, de la correspondance personnelle — reste sensible, et un serveur poli continue d'appliquer son jugement sur ce qu'il fait remonter.

4.3 Elicitation : laisser le serveur poser une question

L'élicitation est la plus récente des trois et celle qui reflète ce que les concepteurs ont appris de la première vague de déploiements d'agents. Le serveur émet elicitation/create avec un message (la question) et un requestedSchema (la forme de la réponse attendue). L'hôte rend la question dans son UI, collecte la réponse, la valide, et la retourne. Le serveur reprend son travail avec la réponse en main.

Le schéma est ce qui rend l'élicitation plus sûre que les prompts en forme libre. Un booléen ne peut pas être répondu par de la prose ; une énumération ne peut pas être répondue par une quatrième option. L'hôte peut montrer à l'utilisateur, dans une UI claire, qu'on lui demande un oui/non, et refuser autre chose. La spec restreint délibérément les schémas à des objets plats de primitives — pour de vrais formulaires, utilisez un outil dont le schéma d'argument est le formulaire, où l'utilisateur peut revoir les valeurs remplies par le modèle avant invocation. L'élicitation est pour les cas à un ou deux champs.

Le profil de risque a la forme du phishing : un serveur qui affiche « le système exige votre clé d'accès AWS pour continuer » essaie de faire taper un secret à l'utilisateur au mauvais endroit. Les hôtes atténuent par une attribution claire — chaque prompt d'élicitation étiqueté avec le serveur d'origine, séparément de la voix de l'assistant — et en refusant les schémas qui ressemblent à du credential. Le pendant positif est le patron de confirmation des outils destructifs : le premier travail d'un outil est d'éliciter « êtes-vous sûr ? » et il n'agit qu'à la confirmation. C'est l'une des pratiques de durcissement MCP les plus efficaces en production.

4.4 Composer les trois

Les primitives sont conçues pour se composer. Un serveur qui a les trois dispose, de fait, d'un runtime d'agent complet délégué à l'hôte : il peut lire la portée (roots), raisonner dessus (sampling), poser des questions de clarification (elicitation), et agir via ses propres outils. Les combinaisons comptent. Sampling plus roots, c'est un serveur d'agent autonome ; sampling plus elicitation, c'est un serveur conversationnel sans accès au système de fichiers ; roots plus elicitation, c'est un assistant déterministe. Chacune seule est bornée ; ensemble, elles se multiplient, et l'UI de consentement d'un hôte est à son meilleur quand elle peut nommer la combinaison que l'utilisateur accorde plutôt que de demander la permission pour chacune isolément.

À retenir : lisez les trois primitives client comme une seule question — quelle part de lui-même l'hôte est-il prêt à prêter au serveur ? Sampling prête le modèle. Roots prête une portée. Elicitation prête l'attention de l'utilisateur. Chaque prêt est négocié séparément pour que le consentement soit délibéré, et le rôle du protocole n'est pas de supprimer le risque mais de le rendre lisible.

Ce que prépare le Chapitre 4

Les primitives serveur et les primitives client décrivent ensemble tout ce que l'hôte et le serveur peuvent se faire l'un à l'autre. Ce que nous n'avons pas encore traité, c'est comment tout cela voyage sur le fil. tools/list et sampling/createMessage ne sont pas que des messages abstraits — ils circulent sur un transport, et le choix du transport décide discrètement de presque toutes les propriétés opérationnelles d'une intégration MCP. Les serveurs doivent aussi être trouvables : un hôte qui veut utiliser un serveur doit savoir qu'il existe, où il vit, et s'il faut croire la déclaration. Le Chapitre 5 reprend les deux.


Prochaine étape — Chapitre 5 : Transports et découverte. Les trois transports que MCP soutient — stdio, SSE, Streamable HTTP — comparés honnêtement, et la couche .well-known/mcp.json plus Server Card qui transforme des intégrations ponctuelles en quelque chose qui ressemble à un écosystème.

Vous voulez le tableau complet ? Le livre parcourt le cycle de vie complet, le modèle d'erreur et la surface de risque de chaque primitive, traite en profondeur le patron du sous-agent borné, et expose le modèle de consentement à plusieurs niveaux qui a émergé pour les hôtes qui gèrent des serveurs en lecture, à portée, et agentiques. LLM Primer IV sur Amazon →

SHO
SHO
CTO et Fondateur de RECEIPTROLLER. Axé sur les données, motivé par l'innovation, toujours curieux.