Aller au contenu principal

Implémenter un client MCP

Mis à jour le 30 juillet 2026

Le serveur MCP fonctionne — l’inspecteur en a fait la preuve. Il est temps de construire le côté client : la pièce qui permet à notre application de communiquer avec le serveur et d’accéder à ses fonctionnalités. Dans l’architecture du chatbot, c’est lui qui prendra la place du run_tool local de la section Tool Use — même rôle, mais les outils viennent désormais d’un serveur.

Les deux méthodes essentielles

Notre client doit implémenter deux méthodes clés : list_tools() et call_tool() — et ce duo n’a rien d’arbitraire : découverte puis exécution, ce sont les deux seules opérations que le protocole exige pour faire travailler des outils distants.

list_tools()

async def list_tools(self) -> list[types.Tool]:
    result = await self.session().list_tools()
    return result.tools

call_tool()

async def call_tool(
    self, tool_name: str, tool_input: dict
) -> types.CallToolResult | None:
    return await self.session().call_tool(tool_name, tool_input)

La brièveté de ces méthodes est un choix du SDK : la session gère toute la complexité — sérialisation des messages, transport, corrélation des réponses — et nos méthodes se contentent d’envelopper ses appels. Notez la signature de call_tool : un nom, un dictionnaire d’arguments — exactement celle du run_tool local. Ce parallèle est voulu, et il paiera à l’intégration.

Tester le client

async with MCPClient(
    command="uv", args=["run", "mcp_server.py"]
) as client:
    result = await client.list_tools()
    print(result)

Ce petit test montre deux choses importantes. Le gestionnaire de contexte (async with) : une session MCP est une connexion vivante qui doit s’ouvrir et se fermer proprement — l’encapsuler dans un contexte garantit le nettoyage, même si le code lève une exception. Et les paramètres command/args : le client lance le serveur en sous-processus (uv run mcp_server.py) et dialogue avec lui en stdio — le transport standard du développement local. Si ce test affiche vos outils avec leurs descriptions et schémas, la tuyauterie est bonne.

Flux complet de l’application

Situons le client dans l’application entière. Quand un utilisateur pose une question sur un document :

1. Notre code utilise le client pour obtenir les outils disponibles
2. Ces outils sont envoyés à Claude avec la question de l'utilisateur
3. Claude décide d'utiliser l'outil read_doc_contents
4. Notre code utilise le client pour exécuter cet outil
5. Le résultat est renvoyé à Claude
6. Claude formule sa réponse finale

Comparez avec la boucle de conversation de la section Tool Use : les étapes 2, 3, 5 et 6 sont identiques — c’est votre boucle, inchangée. Seules les étapes 1 et 4 ont changé de fournisseur : la liste d’outils vient de list_tools() au lieu d’un tableau codé en dur, l’exécution passe par call_tool() au lieu d’une fonction locale. Claude, lui, ne voit aucune différence — des outils, des résultats, comme toujours.

Le client agit comme le pont entre la logique de notre application et le serveur MCP : côté serveur il parle le protocole, côté application il offre exactement l’interface que la boucle de conversation attendait. Les prochaines leçons brancheront les deux autres primitives — ressources puis prompts — sur ce même pont.

Points clés à retenir

  • Deux méthodes suffisent au client : list_tools (découverte) et call_tool (exécution)
  • La session du SDK gère transport et protocole ; le gestionnaire de contexte garantit son nettoyage
  • Le client lance le serveur en sous-processus et dialogue en stdio — le transport du développement
  • Dans le flux complet, seule la provenance des outils change — la boucle de conversation est intacte
  • Testez le client seul (liste des outils) avant toute intégration avec Claude