loadBackup
Restore specific Heptabase MCP backups by specifying the backup path and ID, with optional extraction to access data directly.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| backupId | No | ||
| backupPath | No | ||
| extract | No |
Implementation Reference
- src/server.ts:220-271 (handler)MCP tool handler for 'loadBackup'. Resolves backup path (from ID if provided), calls BackupManager.loadBackup, initializes/updates HeptabaseDataService with extracted data, returns success message.this.tools.loadBackup = { inputSchema: loadBackupSchema, handler: async (params) => { if (!this.backupManager) { this.backupManager = new BackupManager({ backupPath: this.config.backupPath, extractionPath: this.config.extractionPath, autoExtract: params.extract ?? this.config.autoExtract, watchDirectory: false, keepExtracted: this.config.keepExtracted }); } let backupPath = params.backupPath; // If backupId is provided, find the backup path if (params.backupId) { const backups = await this.backupManager.listBackups(); const backup = backups.find(b => b.backupId === params.backupId); if (!backup) { throw new Error('Backup not found'); } backupPath = backup.backupPath; } const metadata = await this.backupManager.loadBackup(backupPath!); // Initialize data service with the extracted path const dataPath = metadata.extractedPath || path.dirname(metadata.backupPath); // Update existing data service if it exists, otherwise create new one if (this.dataService) { // Update the data path and reload (this.dataService as any).config.dataPath = dataPath; await this.dataService.loadData(); } else { this.dataService = new HeptabaseDataService({ dataPath, cacheEnabled: this.config.cacheEnabled, cacheTTL: this.config.cacheTTL }); await this.dataService.loadData(); } return { content: [{ type: 'text', text: `Backup loaded successfully: ${metadata.backupId}` }] }; } };
- src/server.ts:212-218 (schema)Zod input schema for the loadBackup tool, requiring either backupPath or backupId.const loadBackupSchema = z.object({ backupPath: z.string().optional(), backupId: z.string().optional(), extract: z.boolean().optional() }).refine(data => data.backupPath || data.backupId, { message: 'Either backupPath or backupId must be provided' });
- src/server.ts:273-280 (registration)MCP server tool registration for 'loadBackup', with inline schema and handler wrapper that validates input using loadBackupSchema.this.server.tool('loadBackup', { backupPath: z.string().optional(), backupId: z.string().optional(), extract: z.boolean().optional() }, async (params) => { const validated = loadBackupSchema.parse(params); return this.tools.loadBackup.handler(validated); });
- src/services/BackupManager.ts:58-97 (helper)Core implementation in BackupManager that loads backup metadata, extracts ZIP if needed and autoExtract is true, caches metadata, emits events.async loadBackup(backupPath: string): Promise<BackupMetadata> { this.emit('backup:load:start', backupPath); try { const stats = await fs.stat(backupPath); const fileName = path.basename(backupPath); const backupInfo = this.getBackupInfo(fileName); const isCompressed = fileName.endsWith('.zip'); let extractedPath: string | undefined; if (isCompressed && this.config.autoExtract) { const backupName = path.basename(backupPath, '.zip'); extractedPath = path.join(this.config.extractionPath, backupName); // Check if already extracted if (!(await fs.pathExists(extractedPath))) { await this.extractBackup(backupPath, extractedPath); } } const metadata: BackupMetadata = { backupId: path.basename(backupPath, path.extname(backupPath)), backupPath, createdDate: backupInfo.date, fileSize: stats.size, isCompressed, extractedPath, version: backupInfo.version }; this.loadedBackups.set(metadata.backupId, metadata); this.emit('backup:load:complete', metadata); return metadata; } catch (error) { this.emit('backup:load:error', error); throw error; } }