Logs et notifications de progression
Sur cette page
Mise à jour du 2 novembre 2026 — logs. La spécification MCP 2026-07-28 déprécie la fonctionnalité Logging (le niveau de log se transmet désormais requête par requête) ; les notifications de progression liées à une requête restent prévues. Pour journaliser, la spécification conseille d’écrire sur
stderren stdio ou d’utiliser OpenTelemetry. Dans le SDK Python v2, la documentation n’enseigne plus la journalisation par le protocole : journalisez avec le moduleloggingde Python (sortie sur stderr, niveau réglé parMCPServer(..., log_level=...)) ; la progression se signale toujours avecctx.report_progress(progress, total, message), et le client s’y abonne appel par appel avecprogress_callback=. Sources : Logging · Progress.
Les logs et les notifications de progression sont simples à implémenter mais font une énorme différence dans l’expérience utilisateur lors du travail avec des serveurs MCP. Ils aident les utilisateurs à comprendre ce qui se passe pendant les opérations longues au lieu de se demander si quelque chose a planté. À la fin de cette leçon, vous saurez émettre logs et progression depuis un outil, les recevoir côté client, et ce qui circule réellement sur le fil.
Le problème
Quand Claude appelle un outil qui prend du temps — comme faire des recherches sur un sujet ou traiter des données — les utilisateurs ne voient généralement rien jusqu’à la fin de l’opération. C’est frustrant car ils ne savent pas si l’outil fonctionne ou s’est bloqué.
Avec les logs et les notifications de progression activés, les utilisateurs obtiennent un retour en temps réel montrant exactement ce qui se passe en coulisses. Ils peuvent voir des barres de progression, des messages de statut, et des logs détaillés pendant l’exécution de l’opération.
Comment ça fonctionne
Dans le SDK MCP Python, les logs et notifications de progression fonctionnent via l’argument Context automatiquement fourni à vos fonctions d’outils. Cet objet contexte vous donne des méthodes pour communiquer avec le client pendant l’exécution.
@mcp.tool(
name="research",
description="Fait des recherches sur un sujet donné"
)
async def research(
topic: str = Field(description="Sujet à rechercher"),
*,
context: Context
):
await context.info("Démarrage des recherches...")
await context.report_progress(20, 100)
sources = await do_research(topic)
await context.info("Rédaction du rapport...")
await context.report_progress(70, 100)
results = await generate_report(sources)
await context.report_progress(100, 100)
return results
Les méthodes clés :
| Méthode | Usage |
|---|---|
context.info(message) | Envoyer un message de log informatif |
context.warning(message) | Envoyer un avertissement |
context.error(message) | Signaler une erreur |
context.report_progress(current, total) | Mettre à jour la progression |
Voici ce qui circule réellement sur le fil. Nous avons exécuté un outil research identique à celui ci-dessus sur le SDK Python 1.30.0, en transport stdio, avec un progressToken dans la requête, et enregistré les messages JSON-RPC tels quels :
{"method":"notifications/message","params":{"level":"info","data":"Démarrage des recherches..."},"jsonrpc":"2.0"}
{"method":"notifications/progress","params":{"progressToken":"t2","progress":20.0,"total":100.0},"jsonrpc":"2.0"}
{"method":"notifications/message","params":{"level":"info","data":"Rédaction du rapport..."},"jsonrpc":"2.0"}
{"method":"notifications/progress","params":{"progressToken":"t2","progress":100.0,"total":100.0},"jsonrpc":"2.0"}
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"Rapport sur MCP"}],"isError":false}}
Quatre notifications sans id (personne n’y répond), puis le résultat de l’outil avec son id. La progression est rattachée à la requête par le progressToken que le client a placé dans _meta ; sans ce jeton, le serveur n’émet pas de progression.
Implémentation côté client
Côté client, vous devez configurer des callbacks pour gérer ces notifications. Le serveur émet ces messages, mais c’est à votre application cliente de décider comment les présenter aux utilisateurs.
Callback de logging
async def logging_callback(params: LoggingMessageNotificationParams):
print(f"[LOG] {params.data}")
Callback de progression
async def progress_callback(
progress: float, total: float | None, message: str | None
):
if total is not None:
percentage = (progress / total) * 100
print(f"Progression: {progress}/{total} ({percentage:.1f}%)")
else:
print(f"Progression: {progress}")
Connecter les callbacks
async with stdio_client(server_params) as (read, write):
async with ClientSession(
read,
write,
logging_callback=logging_callback # ← callback de logging
) as session:
await session.initialize()
await session.call_tool(
name="research",
arguments={"topic": "intelligence artificielle"},
progress_callback=progress_callback, # ← callback de progression
)
Le callback de logging est fourni lors de la création de la session ; le callback de progression lors de l’appel d’outil individuel.
Options de présentation
Comment vous présentez ces notifications dépend de votre type d’application :
| Type d’application | Approche recommandée |
|---|---|
| CLI | Imprimer les messages et la progression dans le terminal |
| Web | WebSockets, Server-Sent Events, ou polling |
| Desktop | Barres de progression et affichage de statut dans l’UI |
Important : les notifications sont optionnelles
Ces notifications sont entièrement optionnelles. Vous pouvez choisir de les ignorer complètement, d’en afficher seulement certaines, ou de les présenter de la façon qui correspond à votre application. Ce sont purement des améliorations d’expérience utilisateur pour aider à comprendre ce qui se passe pendant les opérations longues.
À vous de jouer
- Ajoutez
context.infoetcontext.report_progressà l’outil le plus lent de votre serveur, un message par étape significative. - Côté client, branchez
logging_callbacksur la session etprogress_callbacksur l’appel, puis affichez une barre de progression dans le terminal. - Retirez le
progress_callbackde l’appel : les logs arrivent-ils encore ? Et la progression ? Expliquez la différence avec leprogressToken.
Sources officielles : Log and progress notifications (Claude Academy) · Progress (spécification 2026-07-28) · Registre des dépréciations (Logging) · Progress (SDK Python v2)
Points clés à retenir
- Le
Contextinjecté dans l’outil émet des logs (context.info,warning,error) et de la progression (context.report_progress(current, total)). - Sur le fil :
notifications/messageetnotifications/progress, sansid; la progression exige unprogressTokendans la requête. - Côté client, le callback de logging se déclare une fois sur la session, celui de progression à chaque appel d’outil.
- Le logging est déprécié en 2026-07-28 (stderr ou OpenTelemetry) ; la progression reste ; tout cela est optionnel et n’affecte pas le résultat.