Skip to main content
Glama

update_project

Update project indexing with incremental RAG capabilities to maintain current semantic search across codebases by processing modified files and adjusting embeddings.

Instructions

Mettre à jour l'indexation d'un projet (indexation incrémentale) avec options RAG

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_pathYesChemin absolu vers le projet à mettre à jour
file_patternsNoPatterns de fichiers à inclure
recursiveNoParcourir les sous-dossiers récursivement
embedding_providerNoFournisseur d'embeddings (fake, ollama, sentence-transformers)fake
embedding_modelNoModèle d'embeddings (pour Ollama: 'nomic-embed-text', 'all-minilm', etc.)nomic-embed-text
chunk_sizeNoTaille des chunks pour le découpage (en tokens)
chunk_overlapNoChevauchement entre les chunks (en tokens)

Implementation Reference

  • Registers the update_project tool (along with other RAG tools) using toolRegistry.register(updateProjectTool, updateProjectHandler). This is called during initialization.
    export function registerRagTools() { console.log("📝 Enregistrement des outils RAG..."); // Enregistrer index_project try { toolRegistry.register(indexProjectTool, indexProjectHandler); console.log(`✅ Outil enregistré: ${indexProjectTool.name}`); } catch (error) { console.error(`❌ Erreur lors de l'enregistrement de ${indexProjectTool.name}:`, error); } // Enregistrer search_code try { toolRegistry.register(searchCodeTool, searchCodeHandler); console.log(`✅ Outil enregistré: ${searchCodeTool.name}`); } catch (error) { console.error(`❌ Erreur lors de l'enregistrement de ${searchCodeTool.name}:`, error); } // Enregistrer manage_projects try { toolRegistry.register(manageProjectsTool, manageProjectsHandler); console.log(`✅ Outil enregistré: ${manageProjectsTool.name}`); } catch (error) { console.error(`❌ Erreur lors de l'enregistrement de ${manageProjectsTool.name}:`, error); } // Enregistrer update_project try { toolRegistry.register(updateProjectTool, updateProjectHandler); console.log(`✅ Outil enregistré: ${updateProjectTool.name}`); } catch (error) { console.error(`❌ Erreur lors de l'enregistrement de ${updateProjectTool.name}:`, error); } console.log(`🎉 Outils RAG terminés. Outils enregistrés au total: ${toolRegistry.size()}`); }
  • Tool schema definition for 'update_project', including input schema with project_path (required), file_patterns, and recursive options.
    export const updateProjectTool = { name: "update_project", description: "Mettre à jour l'indexation d'un projet (indexation incrémentale) avec options RAG", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Chemin absolu vers le projet à mettre à jour" }, file_patterns: { type: "array", items: { type: "string" }, description: "Patterns de fichiers à inclure", default: ["**/*.{js,ts,py,md,txt,json,yaml,yml,html,css,scss}"] }, recursive: { type: "boolean", description: "Parcourir les sous-dossiers récursivement", default: true } }, required: ["project_path"] }, };
  • Main handler for the update_project tool. Validates project_path, loads RAG config defaults and limits, configures embeddings, calls core updateProject, and formats response as MCP content.
    export const updateProjectHandler = async (args) => { if (!args.project_path || typeof args.project_path !== 'string') { throw new Error("The 'project_path' parameter is required and must be a string"); } // Charger la configuration const configManager = getRagConfigManager(); const defaults = configManager.getDefaults(); // Utiliser les valeurs par défaut de la configuration const file_patterns = args.file_patterns || defaults.file_patterns; const recursive = args.recursive !== undefined ? args.recursive : defaults.recursive; const embedding_provider = defaults.embedding_provider; const embedding_model = defaults.embedding_model; // Appliquer les limites aux valeurs numériques de la configuration const chunk_size = configManager.applyLimits('chunk_size', defaults.chunk_size); const chunk_overlap = configManager.applyLimits('chunk_overlap', defaults.chunk_overlap); // Configurer le fournisseur d'embeddings setEmbeddingProvider(embedding_provider, embedding_model); const options = { filePatterns: file_patterns, recursive: recursive, chunkSize: chunk_size, chunkOverlap: chunk_overlap }; try { const result = await updateProject(args.project_path, options); return { content: [{ type: "text", text: JSON.stringify({ ...result, config_used: { embedding_provider, embedding_model, chunk_size, chunk_overlap, recursive, file_patterns_count: file_patterns.length } }, null, 2) }] }; } catch (error) { console.error("Error in update_project tool:", error); throw error; } };
  • Core helper function implementing incremental project update using Git status for changed/added/deleted files, intelligent chunking, embedding, and vector store updates/deletes.
    export async function updateProject(projectPath, options = {}) { const { filePatterns = ["**/*.{js,ts,py,md,txt,json,yaml,yml,html,css,scss}"], recursive = true, chunkSize = 1000, chunkOverlap = 200, } = options; const stats = { totalFiles: 0, indexedFiles: 0, ignoredFiles: 0, errors: 0, chunksCreated: 0, modifiedFiles: 0, deletedFiles: 0, unchangedFiles: 0, }; try { // Vérifier que le projet existe if (!fs.existsSync(projectPath)) { throw new Error(`Project path does not exist: ${projectPath}`); } // Vérifier si c'est un dépôt Git const isGitRepo = await isGitRepository(projectPath); if (!isGitRepo) { console.error(`Project ${projectPath} is not a Git repository, performing full reindex`); const fullStats = await indexProject(projectPath, options); return { ...fullStats, modifiedFiles: fullStats.indexedFiles, deletedFiles: 0, unchangedFiles: 0, }; } // Récupérer les fichiers modifiés depuis le dernier commit const changedFiles = await getChangedFiles(projectPath); // Récupérer tous les fichiers du projet const allFiles = await fg(filePatterns, { cwd: projectPath, absolute: true, dot: false, onlyFiles: true, followSymbolicLinks: false, ...(recursive ? {} : { deep: 1 }), }); stats.totalFiles = allFiles.length; // Traiter les fichiers supprimés const deletedFiles = changedFiles.deleted || []; for (const filePath of deletedFiles) { try { await deleteFileFromIndex(projectPath, filePath); stats.deletedFiles++; console.error(`Deleted from index: ${filePath}`); } catch (error) { console.error(`Error deleting file ${filePath} from index:`, error); stats.errors++; } } // Traiter les fichiers modifiés et ajoutés const filesToProcess = [...(changedFiles.modified || []), ...(changedFiles.added || [])]; for (const filePath of filesToProcess) { try { // Vérifier si le fichier doit être ignoré if (shouldIgnoreFile(filePath, projectPath)) { stats.ignoredFiles++; continue; } // Vérifier si le fichier existe toujours if (!fs.existsSync(filePath)) { stats.deletedFiles++; await deleteFileFromIndex(projectPath, filePath); continue; } // Lire le contenu du fichier const content = fs.readFileSync(filePath, "utf8"); // Ignorer les fichiers vides ou trop petits if (content.trim().length < 10) { stats.ignoredFiles++; continue; } // Détecter le type de contenu et le langage const detection = detectContentType(filePath, content); const contentType = detection.contentType; const language = detection.language; // Découper en chunks de manière intelligente const chunks = chunkSize > 0 ? await chunkIntelligently(content, filePath, contentType, language, chunkSize, chunkOverlap) : [content]; // Supprimer les anciens chunks de ce fichier await deleteFileFromIndex(projectPath, filePath); // Stocker chaque chunk dans le vector store avec métadonnées for (let i = 0; i < chunks.length; i++) { const chunk = chunks[i]; const chunkFilePath = chunks.length > 1 ? `${filePath}#chunk${i}` : filePath; await embedAndStore(projectPath, chunkFilePath, chunk, { chunkIndex: i, totalChunks: chunks.length, contentType: contentType, language: language, fileExtension: filePath.split('.').pop() || undefined, linesCount: chunk.split('\n').length, role: contentType === 'code' ? 'core' : contentType === 'doc' ? 'example' : contentType === 'config' ? 'template' : 'other' }); stats.chunksCreated++; } stats.indexedFiles++; stats.modifiedFiles++; // Log progress if (stats.indexedFiles % 10 === 0) { console.error(`Indexed ${stats.indexedFiles}/${filesToProcess.length} changed files, ${stats.chunksCreated} chunks...`); } } catch (error) { console.error(`Error processing file ${filePath}:`, error); stats.errors++; } } // Compter les fichiers inchangés stats.unchangedFiles = stats.totalFiles - (stats.modifiedFiles + stats.deletedFiles + stats.ignoredFiles); console.error(`Incremental reindex completed for ${projectPath}`); console.error(` Total files: ${stats.totalFiles}`); console.error(` Modified/added: ${stats.modifiedFiles}`); console.error(` Deleted: ${stats.deletedFiles}`); console.error(` Unchanged: ${stats.unchangedFiles}`); console.error(` Chunks created: ${stats.chunksCreated}`); console.error(` Ignored: ${stats.ignoredFiles}`); console.error(` Errors: ${stats.errors}`); return stats; } catch (error) { console.error(`Error updating project ${projectPath}:`, error); throw error; }

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