Skip to main content
Glama

ssh_copy_file

Copy files between local systems and remote servers or between remote servers using SSH connections. Supports automatic directory creation for target paths.

Instructions

Copy files between local and remote servers or between remote servers

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sourceConnectionIdYesSource SSH connection ID (use "local" for local files)
sourcePathYesSource file path
targetConnectionIdYesTarget SSH connection ID (use "local" for local files)
targetPathYesTarget file path
createDirectoriesNoCreate target directories if they don't exist

Implementation Reference

  • The handler function that executes the ssh_copy_file tool. It parses input with CopyFileSchema, handles four copy scenarios (local-local, local-remote, remote-local, remote-remote) using fs.copyFile, NodeSSH.putFile/getFile, creates directories if needed, and uses temp file for remote-remote transfers.
    private async handleSSHCopyFile(args: unknown) { const params = CopyFileSchema.parse(args); try { // Handle different copy scenarios if (params.sourceConnectionId === 'local' && params.targetConnectionId === 'local') { // Local to local copy await fs.copyFile(params.sourcePath, params.targetPath); return { content: [ { type: 'text', text: `Successfully copied ${params.sourcePath} to ${params.targetPath} (local to local)`, }, ], }; } else if (params.sourceConnectionId === 'local') { // Local to remote const targetSSH = connectionPool.get(params.targetConnectionId); if (!targetSSH) { throw new McpError( ErrorCode.InvalidParams, `Target connection ID '${params.targetConnectionId}' not found` ); } if (params.createDirectories) { const targetDir = path.dirname(params.targetPath); await targetSSH.execCommand(`mkdir -p "${targetDir}"`); } await targetSSH.putFile(params.sourcePath, params.targetPath); return { content: [ { type: 'text', text: `Successfully copied ${params.sourcePath} to ${params.targetConnectionId}:${params.targetPath}`, }, ], }; } else if (params.targetConnectionId === 'local') { // Remote to local const sourceSSH = connectionPool.get(params.sourceConnectionId); if (!sourceSSH) { throw new McpError( ErrorCode.InvalidParams, `Source connection ID '${params.sourceConnectionId}' not found` ); } if (params.createDirectories) { const targetDir = path.dirname(params.targetPath); await fs.mkdir(targetDir, { recursive: true }); } await sourceSSH.getFile(params.targetPath, params.sourcePath); return { content: [ { type: 'text', text: `Successfully copied ${params.sourceConnectionId}:${params.sourcePath} to ${params.targetPath}`, }, ], }; } else { // Remote to remote const sourceSSH = connectionPool.get(params.sourceConnectionId); const targetSSH = connectionPool.get(params.targetConnectionId); if (!sourceSSH) { throw new McpError( ErrorCode.InvalidParams, `Source connection ID '${params.sourceConnectionId}' not found` ); } if (!targetSSH) { throw new McpError( ErrorCode.InvalidParams, `Target connection ID '${params.targetConnectionId}' not found` ); } // Use a temporary local file for remote-to-remote transfer const tempFile = `/tmp/mcp-ssh-temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; try { await sourceSSH.getFile(tempFile, params.sourcePath); if (params.createDirectories) { const targetDir = path.dirname(params.targetPath); await targetSSH.execCommand(`mkdir -p "${targetDir}"`); } await targetSSH.putFile(tempFile, params.targetPath); await fs.unlink(tempFile); // Clean up temp file return { content: [ { type: 'text', text: `Successfully copied ${params.sourceConnectionId}:${params.sourcePath} to ${params.targetConnectionId}:${params.targetPath}`, }, ], }; } catch (error) { // Clean up temp file on error try { await fs.unlink(tempFile); } catch {} throw error; } } } catch (error) { throw new McpError( ErrorCode.InternalError, `File copy failed: ${error instanceof Error ? error.message : String(error)}` ); } }
  • Zod schema defining and validating the input parameters for the ssh_copy_file tool.
    const CopyFileSchema = z.object({ sourceConnectionId: z.string().describe('Source SSH connection ID (use "local" for local files)'), sourcePath: z.string().describe('Source file path'), targetConnectionId: z.string().describe('Target SSH connection ID (use "local" for local files)'), targetPath: z.string().describe('Target file path'), createDirectories: z.boolean().default(true).describe('Create target directories if they don\'t exist') });
  • src/index.ts:279-293 (registration)
    Tool registration in the ListToolsRequestSchema response, defining name, description, and input schema for ssh_copy_file.
    { name: 'ssh_copy_file', description: 'Copy files between local and remote servers or between remote servers', inputSchema: { type: 'object', properties: { sourceConnectionId: { type: 'string', description: 'Source SSH connection ID (use "local" for local files)' }, sourcePath: { type: 'string', description: 'Source file path' }, targetConnectionId: { type: 'string', description: 'Target SSH connection ID (use "local" for local files)' }, targetPath: { type: 'string', description: 'Target file path' }, createDirectories: { type: 'boolean', default: true, description: 'Create target directories if they don\'t exist' } }, required: ['sourceConnectionId', 'sourcePath', 'targetConnectionId', 'targetPath'] }, },
  • src/index.ts:491-492 (registration)
    Dispatch case in CallToolRequestSchema handler that routes ssh_copy_file calls to the handleSSHCopyFile method.
    case 'ssh_copy_file': return await this.handleSSHCopyFile(args);

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/mahathirmuh/mcp-ssh-server'

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