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