Tutoriel : le sampling en pratique
Ce tutoriel vous guide pas à pas dans l’implémentation du sampling, en expliquant chaque étape du code.
Étape 1 : Initier le sampling côté serveur
Sur le serveur, pendant un appel d’outil, vous lancez le sampling en appelant la méthode create_message() via le contexte. Vous lui passez les messages que vous souhaitez envoyer au modèle de langage.
# Dans votre fonction d'outil
@mcp.tool()
async def research_and_summarize(topic: str, ctx: Context):
# 1. Faire la recherche
articles = await fetch_wikipedia(topic)
# 2. Initier le sampling pour résumer
result = await ctx.session.create_message(
messages=[
SamplingMessage(
role="user",
content=TextContent(
type="text",
text=f"Résume ces articles en un rapport concis : {articles}"
)
)
],
max_tokens=2000,
system_prompt="Tu es un assistant de recherche expert.",
)
return result.content.text
Étape 2 : Callbacks de sampling
Le callback de sampling est la fonction côté client qui sera appelée quand le serveur demande une génération de texte. Elle reçoit :
context: le contexte de la requêteparams: les paramètres incluant les messages à envoyer au LLM
async def sampling_callback(
context: RequestContext,
params: CreateMessageRequestParams
):
# Votre logique pour appeler Claude
text = await appeler_claude(params.messages, params.system)
return CreateMessageResult(
role="assistant",
model="claude-opus-4-5",
content=TextContent(type="text", text=text),
)
Étape 3 : Formats de messages
Les messages envoyés via sampling suivent le même format que l’API Claude standard :
role:"user"ou"assistant"content: un objetTextContentavectype="text"et le texte du message
Vous pouvez aussi inclure des messages multi-tours pour fournir du contexte :
messages=[
SamplingMessage(role="user", content=TextContent(type="text", text="Question initiale")),
SamplingMessage(role="assistant", content=TextContent(type="text", text="Réponse précédente")),
SamplingMessage(role="user", content=TextContent(type="text", text="Question de suivi"))
]
Étape 4 : Retourner le texte généré
Le callback doit retourner un CreateMessageResult. Assurez-vous de toujours vérifier que le type de contenu est bien "text" :
if result.content.type == "text":
return result.content.text
else:
raise ValueError("Type de contenu inattendu dans la réponse de sampling")
Étape 5 : Connecter le callback
Passez le callback lors de la création de la session client :
async with ClientSession(
read,
write,
sampling_callback=sampling_callback # ← ici
) as session:
await session.initialize()
Étape 6 : Obtenir le résultat
Une fois tout connecté, le flux complet fonctionne automatiquement :
Utilisateur → "Recherche et résume Python"
↓
Outil research_and_summarize appelé
↓
fetch_wikipedia("Python") → données brutes
↓
ctx.session.create_message() → requête sampling au client
↓
sampling_callback → appel Claude → texte résumé
↓
Résultat retourné au serveur → retourné à l'utilisateur
Points clés à retenir
- Le callback est défini côté client, pas côté serveur
- Le serveur ne connaît pas quelle implémentation Claude le client utilise
- Plusieurs clients peuvent utiliser le même serveur MCP avec des implémentations de sampling différentes
- C’est idéal pour les serveurs publics où vous ne voulez pas gérer les coûts des tokens