Tutoriel : notifications en pratique
Ce tutoriel vous montre comment implémenter les logs et les notifications de progression dans votre code.
Étape 1 : L’argument Context dans les fonctions d’outils
Les fonctions d’outils reçoivent automatiquement un argument Context en dernier paramètre. Cet objet a des méthodes pour logger des messages et signaler la progression au client.
from mcp.server.fastmcp import Context
@mcp.tool()
async def long_operation(
data: str,
*,
context: Context # ← reçu automatiquement
):
# Vous pouvez maintenant utiliser context pour communiquer
await context.info("Opération démarrée")
# ... votre logique ...
Note : L’argument Context doit être déclaré avec * avant lui (keyword-only) pour que le SDK le reconnaisse.
Étape 2 : Créer des logs et de la progression
Utilisez le contexte pour communiquer l’état à intervalles réguliers :
@mcp.tool()
async def process_large_file(filename: str, *, context: Context):
await context.info(f"Chargement du fichier {filename}...")
await context.report_progress(10, 100)
data = load_file(filename)
await context.info("Traitement des données...")
await context.report_progress(40, 100)
results = process_data(data)
await context.info("Génération du rapport final...")
await context.report_progress(80, 100)
report = generate_report(results)
await context.info("Terminé !")
await context.report_progress(100, 100)
return report
Étape 3 : Définir les callbacks côté client
Définissez vos fonctions de callback dans votre code client :
# Callback pour les messages de log
async def on_log(params: LoggingMessageNotificationParams):
level = params.level.upper()
print(f"[{level}] {params.data}")
# Callback pour la progression
async def on_progress(progress: float, total: float | None, message: str | None):
if total:
bar_length = 30
filled = int(bar_length * progress / total)
bar = "█" * filled + "░" * (bar_length - filled)
pct = progress / total * 100
print(f"\r[{bar}] {pct:.0f}%", end="", flush=True)
Étape 4 : Passer les callbacks aux bonnes fonctions
Le callback de logging va sur la session ; le callback de progression va sur l’appel d’outil :
async with ClientSession(
read,
write,
logging_callback=on_log # ← sur la session
) as session:
await session.initialize()
result = await session.call_tool(
name="process_large_file",
arguments={"filename": "data.csv"},
progress_callback=on_progress # ← sur l'appel d'outil
)
print(f"\nRésultat : {result}")
Résumé du flux
Outil s'exécute sur le serveur
↓
context.info("message") → LoggingMessageNotification → client
context.report_progress(n, total) → ProgressNotification → client
↓
logging_callback(params) appelé → affichage
progress_callback(progress, total, msg) appelé → barre de progression
Points clés
Contextest keyword-only (*) — placez-le après*dans la signature- Le logging callback est fourni à la session (une fois)
- Le progress callback est fourni à chaque appel d’outil (flexible)
- Vous pouvez choisir d’ignorer l’un ou l’autre selon vos besoins
- Ces notifications n’affectent pas le résultat de l’outil — elles sont informatives uniquement