Le Model Context Protocol (MCP) est un protocole open-source développé par Anthropic qui répond à un défi fondamental des applications de modèles linguistiques volumineux (LLM) : leur isolement des sources de données et des outils externes. Ce tutoriel complet vous guidera à travers l'implémentation de MCP avec LangChain, vous fournissant les connaissances nécessaires pour créer des applications sophistiquées qui tirent parti des deux technologies de manière efficace.

Comprendre MCP et son objectif
Model Context Protocol vise à standardiser la manière dont les applications basées sur les LLM se connectent à divers systèmes externes. Pensez à MCP comme au "USB-C pour l'IA" - une interface universelle permettant un échange de données transparent, sécurisé et évolutif entre les LLM/agents d'IA et les ressources externes.
MCP utilise une architecture client-serveur :
- Hôtes MCP : applications d'IA qui doivent accéder aux données externes
- Serveurs MCP : fournisseurs de données ou d'outils qui fournissent des informations aux hôtes
Le protocole facilite une séparation claire des préoccupations, permettant aux développeurs de créer des connecteurs modulaires et réutilisables tout en maintenant une sécurité robuste grâce à des contrôles de permission granulaires.
Architecture technique
L'architecture de MCP se compose de trois composants principaux :
- Serveur : le serveur MCP expose des outils et des sources de données via une API standardisée
- Client : l'application cliente communique avec le serveur pour accéder aux outils et aux données
- Adaptateur : LangChain fournit des adaptateurs qui simplifient l'intégration entre les serveurs MCP et les applications LLM
Le flux de communication suit ce modèle :
- L'application LangChain demande l'exécution de données/outils
- L'adaptateur MCP transforme la requête au format du protocole MCP
- Le serveur traite la requête et renvoie les résultats
- L'adaptateur transforme la réponse en un format utilisable par LangChain
Prérequis
Avant de commencer, assurez-vous d'avoir ce qui suit :
- Python 3.8+ installé
- Clé API OpenAI (pour utiliser les modèles GPT avec LangChain)
- Familiarité de base avec les concepts de LangChain
- Accès au terminal (exemples montrés sur macOS)
Configuration de l'environnement
Tout d'abord, créons et configurons notre environnement de développement :
# Créer un environnement virtuel
python3 -m venv MCP_Demo
# Activer l'environnement virtuel
source MCP_Demo/bin/activate
# Installer les packages requis
pip install langchain-mcp-adapters
pip install langchain-openai
# Définir votre clé API OpenAI
export OPENAI_API_KEY=your_api_key
Création d'un serveur MCP simple
Nous allons commencer par créer un serveur MCP de base qui fournit des opérations mathématiques. Créez un fichier nommé math_server.py
:
# math_server.py
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Math")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Ajouter deux nombres"""
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""Multiplier deux nombres"""
return a * b
if __name__ == "__main__":
mcp.run(transport="stdio")
Ce serveur expose deux outils mathématiques : add
et multiply
. La classe FastMCP
simplifie la création du serveur, gérant automatiquement les détails du protocole. Chaque fonction décorée avec @mcp.tool()
devient disponible pour les clients, avec une documentation dérivée des docstrings.
Implémentation du client LangChain
Ensuite, créez un client LangChain pour interagir avec le serveur MCP. Enregistrez ceci sous le nom client.py
:
# Créer des paramètres de serveur pour la connexion stdio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import asyncio
model = ChatOpenAI(model="gpt-4o")
# Configurer les paramètres du serveur
server_params = StdioServerParameters(
command="python",
# Spécifier le chemin d'accès à votre fichier serveur
args=["math_server.py"],
)
async def run_agent():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Initialiser la connexion
await session.initialize()
# Charger les outils MCP au format LangChain
tools = await load_mcp_tools(session)
# Créer et exécuter l'agent
agent = create_react_agent(model, tools)
agent_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
return agent_response
# Exécuter la fonction asynchrone
if __name__ == "__main__":
result = asyncio.run(run_agent())
print(result)
Ce client établit une connexion au serveur MCP, charge les outils disponibles et crée un agent LangChain qui peut utiliser ces outils pour résoudre des problèmes.
Exécution de l'exemple
Pour exécuter cet exemple :
- Démarrez le serveur MCP dans un onglet de terminal :
python3 math_server.py
- Dans un autre onglet de terminal, exécutez le client :
python3 client.py
Le client invoquera l'agent LangChain, qui :
- Analyse la question "(3 + 5) x 12"
- Appelle l'outil
add
avec les arguments 3 et 5 - Obtient le résultat 8
- Appelle l'outil
multiply
avec les arguments 8 et 12 - Renvoie la réponse finale : 96
Implémentation avancée du serveur MCP
Développons notre implémentation pour créer un serveur MCP plus sophistiqué qui fournit un accès à la base de données. Cet exemple montre comment créer des connecteurs vers des systèmes externes :
# db_server.py
from mcp.server.fastmcp import FastMCP
import sqlite3
from typing import List, Dict, Any
class DatabaseConnector:
def __init__(self, db_path):
self.conn = sqlite3.connect(db_path)
self.cursor = self.conn.cursor()
def execute_query(self, query: str) -> List[Dict[str, Any]]:
self.cursor.execute(query)
columns = [desc[0] for desc in self.cursor.description]
results = []
for row in self.cursor.fetchall():
results.append({columns[i]: row[i] for i in range(len(columns))})
return results
mcp = FastMCP("DatabaseTools")
db_connector = DatabaseConnector("example.db")
@mcp.tool()
def run_sql_query(query: str) -> List[Dict[str, Any]]:
"""Exécuter une requête SQL sur la base de données et renvoyer les résultats"""
try:
return db_connector.execute_query(query)
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
mcp.run(transport="stdio")
Intégration de plusieurs serveurs MCP avec LangChain
Pour les applications plus complexes, vous devrez peut-être intégrer plusieurs serveurs MCP. Voici comment créer un client qui se connecte à plusieurs serveurs :
# multi_server_client.py
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
import asyncio
from typing import List, Dict
# Définir nos configurations de serveur
servers = [
{
"name": "math",
"params": StdioServerParameters(
command="python",
args=["math_server.py"]
)
},
{
"name": "database",
"params": StdioServerParameters(
command="python",
args=["db_server.py"]
)
}
]
async def connect_to_server(server_config):
"""Se connecter à un seul serveur MCP et charger ses outils"""
name = server_config["name"]
params = server_config["params"]
read, write = await stdio_client(params).__aenter__()
session = ClientSession(read, write)
await session.__aenter__()
await session.initialize()
tools = await load_mcp_tools(session)
return {
"name": name,
"session": session,
"tools": tools,
"cleanup": lambda: asyncio.gather(
session.__aexit__(None, None, None),
stdio_client(params).__aexit__(None, None, None)
)
}
async def run_multi_server_agent():
# Se connecter à tous les serveurs
connections = await asyncio.gather(
*[connect_to_server(server) for server in servers]
)
try:
# Collecter tous les outils de tous les serveurs
all_tools = []
for connection in connections:
all_tools.extend(connection["tools"])
# Créer l'agent avec tous les outils
model = ChatOpenAI(model="gpt-4o")
agent = create_react_agent(model, all_tools)
# Exécuter l'agent avec une requête complexe qui pourrait utiliser plusieurs serveurs
response = await agent.ainvoke({
"messages": "Trouver les clients qui ont dépensé plus que la valeur moyenne des commandes et calculer leur dépense totale."
})
return response
finally:
# Nettoyer toutes les connexions
for connection in connections:
await connection["cleanup"]()
# Exécuter l'agent multi-serveur
if __name__ == "__main__":
result = asyncio.run(run_multi_server_agent())
print(result)
Gestion des erreurs et stratégies de repli
Les implémentations MCP robustes doivent inclure la gestion des erreurs. Voici une version améliorée du client qui démontre la gestion des erreurs et les stratégies de repli :
# robust_client.py
async def run_agent_with_fallbacks():
try:
# Tenter la connexion principale
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
try:
await session.initialize()
tools = await load_mcp_tools(session)
agent = create_react_agent(model, tools)
return await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
except Exception as e:
print(f"Error using MCP tools: {e}")
# Revenir à l'appel direct du modèle sans outils
return await model.ainvoke([
HumanMessage(content="what's (3 + 5) x 12?")
])
except Exception as connection_error:
print(f"Connection error: {connection_error}")
# Repli ultime
return {"error": "Could not establish connection to MCP server"}
Considérations de sécurité
Lors de l'implémentation de MCP avec LangChain, tenez compte de ces bonnes pratiques de sécurité :
- Validation des entrées : validez toujours les entrées des outils MCP pour éviter les attaques par injection
- Permissions des outils : implémentez des permissions précises pour chaque outil
- Limitation du débit : appliquez des limites de débit pour empêcher l'abus des outils
- Authentification : implémentez une authentification appropriée entre les clients et les serveurs
Voici un exemple d'implémentation des permissions des outils :
from mcp.server.fastmcp import FastMCP, Permission
mcp = FastMCP("SecureTools")
# Définir les niveaux de permission
READ_PERMISSION = Permission("read", "Can read data")
WRITE_PERMISSION = Permission("write", "Can modify data")
@mcp.tool(permissions=[READ_PERMISSION])
def get_data(key: str) -> str:
"""Obtenir des données par clé (nécessite la permission de lecture)"""
# Implémentation...
return f"Data for {key}"
@mcp.tool(permissions=[WRITE_PERMISSION])
def update_data(key: str, value: str) -> bool:
"""Mettre à jour les données (nécessite la permission d'écriture)"""
# Implémentation...
return True
Optimisation des performances
Pour les déploiements en production, tenez compte de ces optimisations de performances :
- Pool de connexions : réutilisez les connexions MCP plutôt que d'en créer de nouvelles pour chaque requête
- Traitement par lots : regroupez plusieurs appels d'outils lorsque cela est possible
- Traitement asynchrone : utilisez asyncio pour gérer plusieurs requêtes simultanément
Exemple de pool de connexions :
class MCPConnectionPool:
def __init__(self, max_connections=10):
self.available_connections = asyncio.Queue(max_connections)
self.max_connections = max_connections
self.current_connections = 0
async def initialize(self):
# Pré-créer des connexions
for _ in range(3): # Commencer avec 3 connexions
await self._create_connection()
async def _create_connection(self):
if self.current_connections >= self.max_connections:
raise Exception("Maximum connections reached")
read, write = await stdio_client(server_params).__aenter__()
session = await ClientSession(read, write).__aenter__()
await session.initialize()
self.current_connections += 1
await self.available_connections.put(session)
async def get_connection(self):
if self.available_connections.empty() and self.current_connections < self.max_connections:
await self._create_connection()
return await self.available_connections.get()
async def release_connection(self, connection):
await self.available_connections.put(connection)
Tests des implémentations MCP
Des tests approfondis sont cruciaux pour des implémentations MCP fiables. Voici une approche de test utilisant pytest :
# test_mcp.py
import pytest
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
@pytest.fixture
async def mcp_session():
server_params = StdioServerParameters(
command="python",
args=["math_server.py"],
)
read, write = await stdio_client(server_params).__aenter__()
session = ClientSession(read, write)
await session.__aenter__()
await session.initialize()
yield session
await session.__aexit__(None, None, None)
await stdio_client(server_params).__aexit__(None, None, None)
@pytest.mark.asyncio
async def test_add_tool(mcp_session):
tools = await load_mcp_tools(mcp_session)
add_tool = next(tool for tool in tools if tool.name == "add")
result = await add_tool.invoke({"a": 5, "b": 7})
assert result == 12
@pytest.mark.asyncio
async def test_multiply_tool(mcp_session):
tools = await load_mcp_tools(mcp_session)
multiply_tool = next(tool for tool in tools if tool.name == "multiply")
result = await multiply_tool.invoke({"a": 6, "b": 8})
assert result == 48
Conclusion
Le Model Context Protocol fournit un cadre puissant pour connecter les applications LangChain avec des outils et des sources de données externes. En standardisant ces connexions, MCP permet aux développeurs de créer des agents d'IA sophistiqués qui peuvent interagir de manière transparente avec leur environnement.
La combinaison des capacités d'agent de LangChain avec la connectivité de MCP crée une base pour la création d'applications véritablement puissantes et contextuelles. Au fur et à mesure que l'écosystème MCP continue de croître, nous pouvons nous attendre à ce que davantage de serveurs et d'outils pré-construits émergent, simplifiant davantage le processus de développement.
Ce tutoriel a couvert les concepts fondamentaux et les détails d'implémentation de l'utilisation de MCP avec LangChain, de la configuration de base aux modèles avancés comme le pool de connexions et la gestion des erreurs. En suivant ces pratiques, vous pouvez créer des applications robustes et prêtes pour la production qui tirent parti du meilleur des deux technologies.
Pour une exploration plus approfondie, envisagez d'enquêter sur l'écosystème croissant de serveurs MCP disponibles sur GitHub, ou contribuez vos propres serveurs à la communauté. L'avenir des agents d'IA réside dans leur capacité à tirer parti efficacement des outils et des données externes, et MCP est une étape importante vers la réalisation de cette vision.