Skip to main content
Glama
fkom13

MCP SFTP Orchestrator

by fkom13

Transférer plusieurs fichiers/dossiers (SFTP)

task_transfer_multi

Execute multiple SFTP file transfers using glob patterns (*, ?, []) for batch uploads or downloads between local and remote systems.

Instructions

Lance des transferts SFTP multiples avec support de patterns glob (*, ?, []).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
aliasYesAlias du serveur cible.
directionYes
filesYesListe des fichiers à transférer
rappelNoDéfinit un rappel en secondes.

Implementation Reference

  • The inline handler function for the 'task_transfer_multi' tool. It creates a job with the files array, logs it, triggers the SFTP multi-transfer execution, awaits completion or timeout, and returns the result or background notification.
    async (params) => {
        const job = queue.addJob({ 
            type: 'sftp', 
            ...params, 
            status: 'pending',
            files: params.files
        });
        history.logTask(job);
        sftp.executeMultiTransfer(job.id);
    
        const finalJob = await waitForJobCompletion(job.id, config.syncTimeout);
        if (finalJob) {
            return { content: [{ type: "text", text: `Résultat transferts multiples (tâche ${finalJob.id}):\n${JSON.stringify(finalJob, null, 2)}` }] };
        } else {
            return { content: [{ type: "text", text: `Tâche de transferts multiples ${job.id} initiée en arrière-plan.` }] };
        }
    }
  • Input schema definition for the task_transfer_multi tool, including parameters for server alias, direction, list of local/remote file pairs supporting globs, and optional reminder.
    {
        title: "Transférer plusieurs fichiers/dossiers (SFTP)",
        description: "Lance des transferts SFTP multiples avec support de patterns glob (*, ?, []).",
        inputSchema: z.object({
            alias: z.string().describe("Alias du serveur cible."),
            direction: z.enum(['upload', 'download']),
            files: z.array(z.object({
                local: z.string().describe("Chemin local ou pattern glob (ex: /home/*.txt)"),
                remote: z.string().describe("Chemin distant")
            })).describe("Liste des fichiers à transférer"),
            rappel: z.number().optional().describe("Définit un rappel en secondes.")
        })
    },
  • server.js:511-543 (registration)
    Full registration of the task_transfer_multi tool on the MCP server, including name, schema, and handler function.
    server.registerTool(
        "task_transfer_multi",
        {
            title: "Transférer plusieurs fichiers/dossiers (SFTP)",
            description: "Lance des transferts SFTP multiples avec support de patterns glob (*, ?, []).",
            inputSchema: z.object({
                alias: z.string().describe("Alias du serveur cible."),
                direction: z.enum(['upload', 'download']),
                files: z.array(z.object({
                    local: z.string().describe("Chemin local ou pattern glob (ex: /home/*.txt)"),
                    remote: z.string().describe("Chemin distant")
                })).describe("Liste des fichiers à transférer"),
                rappel: z.number().optional().describe("Définit un rappel en secondes.")
            })
        },
        async (params) => {
            const job = queue.addJob({ 
                type: 'sftp', 
                ...params, 
                status: 'pending',
                files: params.files
            });
            history.logTask(job);
            sftp.executeMultiTransfer(job.id);
    
            const finalJob = await waitForJobCompletion(job.id, config.syncTimeout);
            if (finalJob) {
                return { content: [{ type: "text", text: `Résultat transferts multiples (tâche ${finalJob.id}):\n${JSON.stringify(finalJob, null, 2)}` }] };
            } else {
                return { content: [{ type: "text", text: `Tâche de transferts multiples ${job.id} initiée en arrière-plan.` }] };
            }
        }
    );
  • Core helper function executeTransfer that performs the actual SFTP operations. Handles multi-file transfers by looping over job.files, supports glob expansion, upload/download of files and directories, connection management, progress tracking, error handling, and job status updates.
    async function executeTransfer(jobId) {
        const job = queue.getJob(jobId);
        if (!job) return queue.log('error', `Tâche introuvable: ${jobId}`);
    
        let sftp = null;
        try {
            const serverConfig = await serverManager.getServer(job.alias);
            queue.updateJobStatus(jobId, 'running');
    
            sftp = new SftpClient();
    
            // Configuration de la connexion
            const config = {
                host: serverConfig.host,
                port: 22,
                username: serverConfig.user,
                readyTimeout: 20000,
                retries: 3,
                retry_factor: 2,
                retry_minTimeout: 2000
            };
            
            if (serverConfig.keyPath) {
                config.privateKey = await fs.readFile(serverConfig.keyPath);
            } else if (serverConfig.password) {
                config.password = serverConfig.password;
            } else {
                throw new Error(`Aucune méthode d'authentification pour '${job.alias}'.`);
            }
    
            await sftp.connect(config);
            
            // Déterminer si on traite plusieurs fichiers
            const files = job.files || [{ local: job.local, remote: job.remote }];
            const isMultiple = Array.isArray(job.files) && job.files.length > 1;
            
            let successCount = 0;
            let failedFiles = [];
            let totalFiles = 0;
            
            // Traiter chaque fichier
            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                const progress = isMultiple ? ` (${i + 1}/${files.length})` : '';
                
                try {
                    if (job.direction === 'upload') {
                        const localFiles = await expandFileList(file.local);
                        totalFiles += localFiles.length;
                        for (const localFile of localFiles) {
                            queue.log('info', `Transfert${progress}: ${localFile}`);
                            await handleUpload(sftp, localFile, file.remote);
                            successCount++;
                        }
                    } else if (job.direction === 'download') {
                        const downloadedCount = await handleDownload(sftp, file.remote, file.local);
                        totalFiles += downloadedCount;
                        successCount += downloadedCount;
                    }
                } catch (err) {
                    queue.log('error', `Échec transfert ${file.local || file.remote}: ${err.message}`);
                    failedFiles.push({ file: file.local || file.remote, error: err.message });
                }
            }
            
            await sftp.end();
            
            // Génération du rapport
            let status = successCount === totalFiles ? 'completed' : 'partial';
            let output = `Transfert ${job.direction}: ${successCount}/${totalFiles} fichiers réussis`;
            
            if (failedFiles.length > 0) {
                output += `\nÉchecs: ${failedFiles.map(f => f.file).join(', ')}`;
                if (successCount === 0) status = 'failed';
            }
            
            queue.updateJobStatus(jobId, status, { output, failedFiles });
            
        } catch (err) {
            queue.updateJobStatus(jobId, 'failed', { error: err.message });
        } finally {
            if (sftp) {
                try {
                    await sftp.end();
                } catch (e) {
                    // Ignorer les erreurs de fermeture
                }
            }
        }
    }
  • Thin wrapper executeMultiTransfer that retrieves the job and delegates to the core executeTransfer function.
    async function executeMultiTransfer(jobId) {
        const job = queue.getJob(jobId);
        if (!job) return queue.log('error', `Tâche introuvable: ${jobId}`);
        
        // Utilise la même fonction mais avec support multi-fichiers
        return executeTransfer(jobId);
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions glob pattern support which is useful, but doesn't describe critical behaviors: whether transfers are synchronous/asynchronous, error handling, authentication requirements, rate limits, or what happens when transfers fail. For a file transfer tool with mutation capabilities, this leaves significant gaps in understanding how the tool behaves.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient French sentence that communicates the core functionality without waste. It's appropriately sized and front-loaded with the essential information about what the tool does.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a file transfer tool with no annotations and no output schema, the description is incomplete. It doesn't explain what the tool returns, how to monitor transfer progress, error conditions, or authentication requirements. The combination of mutation capability (file transfers), multiple parameters, and lack of structured metadata means the description should provide more operational context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 75%, so the schema documents most parameters well. The description adds minimal value beyond the schema - it mentions glob pattern support which relates to the 'local' parameter's pattern capability, but doesn't explain parameter interactions or provide additional context about how parameters work together. The baseline of 3 is appropriate given the decent schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Lance des transferts SFTP multiples avec support de patterns glob' (Launches multiple SFTP transfers with glob pattern support). It specifies the action (launch transfers), resource (SFTP files/folders), and key capability (glob patterns). However, it doesn't explicitly differentiate from its sibling 'task_transfer' which appears to be a similar single-transfer tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention the sibling 'task_transfer' tool or explain when to choose multiple transfers over single transfers. There's no context about prerequisites, dependencies, or typical use cases for batch SFTP operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/fkom13/mcp-sftp-orchestrator'

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