Skip to main content
Glama
GUIDE-NOUVEAUX-OUTILS.md8.29 kB
# Guide des Nouveaux Outils - Système ToolRegistry Ce document explique comment créer et enregistrer de nouveaux outils dans le système ToolRegistry. ## 📋 Vue d'Ensemble Le système ToolRegistry permet : - **Enregistrement automatique** des outils via convention de nommage - **Gestion centralisée** de tous les outils - **Exécution unifiée** avec validation des paramètres - **Découverte dynamique** au démarrage ## 🛠️ Création d'un Nouvel Outil ### Étape 1 : Structure de Fichier Créez un nouveau fichier dans `src/tools/` avec la convention suivante : ``` src/tools/[catégorie]/[nom-outil].ts ``` Exemple : `src/tools/graph/create-entities.ts` ### Étape 2 : Définition de l'Outil Chaque outil doit exporter deux éléments : 1. **Définition de l'outil** (`*Tool`) : Schéma d'entrée et métadonnées 2. **Handler de l'outil** (`*Handler`) : Fonction d'exécution ```typescript // Exemple : src/tools/graph/create-entities.ts import { Tool } from "@modelcontextprotocol/sdk/types.js"; import { knowledgeGraphManager } from "../../knowledge-graph/manager.js"; // 1. Définition de l'outil export const createEntitiesTool: Tool = { name: "create_entities", description: "Create multiple new entities in the knowledge graph", inputSchema: { type: "object", properties: { entities: { type: "array", items: { type: "object", properties: { name: { type: "string", description: "The name of the entity" }, entityType: { type: "string", description: "The type of the entity" }, observations: { type: "array", items: { type: "string" }, description: "An array of observation contents associated with the entity" }, }, required: ["name", "entityType", "observations"], }, }, }, required: ["entities"], }, }; // 2. Handler de l'outil export async function createEntitiesHandler(args: any): Promise<any> { // Validation des arguments if (!args.entities || !Array.isArray(args.entities)) { throw new Error("The 'entities' parameter is required and must be an array"); } // Exécution de la logique métier const result = await knowledgeGraphManager.createEntities(args.entities); // Formatage de la réponse return { content: [ { type: "text", text: JSON.stringify(result, null, 2) } ] }; } ``` ### Étape 3 : Convention de Nommage - **Nom de l'outil** : `snake_case` (ex: `create_entities`) - **Nom du fichier** : `kebab-case` (ex: `create-entities.ts`) - **Variables exportées** : - `[nom]Tool` : Définition de l'outil - `[nom]Handler` : Handler de l'outil ## 🔄 Enregistrement Automatique Le système découvre automatiquement les outils qui suivent la convention : 1. **Recherche récursive** dans `src/tools/` 2. **Filtrage** des fichiers `.ts` avec `*Tool` et `*Handler` exports 3. **Enregistrement** dans le ToolRegistry ### Fichier de Configuration : `src/core/registry.ts` ```typescript // Exemple d'enregistrement automatique export async function initializeAutoRegistry(options: { verbose?: boolean } = {}): Promise<number> { const toolFiles = await discoverToolFiles(); let registeredCount = 0; for (const file of toolFiles) { try { const module = await import(file); // Recherche des exports Tool et Handler const toolName = Object.keys(module).find(key => key.endsWith('Tool')); const handlerName = Object.keys(module).find(key => key.endsWith('Handler')); if (toolName && handlerName) { const tool = module[toolName]; const handler = module[handlerName]; toolRegistry.register(tool, handler); registeredCount++; if (options.verbose) { console.log(`✅ Outil enregistré: ${tool.name}`); } } } catch (error) { console.error(`❌ Erreur lors de l'enregistrement de ${file}:`, error); } } return registeredCount; } ``` ## 🧪 Tests des Nouveaux Outils ### Test Unitaire ```typescript // test-nouvel-outil.js import { toolRegistry } from './build/core/tool-registry.js'; async function testNouvelOutil() { console.log('🧪 Test du nouvel outil...'); // Vérifier que l'outil est enregistré if (!toolRegistry.hasTool('nouvel_outil')) { console.error('❌ L\'outil n\'est pas enregistré'); return false; } // Tester l'exécution avec des arguments valides try { const result = await toolRegistry.execute('nouvel_outil', { // arguments valides }); console.log('✅ Exécution réussie:', result); return true; } catch (error) { console.error('❌ Erreur d\'exécution:', error); return false; } } ``` ### Test d'Intégration Ajoutez votre test à `run-all-tests.js` : ```javascript const testFiles = [ // ... tests existants 'test-nouvel-outil.js', // Ajoutez votre test ici ]; ``` ## 📊 Bonnes Pratiques ### 1. Validation des Arguments - Toujours valider les types et la présence des arguments requis - Fournir des messages d'erreur clairs ### 2. Gestion des Erreurs - Capturer et logger les erreurs - Retourner des erreurs structurées ### 3. Formatage des Réponses - Retourner toujours un objet avec `content` - Utiliser `type: "text"` pour les réponses textuelles - Formater JSON avec indentation pour la lisibilité ### 4. Documentation - Documenter le schéma d'entrée dans la description - Inclure des exemples d'utilisation ## 🔍 Dépannage ### Problème : L'outil n'est pas enregistré **Solution :** 1. Vérifier la convention de nommage (`*Tool` et `*Handler`) 2. Vérifier que le fichier est dans `src/tools/` 3. Vérifier les erreurs d'import dans `registry.ts` ### Problème : Erreur d'exécution **Solution :** 1. Vérifier la validation des arguments 2. Vérifier les dépendances (imports) 3. Tester le handler isolément ### Problème : Schéma invalide **Solution :** 1. Vérifier la structure du schéma JSON 2. Tester avec `ajv` ou un validateur JSON ## 📚 Exemples Complets ### Exemple 1 : Outil Simple ```typescript // src/tools/util/hello-world.ts import { Tool } from "@modelcontextprotocol/sdk/types.js"; export const helloWorldTool: Tool = { name: "hello_world", description: "A simple hello world tool", inputSchema: { type: "object", properties: { name: { type: "string", description: "Name to greet" } }, required: ["name"] } }; export async function helloWorldHandler(args: any): Promise<any> { if (!args.name) { throw new Error("The 'name' parameter is required"); } return { content: [{ type: "text", text: `Hello, ${args.name}!` }] }; } ``` ### Exemple 2 : Outil avec Logique Complexe ```typescript // src/tools/rag/advanced-search.ts import { Tool } from "@modelcontextprotocol/sdk/types.js"; import { searchEngine } from "../../rag/searcher.js"; export const advancedSearchTool: Tool = { name: "advanced_search", description: "Advanced semantic search with filters", inputSchema: { type: "object", properties: { query: { type: "string" }, filters: { type: "object", properties: { language: { type: "string" }, minScore: { type: "number" }, maxResults: { type: "number" } } } }, required: ["query"] } }; export async function advancedSearchHandler(args: any): Promise<any> { const { query, filters = {} } = args; if (!query || typeof query !== 'string') { throw new Error("The 'query' parameter is required and must be a string"); } const results = await searchEngine.advancedSearch(query, filters); return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] }; } ``` ## 🚀 Prochaines Étapes 1. **Créer votre outil** suivant la convention 2. **Tester localement** avec les tests unitaires 3. **Ajouter à la suite de tests** principale 4. **Documenter** dans le README 5. **Soumettre** pour revue --- **Dernière mise à jour** : 27/12/2025 **Version du système** : ToolRegistry v1.0.0 **Statut** : Production Ready 🚀

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ali-48/rag-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server