smart-thinking-mcp
Version:
Un serveur MCP avancé pour le raisonnement multi-dimensionnel, adaptatif et collaboratif
473 lines (462 loc) • 25 kB
JavaScript
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
;