UNPKG

smart-thinking-mcp

Version:

Un serveur MCP avancé pour le raisonnement multi-dimensionnel, adaptatif et collaboratif

473 lines (462 loc) 25 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const zod_1 = require("zod"); const thought_graph_1 = require("./thought-graph"); const memory_manager_1 = require("./memory-manager"); const tool_integrator_1 = require("./tool-integrator"); const quality_evaluator_1 = require("./quality-evaluator"); const visualizer_1 = require("./visualizer"); const embedding_service_1 = require("./embedding-service"); const metrics_calculator_1 = require("./metrics-calculator"); const verification_memory_1 = require("./verification-memory"); const service_container_1 = require("./services/service-container"); const path_1 = __importDefault(require("path")); const fs_1 = require("fs"); const config_1 = require("./config"); /** * Point d'entrée du serveur MCP Smart-Thinking */ // Protection contre les messages non-JSON envoyés à stdout const originalStdoutWrite = process.stdout.write; // Fonction de gestion des sorties pour éviter les problèmes de types const safeStdoutWrite = function () { const chunk = arguments[0]; if (typeof chunk === 'string') { const trimmed = chunk.trim(); // Si ça ressemble à du JSON mais n'en est pas if ((trimmed.startsWith('{') || trimmed.startsWith('[')) && !isValidJSON(trimmed)) { console.error('[ERREUR] JSON invalide détecté:', chunk); try { const safeMessage = JSON.stringify({ jsonrpc: "2.0", result: { content: [{ type: "text", text: chunk }] } }); return originalStdoutWrite.call(process.stdout, safeMessage, arguments[1], arguments[2]); } catch (e) { console.error('[ERREUR] Impossible de corriger le JSON:', e); process.stderr.write(chunk, arguments[1]); if (typeof arguments[2] === 'function') arguments[2](); return true; } } // Si c'est du texte brut (non-JSON) if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) { console.error('[INFO] Texte non-JSON redirigé vers stderr:', chunk); process.stderr.write(chunk, arguments[1]); if (typeof arguments[2] === 'function') arguments[2](); return true; } } // Comportement normal pour le JSON valide ou les non-strings return originalStdoutWrite.apply(process.stdout, arguments); }; // Remplacer process.stdout.write par notre version sécurisée process.stdout.write = safeStdoutWrite; // Fonction utilitaire pour vérifier la validité JSON function isValidJSON(str) { try { JSON.parse(str); return true; } catch (e) { return false; } } // Récupérer les informations du package.json pour la version const packageInfo = require(path_1.default.join(__dirname, '..', 'package.json')); const version = packageInfo.version || '1.0.3'; // Afficher un message de bienvenue console.error(` ╔══════════════════════════════════════════════════════════════╗ ║ ║ ║ Smart-Thinking MCP Server ║ ║ Un outil de raisonnement multi-dimensionnel avancé ║ ║ ║ ║ Version: ${version} ║ ║ ║ ║ Démarrage du serveur... ║ ║ ║ ╚══════════════════════════════════════════════════════════════╝ `); // Initialisation des services const COHERE_API_KEY = 'DckObDtnnRkPQQK6dwooI7mAB60HmmhNh1OBD23K'; const embeddingService = new embedding_service_1.EmbeddingService(COHERE_API_KEY); const metricsCalculator = new metrics_calculator_1.MetricsCalculator(); const qualityEvaluator = new quality_evaluator_1.QualityEvaluator(); const toolIntegrator = new tool_integrator_1.ToolIntegrator(); const thoughtGraph = new thought_graph_1.ThoughtGraph(undefined, embeddingService, qualityEvaluator); const memoryManager = new memory_manager_1.MemoryManager(embeddingService); const visualizer = new visualizer_1.Visualizer(); const verificationMemory = verification_memory_1.VerificationMemory.getInstance(); // Configuration des dépendances verificationMemory.setEmbeddingService(embeddingService); const serviceContainer = service_container_1.ServiceContainer.getInstance(); serviceContainer.initializeServices(toolIntegrator, metricsCalculator, embeddingService); const verificationService = serviceContainer.getVerificationService(); qualityEvaluator.setVerificationService(verificationService); // Configuration des écouteurs d'événements thoughtGraph.on('calculations-verified', (data) => { console.error(`Smart-Thinking: Calculs vérifiés pour la pensée ${data.thoughtId}`); }); // Créer une instance du serveur MCP const server = new mcp_js_1.McpServer({ name: "smart-thinking-mcp", version: version, capabilities: {} }); // Schémas Zod pour les options avancées const FilterOptionsSchema = zod_1.z.object({ nodeTypes: zod_1.z.array(zod_1.z.enum(['regular', 'revision', 'meta', 'hypothesis', 'conclusion'])).optional(), connectionTypes: zod_1.z.array(zod_1.z.enum(['supports', 'contradicts', 'refines', 'branches', 'derives', 'associates'])).optional(), metricThresholds: zod_1.z.object({ confidence: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional(), relevance: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional(), quality: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional() }).optional(), textSearch: zod_1.z.string().optional(), dateRange: zod_1.z.tuple([zod_1.z.date(), zod_1.z.date()]).optional(), customFilters: zod_1.z.record(zod_1.z.any()).optional() }).optional(); const InteractivityOptionsSchema = zod_1.z.object({ zoomable: zod_1.z.boolean().optional(), draggable: zod_1.z.boolean().optional(), selectable: zod_1.z.boolean().optional(), tooltips: zod_1.z.boolean().optional(), expandableNodes: zod_1.z.boolean().optional(), initialZoom: zod_1.z.number().optional(), zoomRange: zod_1.z.tuple([zod_1.z.number(), zod_1.z.number()]).optional(), highlightOnHover: zod_1.z.boolean().optional() }).optional(); /** * Schéma des paramètres pour l'outil smartthinking * ---------------------------------------------- * Ce schéma définit tous les paramètres que Claude peut utiliser * pour interagir avec l'outil Smart-Thinking */ const SmartThinkingParamsSchema = zod_1.z.object({ thought: zod_1.z.string().describe('Le contenu de la pensée à analyser - PARAMÈTRE OBLIGATOIRE - Cette pensée sera ajoutée au graphe de raisonnement'), thoughtType: zod_1.z.enum(['regular', 'revision', 'meta', 'hypothesis', 'conclusion']).default('regular') .describe('Type de pensée dans le graphe de raisonnement - Détermine la fonction de cette pensée'), connections: zod_1.z.array(zod_1.z.any()).default([]) .describe('Connexions à d\'autres pensées - Permet de lier cette pensée à d\'autres pensées du graphe'), requestSuggestions: zod_1.z.boolean().default(false) .describe('Demander des suggestions d\'amélioration du raisonnement'), generateVisualization: zod_1.z.boolean().default(false) .describe('Générer une visualisation du graphe de pensée'), visualizationType: zod_1.z.enum(['graph', 'chronological', 'thematic', 'hierarchical', 'force', 'radial']).default('graph') .describe('Type de visualisation à générer'), suggestTools: zod_1.z.boolean().default(true) .describe('Suggérer des outils MCP pertinents pour cette étape du raisonnement'), sessionId: zod_1.z.string().optional() .describe('Identifiant de session pour maintenir l\'état entre les appels'), userId: zod_1.z.string().optional() .describe('Identifiant de l\'utilisateur pour la personnalisation'), help: zod_1.z.boolean().default(true) .describe('Afficher le guide d\'utilisation complet'), requestVerification: zod_1.z.boolean().default(false) .describe('Demander explicitement une vérification des informations'), containsCalculations: zod_1.z.boolean().default(false) .describe('Indique si la pensée contient des calculs à vérifier'), visualizationOptions: zod_1.z.object({ clusterBy: zod_1.z.enum(['type', 'theme', 'metric', 'connectivity']).optional() .describe('Critère de regroupement des nœuds en clusters'), direction: zod_1.z.enum(['LR', 'RL', 'TB', 'BT']).optional().default('TB') .describe('Direction de la disposition hiérarchique'), centerNode: zod_1.z.string().optional() .describe('ID du nœud central pour les visualisations radiales ou hiérarchiques'), maxDepth: zod_1.z.number().optional() .describe('Profondeur maximale pour les visualisations hiérarchiques ou radiales'), filters: FilterOptionsSchema .describe('Options de filtrage des nœuds et des liens'), interactivity: InteractivityOptionsSchema .describe('Options d\'interactivité pour la visualisation') }).optional() .describe('Options avancées pour la visualisation') }); /** * Définition de l'outil smartthinking * ----------------------------------- * Cet outil permet à Claude d'utiliser le système de raisonnement Smart-Thinking */ server.tool('smartthinking', SmartThinkingParamsSchema.shape, async (params) => { // Si help=true et aucune pensée n'est fournie, afficher le guide d'utilisation if (params.help && !params.thought) { return { content: [ { type: 'text', text: `# Smart-Thinking - Guide d'utilisation Smart-Thinking est un outil de raisonnement multi-dimensionnel qui organise les pensées en graphe plutôt qu'en séquence linéaire, permettant une analyse plus riche et interconnectée des problèmes complexes. ## Paramètres principaux - **thought** (obligatoire): La pensée à analyser - **thoughtType**: Type de pensée (regular, revision, meta, hypothesis, conclusion) - **connections**: Liens vers d'autres pensées [{targetId, type, strength}] - **requestSuggestions**: Demander des suggestions d'amélioration - **generateVisualization**: Créer une représentation visuelle du graphe - **requestVerification**: Vérifier les informations contenues dans la pensée - **containsCalculations**: Activer la vérification des calculs mathématiques ## Types de pensées - **regular**: Pensée standard pour développer une idée - **meta**: Réflexion sur le processus de raisonnement lui-même - **hypothesis**: Formulation d'une hypothèse à tester - **revision**: Modification d'une pensée précédente - **conclusion**: Synthèse finale ou déduction ## Types de connexions - **supports**: Pensée qui renforce une autre - **contradicts**: Pensée qui s'oppose à une autre - **refines**: Pensée qui précise ou améliore une autre - **branches**: Pensée qui explore une nouvelle direction - **derives**: Pensée qui découle logiquement d'une autre - **associates**: Pensée simplement liée à une autre ## Types de visualisations - **graph**: Réseau standard de connexions - **chronological**: Timeline d'évolution du raisonnement - **thematic**: Clusters par thèmes similaires - **hierarchical**: Structure arborescente - **force**: Disposition basée sur forces d'attraction/répulsion - **radial**: Cercles concentriques autour d'une pensée centrale ## Exemple d'utilisation \`\`\` Utilise l'outil smartthinking avec: thought: "L'intelligence artificielle transformera profondément le marché du travail" thoughtType: "hypothesis" generateVisualization: true \`\`\` ` } ] }; } // Vérifier si le paramètre 'thought' est présent if (!params.thought) { console.error('Smart-Thinking: ERROR - Paramètre "thought" manquant'); return { isError: true, content: [ { type: 'text', text: JSON.stringify({ error: "Le paramètre 'thought' est obligatoire.", message: "Vous devez fournir une pensée à analyser." }, null, 2) } ] }; } console.error('Smart-Thinking: traitement de la pensée:', params.thought); // Traitement de la pensée const preliminaryResult = await verificationService.performPreliminaryVerification(params.thought, !!params.containsCalculations); const thoughtId = thoughtGraph.addThought(preliminaryResult.preverifiedThought, params.thoughtType, params.connections); // Évaluation de la qualité const qualityMetrics = qualityEvaluator.evaluate(thoughtId, thoughtGraph); thoughtGraph.updateThoughtMetrics(thoughtId, qualityMetrics); // Détermination du statut de vérification let verificationStatus = 'unverified'; let certaintySummary = "Information non vérifiée"; if (preliminaryResult.verificationInProgress) { if (preliminaryResult.initialVerification) { verificationStatus = 'partially_verified'; certaintySummary = `Calculs vérifiés préalablement, niveau de confiance initial: ${Math.round(qualityMetrics.confidence * 100)}%.`; } else { verificationStatus = 'verification_in_progress'; certaintySummary = "Vérification des calculs en cours..."; } } else if (params.containsCalculations) { certaintySummary = `Information non vérifiée, niveau de confiance: ${Math.round(qualityMetrics.confidence * 100)}%. Aucun calcul n'a été détecté pour vérification.`; } else { certaintySummary = `Information non vérifiée, niveau de confiance: ${Math.round(qualityMetrics.confidence * 100)}%. Pour une vérification complète, utilisez le paramètre requestVerification=true.`; } // Préparation de la réponse initiale const response = { thoughtId, thought: preliminaryResult.preverifiedThought, thoughtType: params.thoughtType || 'regular', qualityMetrics, isVerified: preliminaryResult.initialVerification, verificationStatus: verificationStatus, certaintySummary: certaintySummary, reliabilityScore: metricsCalculator.calculateReliabilityScore(qualityMetrics, preliminaryResult.initialVerification ? 'partially_verified' : 'unverified', preliminaryResult.verifiedCalculations, undefined // Pas de score précédent pour la première pensée ) }; // Traitement des calculs vérifiés if (preliminaryResult.verifiedCalculations && preliminaryResult.verifiedCalculations.length > 0) { response.isVerified = true; response.verificationStatus = 'partially_verified'; response.verification = { status: preliminaryResult.initialVerification ? 'partially_verified' : 'inconclusive', confidence: qualityMetrics.confidence, sources: ['Vérification préliminaire des calculs'], verificationSteps: ['Détection et vérification préliminaire des expressions mathématiques'], verifiedCalculations: preliminaryResult.verifiedCalculations }; const correctCalculations = preliminaryResult.verifiedCalculations.filter((calc) => calc.isCorrect).length; const totalCalculations = preliminaryResult.verifiedCalculations.length; if (totalCalculations > 0) { const calculationAccuracy = correctCalculations / totalCalculations; response.reliabilityScore = (qualityMetrics.confidence * 0.7) + (calculationAccuracy * 0.3); } } // Vérification des informations précédemment vérifiées const thought = thoughtGraph.getThought(thoughtId); // Récupérer les IDs des pensées connectées const connectedThoughtIds = params.connections?.map(conn => conn.targetId) || []; // Appel amélioré avec type de pensée et connexions const previousResult = await verificationService.checkPreviousVerification(thought?.content || params.thought, params.sessionId || 'default', params.thoughtType || 'regular', connectedThoughtIds); if (previousResult.previousVerification) { response.isVerified = previousResult.isVerified; response.verificationStatus = previousResult.verificationStatus; response.certaintySummary = previousResult.certaintySummary; response.verification = previousResult.verification; response.reliabilityScore = metricsCalculator.calculateReliabilityScore(qualityMetrics, previousResult.verificationStatus, preliminaryResult.verifiedCalculations, response.reliabilityScore // Utiliser le score déjà calculé comme référence ); if (thought) { thought.metadata.previousVerification = { similarity: previousResult.previousVerification.similarity, status: previousResult.previousVerification.status, confidence: previousResult.previousVerification.confidence, timestamp: previousResult.previousVerification.timestamp }; } } // Vérification approfondie si nécessaire if ((qualityMetrics.confidence < config_1.VerificationConfig.CONFIDENCE.VERIFICATION_REQUIRED || params.requestVerification) && !previousResult.previousVerification) { console.error('Smart-Thinking: Confiance faible ou vérification demandée, vérification complète nécessaire...'); try { if (thought) { response.verificationStatus = 'verification_in_progress'; const verification = await verificationService.deepVerify(thought, params.containsCalculations || false, false, params.sessionId || 'default'); response.verification = verification; response.isVerified = verification.status === 'verified' || verification.status === 'partially_verified' || (!!verification.verifiedCalculations && verification.verifiedCalculations.length > 0); response.verificationStatus = verification.status; response.reliabilityScore = metricsCalculator.calculateReliabilityScore(qualityMetrics, verification.status, verification.verifiedCalculations, response.reliabilityScore // Utiliser le score déjà calculé comme référence ); response.certaintySummary = metricsCalculator.generateCertaintySummary(verification.status, response.reliabilityScore); if (verification.verifiedCalculations && verification.verifiedCalculations.length > 0) { response.thought = verificationService.annotateThoughtWithVerifications(response.thought, verification.verifiedCalculations); thoughtGraph.updateThoughtContent(thoughtId, response.thought); } } } catch (error) { console.error('Smart-Thinking: Erreur lors de la vérification complète:', error); response.verificationStatus = 'inconclusive'; response.certaintySummary = `Erreur lors de la vérification: ${error instanceof Error ? error.message : 'Erreur inconnue'}. Niveau de confiance: ${Math.round(qualityMetrics.confidence * 100)}%.`; } } // Fonctionnalités additionnelles selon les paramètres if (params.suggestTools) { response.suggestedTools = toolIntegrator.suggestTools(params.thought); } // Génération de visualisation si demandée if (params.generateVisualization) { try { const visualizationType = params.visualizationType || 'graph'; const visualizationOptions = params.visualizationOptions || {}; const generateVisualizationAsync = async () => { switch (visualizationType) { case 'chronological': return await Promise.resolve(visualizer.generateChronologicalVisualization(thoughtGraph)); case 'thematic': return await Promise.resolve(visualizer.generateThematicVisualization(thoughtGraph)); case 'hierarchical': return await Promise.resolve(visualizer.generateHierarchicalVisualization(thoughtGraph, visualizationOptions.centerNode, { direction: visualizationOptions.direction, levelSeparation: 100, clusterBy: visualizationOptions.clusterBy })); case 'force': return await Promise.resolve(visualizer.generateForceDirectedVisualization(thoughtGraph, { clusterBy: visualizationOptions.clusterBy, forceStrength: 0.5, centerNode: visualizationOptions.centerNode })); case 'radial': return await Promise.resolve(visualizer.generateRadialVisualization(thoughtGraph, visualizationOptions.centerNode, { maxDepth: visualizationOptions.maxDepth, radialDistance: 120 })); case 'graph': default: return await Promise.resolve(visualizer.generateVisualization(thoughtGraph, thoughtId)); } }; response.visualization = await generateVisualizationAsync(); if (visualizationOptions.filters && response.visualization) { response.visualization = visualizer.applyFilters(response.visualization, visualizationOptions.filters); } if (response.visualization && response.visualization.nodes.length > 100) { response.visualization = visualizer.simplifyVisualization(response.visualization); } } catch (error) { console.error('Smart-Thinking: Erreur lors de la génération de la visualisation:', error); } } // Récupération des mémoires et suggestions const relevantMemoriesPromise = memoryManager.getRelevantMemories(params.thought); response.suggestedNextSteps = thoughtGraph.suggestNextSteps(); response.relevantMemories = await relevantMemoriesPromise; // Stockage de la pensée dans la mémoire si sa qualité est suffisante if (response.qualityMetrics.quality > 0.7) { const tags = params.thought .toLowerCase() .split(/\W+/) .filter((word) => word.length > 4) .slice(0, 5); memoryManager.addMemory(params.thought, tags); } console.error('Smart-Thinking: pensée traitée avec succès, id:', thoughtId); // Retour de la réponse formatée pour MCP return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; }); // Initialisation du transport const transport = new stdio_js_1.StdioServerTransport(); // Création du répertoire data async function ensureDataDirExists() { const dataDir = path_1.default.join(process.cwd(), 'data'); try { await fs_1.promises.mkdir(dataDir, { recursive: true }); console.error('Smart-Thinking: Répertoire data créé ou confirmé'); } catch (error) { console.error('Smart-Thinking: Erreur lors de la création du répertoire data:', error); } } // Démarrage du serveur async function start() { try { await ensureDataDirExists(); await server.connect(transport); console.error('Smart-Thinking MCP Server démarré avec succès.'); console.error('L\'outil "smartthinking" est maintenant disponible pour Claude.'); } catch (error) { console.error('Erreur lors du démarrage du serveur:', error); process.exit(1); } } start(); //# sourceMappingURL=index.js.map