backup-database
Create backups of Firebird databases to protect data. Specify backup format, compression, and storage path for database protection.
Instructions
Creates a backup of the Firebird database
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| backupPath | Yes | Path where the backup file will be saved | |
| options | No |
Implementation Reference
- src/tools/database.ts:51-59 (schema)Zod input schema for backup-database tool defining backup path and options.export const BackupDatabaseArgsSchema = z.object({ backupPath: z.string().min(1).describe("Path where the backup file will be saved"), options: z.object({ format: z.enum(['gbak', 'nbackup']).default('gbak').describe("Backup format: gbak (full backup) or nbackup (incremental)"), compress: z.boolean().default(false).describe("Whether to compress the backup"), metadata_only: z.boolean().default(false).describe("Whether to backup only metadata (no data)"), verbose: z.boolean().default(false).describe("Whether to show detailed progress") }).optional() });
- src/tools/database.ts:372-402 (registration)Registration of backup-database tool in the tools map with handler that calls backupDatabase and formats response for MCP.// Add backup-database tool tools.set("backup-database", { name: "backup-database", description: "Creates a backup of the Firebird database", inputSchema: BackupDatabaseArgsSchema, handler: async (request) => { const { backupPath, options } = request; logger.info(`Executing backup-database tool to: ${backupPath}`); try { const result = await backupDatabase(backupPath, options); return { content: [{ type: "text", text: formatForClaude(result) }] }; } catch (error) { const errorResponse = wrapError(error); logger.error(`Error backing up database: ${errorResponse.error} [${errorResponse.errorType || 'UNKNOWN'}]`); return { content: [{ type: "text", text: formatForClaude(errorResponse) }] }; } } });
- src/db/management.ts:86-195 (handler)Core implementation of database backup using gbak or nbackup Firebird tools via child_process.spawn.export const backupDatabase = async ( backupPath: string, options: BackupOptions = {}, config = DEFAULT_CONFIG ): Promise<BackupResult> => { const startTime = Date.now(); try { // Check if Firebird tools are installed const toolsCheck = await checkFirebirdTools(); if (!toolsCheck.installed) { throw new FirebirdError( `Firebird client tools are not installed. ${toolsCheck.installInstructions}`, 'MISSING_FIREBIRD_TOOLS' ); } // Ensure the backup directory exists const backupDir = path.dirname(backupPath); if (!fs.existsSync(backupDir)) { fs.mkdirSync(backupDir, { recursive: true }); } // Determine which backup tool to use const format = options.format || 'gbak'; let command: string; let args: string[] = []; // Try to find Firebird bin directory const firebirdBinPath = await findFirebirdBinPath(); if (firebirdBinPath) { logger.info(`Found Firebird bin directory: ${firebirdBinPath}`); // Use full path to command if bin directory was found command = path.join(firebirdBinPath, format); } else { // Use command name only, relying on system PATH command = format; } if (format === 'gbak') { args = [ '-b', // Backup '-v', // Verbose output '-user', config.user || 'SYSDBA', '-password', config.password || 'masterkey' ]; if (options.metadata_only) { args.push('-m'); // Metadata only } if (options.compress) { args.push('-z'); // Compress } // Add connection string and backup path const connectionString = `${config.host}/${config.port}:${config.database}`; args.push(connectionString, backupPath); } else if (format === 'nbackup') { args = [ '-B', '0', // Level 0 backup (full) '-user', config.user || 'SYSDBA', '-password', config.password || 'masterkey' ]; // Add database path and backup path args.push(config.database, backupPath); } else { throw new FirebirdError( `Invalid backup format: ${format}`, 'CONFIGURATION_ERROR' ); } logger.info(`Starting database backup to ${backupPath} using ${format}`); if (options.verbose) { logger.debug(`Backup command: ${command} ${args.join(' ')}`); } // Execute the backup command const result = await executeCommand(command, args, options.verbose); // Get the size of the backup file const stats = fs.statSync(backupPath); const duration = Date.now() - startTime; logger.info(`Backup completed successfully in ${duration}ms, size: ${stats.size} bytes`); return { success: true, backupPath, size: stats.size, duration, details: result }; } catch (error: any) { const duration = Date.now() - startTime; const errorMessage = `Error creating database backup: ${error.message || error}`; logger.error(errorMessage); return { success: false, backupPath, size: 0, duration, error: errorMessage, details: error.details || '' }; } };
- src/db/management.ts:419-463 (helper)Helper function to execute Firebird command-line tools (gbak, nbackup, etc.) using child_process.spawn and capture output.async function executeCommand(command: string, args: string[], verbose: boolean = false): Promise<string> { return new Promise((resolve, reject) => { const process = spawn(command, args); let stdout = ''; let stderr = ''; process.stdout.on('data', (data) => { const output = data.toString(); stdout += output; if (verbose) { logger.debug(`[${command}] ${output.trim()}`); } }); process.stderr.on('data', (data) => { const output = data.toString(); stderr += output; if (verbose) { logger.error(`[${command}] ${output.trim()}`); } }); process.on('close', (code) => { if (code === 0) { resolve(stdout); } else { const error = new FirebirdError( `Command failed with code ${code}: ${stderr || 'No error message'}`, 'COMMAND_EXECUTION_ERROR' ); (error as any).details = stderr; reject(error); } }); process.on('error', (error) => { const fbError = new FirebirdError( `Failed to execute command: ${error.message}`, 'COMMAND_EXECUTION_ERROR' ); (fbError as any).details = error.message; reject(fbError); }); }); }
- src/db/management.ts:19-24 (schema)TypeScript interface for BackupOptions used in the backupDatabase function.export interface BackupOptions { format?: 'gbak' | 'nbackup'; compress?: boolean; metadata_only?: boolean; verbose?: boolean; }