Journalisation
Traduction automatique
Cette page a été traduite automatiquement à partir de la documentation en anglais, et la page en anglais fait foi. Si quelque chose vous semble incorrect, la page Traductions explique comment le signaler.
Journalisez depuis un outil comme vous le feriez depuis n’importe quelle autre fonction Python : avec la bibliothèque standard.
MCP possède une capacité de journalisation au niveau du protocole : un serveur pouvait envoyer ses messages de journal au client sous forme de notifications, via des méthodes de l’objet Context. La révision 2026-07-28 de la spécification rend cette capacité obsolète sans la remplacer, si bien que cette documentation ne l’enseigne pas. La liste complète de ce qui est obsolète, et de ce qu’il faut faire à la place, se trouve dans Fonctionnalités obsolètes.
Ce que vous faites à la place, c’est ce que vous faites dans tout autre programme Python : utiliser la bibliothèque standard.
Un outil qui journalise
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("Bookshop")
@mcp.tool()
def search_books(query: str) -> str:
"""Search the catalog by title or author."""
logger.info("Searching for %r", query)
return f"Found 3 books matching {query!r}."
logging.getLogger(__name__)vous donne un logger nommé d’après votre module. Créez-le une seule fois, en haut du fichier.- Dans l’outil, vous appelez
logger.info(...)comme dans n’importe quelle autre fonction. Rien à injecter, rien àawait, rien de spécifique à MCP.
Check
Appelez l’outil et regardez le résultat complet :
result.content # [TextContent(text="Found 3 books matching 'dune'.")]
result.structured_content # {'result': "Found 3 books matching 'dune'."}
La ligne de journal n’y figure nulle part. La journalisation est faite pour vous, la personne qui exploite le serveur. Le modèle
ne la voit jamais. Si le modèle doit lire quelque chose, renvoyez-le avec return.
Où cela va
Pour un serveur stdio, cette question compte plus que d’habitude. L’hôte a lancé votre serveur comme sous-processus et lit les messages MCP depuis son stdout. La sortie d’erreur standard est à vous.
La bibliothèque standard fait déjà ce qu’il faut : la sortie des journaux va vers sys.stderr par défaut. Vos lignes logger.info(...) arrivent dans le terminal (ou là où l’hôte collecte le stderr du sous-processus), et le flux du protocole reste propre.
Tip
N’utilisez pas print() dans un serveur stdio. print écrit sur stdout, et stdout appartient au protocole.
Pendant qu’il sert, le SDK redirige vers stderr ce qui est effectivement vidé (flush) sur stdout, de sorte que cela ne peut pas corrompre
la liaison ; mais dans un processus à tampon par blocs, un print() reste généralement non vidé dans le tampon de sys.stdout
jusqu’à ce que l’interpréteur le purge à la sortie, directement sur le flux du protocole. Même lorsqu’elle est redirigée,
la ligne arrive brute au milieu de la sortie des journaux, sans niveau, sans nom de logger et sans aucun moyen de la filtrer.
logger.debug("got here") demande le même effort d’une ligne et va au bon endroit.
Le niveau
Vous n’avez pas à appeler logging.basicConfig() vous-même. La construction d’un MCPServer l’a déjà fait, avec un gestionnaire de journalisation pointé vers la sortie d’erreur standard, au niveau que vous passez via log_level= ; MCPServer("Bookshop", log_level="DEBUG") suffit donc pour voir vos lignes logger.debug(...).
La valeur par défaut est "INFO".
logging.basicConfig() ne remplace jamais des gestionnaires de journalisation qui existent déjà. Si vous configurez la journalisation vous-même avant de créer le serveur, votre configuration l’emporte.
Essayer
Lancez le serveur avec le MCP Inspector :
uv run mcp dev server.py
Appelez search_books depuis l’onglet Tools. L’Inspector vous montre le résultat : uniquement la valeur de retour. La ligne
Searching for 'dune'
est partie vers la sortie d’erreur standard : le terminal, pas la liaison.
Info
Si ce que vous voulez vraiment, c’est du traçage (chaque requête, sa durée, son éventuel échec), vous ne voulez pas des lignes de journal, vous voulez des spans. Votre serveur en émet déjà : le SDK trace chaque message avec OpenTelemetry par défaut. Voir OpenTelemetry.
Récapitulatif
- La capacité de journalisation du protocole MCP est rendue obsolète par la spécification 2026-07-28 et n’est pas remplacée. Ne construisez rien dessus.
logger = logging.getLogger(__name__)au niveau du module,logger.info(...)dans l’outil. C’est tout le modèle à suivre.- La sortie des journaux n’atteint jamais le modèle. Seule la valeur que vous renvoyez avec
returny parvient. - La sortie d’erreur standard est à vous ; stdout appartient au protocole. Pendant qu’il sert, le SDK redirige vers stderr ce qui s’égare sur stdout et est vidé, mais un
print()non vidé peut encore se déverser sur la liaison à la sortie, et les lignes redirigées arrivent sans étiquette ; utilisezlogging, dont le gestionnaire vide chaque enregistrement. MCPServer(..., log_level="DEBUG")fixe le niveau, et une configuration de journalisation que vous avez faite au préalable est laissée telle quelle.
Prévenir les clients connectés que quelque chose a changé sur votre serveur (la liste des outils, une ressource), c’est l’affaire des Abonnements.