vinzlac/langchain-custom-mcp-server-adapters-test
If you are the rightful owner of langchain-custom-mcp-server-adapters-test and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
This project demonstrates the use of `@langchain/mcp-adapters` to automatically load tools from a custom MCP server without manual declarations in LangChain.
LangChain Custom MCP Server Adapters Test
Ce projet démontre l'utilisation de @langchain/mcp-adapters pour charger automatiquement les outils depuis un serveur MCP personnalisé sans avoir à les déclarer manuellement dans LangChain.
🎯 Différences avec l'approche précédente
❌ Approche précédente (déclaration manuelle)
- Création manuelle de wrappers LangChain pour chaque outil MCP
- Déclaration explicite de chaque outil dans le code LangChain
- Maintenance nécessaire lors de l'ajout de nouveaux outils
- Fichiers séparés pour chaque outil (
mcpSearchTool.ts,mcpWeatherTool.ts)
✅ Nouvelle approche (chargement automatique)
- Chargement automatique de tous les outils depuis le serveur MCP
- Aucune déclaration manuelle nécessaire
- Les outils sont découverts dynamiquement via le protocole MCP
- Ajout de nouveaux outils = aucune modification du code LangChain nécessaire
- Utilisation de
@langchain/mcp-adaptersv1.0.0 avec LangChain v1.0.0
🏗️ Architecture
Vue d'ensemble
┌─────────────────┐
│ User Query │
└────────┬────────┘
│
▼
┌─────────────────────────────────────┐
│ LangChain Agent (GPT-4) │
│ - createAgent() API v1.0.0 │
│ - Orchestre les outils │
│ - Sélection intelligente │
└────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ @langchain/mcp-adapters v1.0.0 │
│ MultiServerMCPClient │
│ - Charge automatiquement │
│ tous les outils MCP │
│ - getTools() discovery │
└────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ MCP Server (custom, stdio) │
│ - Serveur MCP personnalisé │
│ - Expose les outils │
│ - search, weather │
└────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ External APIs │
│ - Brave Search │
│ - OpenWeatherMap │
└─────────────────────────────────────┘
Diagramme de séquence
sequenceDiagram
participant User as 👤 User
participant Agent as 🤖 LangChain Agent
participant MCPClient as 📦 MCP Client<br/>(@langchain/mcp-adapters)
participant MCPServer as 🔧 MCP Server<br/>(Custom)
participant LLM as 🧠 LLM<br/>(OpenAI GPT-4)
participant API as 🌐 External APIs<br/>(Brave, OpenWeather)
Note over Agent,MCPClient: Initialisation
Agent->>MCPClient: initialize()
MCPClient->>MCPServer: ListTools request
MCPServer-->>MCPClient: Tools list (search, weather)
MCPClient->>Agent: getTools() → [search, weather]
Agent->>LLM: createAgent(model, tools, systemPrompt)
LLM-->>Agent: Agent ready
Note over User,API: Exécution d'une requête
User->>Agent: Question: "Météo à Paris"
Agent->>LLM: invoke({messages: [HumanMessage]})
Note over LLM: Analyse la question et décide d'utiliser l'outil weather
LLM-->>Agent: ToolCall: weather(city="Paris")
Agent->>MCPClient: Call tool: weather
MCPClient->>MCPServer: CallTool request (weather, {city: "Paris"})
Note over MCPServer,API: Exécution de l'outil weather
MCPServer->>API: GET /geo/1.0/direct?q=Paris
API-->>MCPServer: Coordinates (lat, lon)
MCPServer->>API: GET /data/2.5/forecast?lat=X&lon=Y
API-->>MCPServer: Weather data
MCPServer-->>MCPClient: Response: Weather text
MCPClient-->>Agent: Tool result
Note over Agent,LLM: L'agent traite le résultat et génère la réponse finale
Agent->>LLM: invoke({messages: [HumanMessage, ToolMessage, ...]})
LLM-->>Agent: Final response message
Agent-->>User: Réponse: "Météo actuelle à Paris..."
Flux détaillé avec logs
sequenceDiagram
participant User as 👤 User
participant Client as 📱 LangChain Client
participant MCPClient as 📦 MCP Client
participant MCPServer as 🔧 MCP Server
participant LLM as 🧠 LLM
participant API as 🌐 External APIs
User->>Client: ask("Météo à Paris")
Note right of Client: [USER] 📥 Question reçue<br/>[LANGCHAIN-AGENT] 📤 Request payload
Client->>LLM: agent.invoke({messages})
Note right of LLM: Analyse et décide d'utiliser weather
LLM-->>Client: ToolCall: weather(city="Paris")
Note left of Client: [LANGCHAIN-AGENT] 🔧 Appel d'outil
Client->>MCPClient: Call tool: weather
Note right of MCPClient: [MCP-CLIENT] 📤 Tool call
MCPClient->>MCPServer: CallTool request
Note right of MCPServer: [MCP-SERVER] 📥 Appel d'outil reçu<br/>[MCP-SERVER] 📤 Request payload<br/>[TOOL:weather] 🌤️ Recherche météo
MCPServer->>API: GET /geo/1.0/direct?q=Paris
Note right of API: [TOOL:weather] 📤 API Request payload (geo)
API-->>MCPServer: Coordinates
Note left of API: [TOOL:weather] 📥 API Response payload (geo)
MCPServer->>API: GET /data/2.5/forecast?lat=X&lon=Y
Note right of API: [TOOL:weather] 📤 API Request payload (weather)
API-->>MCPServer: Weather data
Note left of API: [TOOL:weather] 📥 API Response payload (weather)
MCPServer-->>MCPClient: Response with weather text
Note left of MCPServer: [MCP-SERVER] 📥 Response payload<br/>[TOOL:weather] ⏱️ Temps d'exécution
MCPClient-->>Client: Tool result
Note left of MCPClient: [MCP-CLIENT] 📥 Tool response
Client->>LLM: invoke({messages: [..., ToolMessage]})
Note right of LLM: Génère la réponse finale
LLM-->>Client: Final response
Note left of LLM: [LANGCHAIN-AGENT] ✅ Agent terminé<br/>[LANGCHAIN-AGENT] 📥 Response payload
Client-->>User: Réponse finale
Note left of Client: [LANGCHAIN-AGENT] 📤 Réponse finale extraite
📋 Prérequis
- Node.js 18+
- Clés API pour :
- OpenAI (GPT-4)
- Brave Search
- OpenWeatherMap
🚀 Installation
- Cloner le repository :
git clone <votre-repo>
cd langchain-custom-mcp-server-adapters-test
- Installer les dépendances :
npm install
- Créer le fichier
.envà partir deenv.example:
cp env.example .env
- Éditer le fichier
.envet ajouter vos clés API :
OPENAI_API_KEY=votre_cle_openai
BRAVE_API_KEY=votre_cle_brave
OPENWEATHER_API_KEY=votre_cle_openweather
OPENAI_MODEL=gpt-4
💻 Utilisation
Mode développement (avec auto-reload)
npm run dev
Lancer le client directement (sans compilation)
npm run client
Note : Ce script utilise
tsxpour exécuter directement les fichiers TypeScript sans compilation, ce qui est plus rapide pour le développement.
Lancer le serveur MCP seul (pour tests)
npm run mcp-server
Compiler le projet
npm run build
Exécuter le projet compilé
npm start
Une fois lancé, vous pouvez poser des questions dans le terminal. Tapez exit ou quit pour quitter.
📁 Structure du projet
langchain-custom-mcp-server-adapters-test/
├── src/
│ ├── index.ts # Point d'entrée principal
│ ├── client.ts # Client LangChain avec chargement automatique des outils MCP
│ ├── mcpServer.ts # Serveur MCP custom (expose les outils search et weather)
│ ├── mcpServerRunner.ts # Runner pour le serveur MCP en mode stdio
│ └── config.ts # Gestion de la configuration
├── dist/ # Fichiers compilés
├── .env # Variables d'environnement (à créer)
├── env.example # Exemple de configuration
├── package.json
├── tsconfig.json
├── ADAPTATION.md # Documentation de l'adaptation avec Context7
└── README.md
🔧 Comment ça fonctionne
1. Serveur MCP Custom
Ce projet utilise un serveur MCP personnalisé (pas un serveur out-of-the-box) :
- Implémenté dans
src/mcpServer.tsavec le SDK@modelcontextprotocol/sdk - Définit manuellement les outils
searchetweather - Implémente la logique métier (appels API externes)
- Lancement local via
mcpServerRunner.tsen mode stdio
Pourquoi custom ?
- Contrôle total sur les outils et leur logique
- Intégration directe avec vos APIs spécifiques
- Personnalisation des réponses et formats
- Logs détaillés pour le debugging
2. Configuration du client MCP
Le serveur MCP est configuré dans client.ts :
const mcpServerConfig = {
searchWeatherServer: {
transport: "stdio" as const,
command: "npx",
args: ["-y", "tsx", join(__dirname, "mcpServerRunner.ts")],
},
};
const mcpClient = new MultiServerMCPClient(mcpServerConfig);
3. Chargement automatique des outils
Les outils sont chargés automatiquement via getTools() :
// Charge TOUS les outils de TOUS les serveurs MCP configurés
const tools = await this.mcpClient.getTools();
Aucune déclaration manuelle nécessaire ! Les outils sont découverts dynamiquement via le protocole MCP.
4. Utilisation avec LangChain 1.0.0
Le projet utilise la nouvelle API de LangChain 1.0.0 avec createAgent() :
import { createAgent, ReactAgent } from "langchain";
// Créer l'agent avec la nouvelle API
this.agent = createAgent({
model: this.model,
tools, // Outils chargés automatiquement
systemPrompt,
});
// Utiliser l'agent
const result = await this.agent.invoke({
messages: [new HumanMessage(question)],
});
Note : LangChain 1.0.0 utilise createAgent() au lieu de createOpenAIFunctionsAgent() et AgentExecutor de la version 0.x.
📦 Versions utilisées
Ce projet utilise les versions 1.0.0 des packages LangChain pour la compatibilité :
@langchain/core:^1.0.0@langchain/mcp-adapters:^1.0.0@langchain/openai:^1.0.0langchain:^1.0.0@modelcontextprotocol/sdk:^1.0.0
📊 Logs détaillés
Le projet inclut des logs complets pour tracer tous les appels :
Préfixes des logs
[MCP-CLIENT]: Client MCP (chargement des outils)[MCP-SERVER]: Serveur MCP (requêtes/réponses)[TOOL:nom]: Outils individuels (search, weather)[LANGCHAIN-AGENT]: Agent LangChain[USER]: Entrées utilisateur[ERROR]: Erreurs
Contenu des logs
Chaque log inclut :
- Payloads de requête : Données complètes envoyées (JSON formaté)
- Payloads de réponse : Données complètes reçues (JSON formaté)
- Métriques de performance : Temps d'exécution, taille des données
- Détails des appels API : Requêtes/réponses des APIs externes
Exemple de logs
[MCP-CLIENT] 🔄 Chargement des outils depuis le serveur MCP...
[MCP-CLIENT] 📤 Request payload: getTools()
[MCP-SERVER] 📥 Requête ListTools reçue
[MCP-SERVER] 📤 Request payload: {"method":"tools/list",...}
[MCP-SERVER] 📥 Response payload: {"tools":[...]}
[MCP-CLIENT] ✅ 2 outils chargés depuis le serveur MCP
[LANGCHAIN-AGENT] 🔄 Invocation de l'agent avec le message utilisateur...
[LANGCHAIN-AGENT] 📤 Request payload (invoke): {"messages":[...]}
[TOOL:search] 🔍 Recherche Brave Search pour: "TypeScript"
[TOOL:search] 📤 API Request payload: {"url":"...","params":{...}}
[TOOL:search] 📥 API Response payload: {"resultsCount":5,...}
[LANGCHAIN-AGENT] ✅ Agent a terminé en 1234ms
🎯 Fonctionnalités
Recherche Web (Brave Search)
L'agent peut rechercher des informations sur le web :
- "Qu'est-ce que TypeScript?"
- "Recherche des nouvelles sur l'IA en 2024"
Météo
L'agent peut obtenir la météo actuelle et les prévisions :
- "Météo à Paris"
- "Quel temps fait-il à Lyon?"
- "Météo 75001"
Requêtes complexes
L'agent peut combiner plusieurs outils pour répondre à des questions complexes :
- "Compare React et Vue.js en 2024" (utilisera la recherche)
- "Météo à Paris et recherche des événements météo cette semaine" (utilisera météo + recherche)
🔄 Ajouter de nouveaux outils
Pour ajouter un nouvel outil au serveur MCP :
-
Ajoutez l'outil dans
mcpServer.ts:- Ajoutez la définition dans
ListToolsRequestSchema - Ajoutez le handler dans
CallToolRequestSchema
- Ajoutez la définition dans
-
C'est tout ! L'outil sera automatiquement chargé et disponible dans LangChain sans modification du code client.
📝 Exemples d'utilisation
> Météo à Paris
🤔 Traitement en cours...
────────────────────────────────────────────────────────────
[USER] 📥 Question reçue: "Météo à Paris"
[LANGCHAIN-AGENT] 🔄 Invocation de l'agent avec le message utilisateur...
[TOOL:weather] 🌤️ Recherche météo pour: "Paris"
[TOOL:weather] 📤 API Request payload (geo): {...}
[TOOL:weather] 📥 API Response payload (geo): {...}
[LANGCHAIN-AGENT] ✅ Agent a terminé en 1234ms
────────────────────────────────────────────────────────────
💬 Réponse:
**Météo actuelle à Paris**
🌡️ Température: 15°C (ressentie: 14°C)
☁️ Conditions: nuageux
💧 Humidité: 65%
📊 Pression: 1013 hPa
💨 Vent: 12.5 km/h NE
**Prévisions (prochaines 24h):**
- lun. 14:00: 16°C, nuageux
- lun. 17:00: 17°C, partiellement nuageux
...
🐛 Dépannage
Erreur "Missing required environment variable"
Vérifiez que votre fichier .env contient toutes les clés API requises.
Erreur "Model not found"
Assurez-vous que votre clé OpenAI a accès à GPT-4. Vous pouvez utiliser gpt-4-turbo-preview ou gpt-3.5-turbo comme alternative.
Erreur de compilation TypeScript
Vérifiez que vous avez installé toutes les dépendances avec npm install.
Le serveur MCP ne démarre pas
Assurez-vous que tsx est disponible. Le projet utilise npx -y tsx pour lancer le serveur, ce qui devrait fonctionner automatiquement.
Erreur "Package subpath './agents' is not defined"
Cette erreur indique que vous utilisez une ancienne version de LangChain. Assurez-vous d'utiliser LangChain 1.0.0 avec la nouvelle API createAgent().
📚 Documentation et ressources
Utilisation de Context7
Ce projet a été développé en utilisant Context7 MCP pour obtenir la documentation de @langchain/mcp-adapters :
-
Résolution de l'ID de la librairie :
mcp_context7_resolve-library-id("langchain-mcp-adapters")Résultat :
/langchain-ai/langchain-mcp-adapters -
Récupération de la documentation :
mcp_context7_get-library-docs( "/langchain-ai/langchain-mcp-adapters", "MultiServerMCPClient getTools usage examples" )
Voir ADAPTATION.md pour plus de détails sur l'adaptation du projet.
Ressources
- LangChain MCP Adapters Documentation
- Model Context Protocol (MCP) Specification
- LangChain.js Documentation
- @langchain/mcp-adapters sur npm
🔍 Différences avec les serveurs MCP out-of-the-box
Ce projet utilise un serveur MCP custom plutôt qu'un serveur pré-existant. Voici pourquoi :
Serveur MCP Custom (ce projet)
✅ Avantages :
- Contrôle total sur les outils et leur logique
- Intégration directe avec vos APIs spécifiques
- Personnalisation des réponses et formats
- Logs détaillés pour le debugging
- Facile à étendre avec de nouveaux outils
Serveurs MCP Out-of-the-box
Vous pouvez également utiliser des serveurs MCP pré-existants :
const mcpServerConfig = {
// Serveur MCP pré-existant (exemple)
math: {
transport: "stdio" as const,
command: "npx",
args: ["-y", "@modelcontextprotocol/server-math"],
},
// Votre serveur custom
searchWeatherServer: {
transport: "stdio" as const,
command: "npx",
args: ["-y", "tsx", mcpServerPath],
},
};
📄 License
ISC
🤝 Contribution
Les contributions sont les bienvenues ! N'hésitez pas à :
- Fork le projet
- Créer une branche pour votre fonctionnalité
- Commiter vos changements
- Pousser vers la branche
- Ouvrir une Pull Request