compareBackups
Analyze and compare two Heptabase backups to identify differences, export results, and optimize data management for enhanced workflow efficiency.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| backupId1 | Yes | ||
| backupId2 | Yes | ||
| exportPath | No | ||
| whiteboardId | No |
Implementation Reference
- src/tools/analysis.ts:110-219 (handler)The main handler function that executes the compareBackups tool logic. It loads two backups using BackupManager, fetches relevant data (whiteboards, cards, connections) using HeptabaseDataService, computes differences, formats a text summary of changes, and optionally exports JSON to a file.export async function compareBackups( dataService: HeptabaseDataService, backupManager: BackupManager, params: z.infer<typeof compareBackupsSchema> ) { // Get backup metadata const backup1 = await backupManager.getBackupMetadata(params.backupId1); const backup2 = await backupManager.getBackupMetadata(params.backupId2); if (!backup1 || !backup2) { throw new Error('One or both backups not found'); } // Load the first backup await backupManager.loadBackup(backup1.backupPath); let data1: any; let data2: any; if (params.whiteboardId) { // Compare specific whiteboard data1 = await dataService.getWhiteboard(params.whiteboardId, { includeCards: true, includeConnections: true }); // Load the second backup await backupManager.loadBackup(backup2.backupPath); data2 = await dataService.getWhiteboard(params.whiteboardId, { includeCards: true, includeConnections: true }); } else { // Compare entire backups data1 = { whiteboards: await dataService.getWhiteboards(), cards: await dataService.getCards(), connections: await dataService.getConnections() }; // Load the second backup await backupManager.loadBackup(backup2.backupPath); data2 = { whiteboards: await dataService.getWhiteboards(), cards: await dataService.getCards(), connections: await dataService.getConnections() }; } // Calculate differences const comparison = { timestamp: new Date().toISOString(), backup1: { id: backup1.backupId, date: backup1.createdDate, size: backup1.fileSize }, backup2: { id: backup2.backupId, date: backup2.createdDate, size: backup2.fileSize }, changes: {} as any }; if (params.whiteboardId) { comparison.changes = { whiteboard: params.whiteboardId, cardsAdded: data2.cards.length - data1.cards.length, connectionsAdded: data2.connections.length - data1.connections.length }; } else { comparison.changes = { whiteboardsAdded: data2.whiteboards.length - data1.whiteboards.length, cardsAdded: data2.cards.length - data1.cards.length, connectionsAdded: data2.connections.length - data1.connections.length }; } // Format response let text = 'Comparison Results\n\n'; text += `Backup 1: ${backup1.backupId} (${backup1.createdDate})\n`; text += `Backup 2: ${backup2.backupId} (${backup2.createdDate})\n\n`; if (params.whiteboardId) { text += `Whiteboard: ${data1.whiteboard.name}\n`; text += `Added: ${comparison.changes.cardsAdded} cards\n`; text += `Added: ${comparison.changes.connectionsAdded} connections\n`; } else { text += `Added: ${comparison.changes.whiteboardsAdded} whiteboards\n`; text += `Added: ${comparison.changes.cardsAdded} cards\n`; text += `Added: ${comparison.changes.connectionsAdded} connections\n`; } // Export if requested if (params.exportPath) { await fs.mkdir(path.dirname(params.exportPath), { recursive: true }); await fs.writeFile(params.exportPath, JSON.stringify(comparison, null, 2), 'utf8'); text += `\nComparison saved to ${params.exportPath}`; } return { content: [{ type: 'text', text }] }; }
- src/tools/analysis.ts:13-18 (schema)Zod schema defining the input parameters for the compareBackups tool: required backup IDs and optional whiteboard ID and export path.export const compareBackupsSchema = z.object({ backupId1: z.string(), backupId2: z.string(), whiteboardId: z.string().optional(), exportPath: z.string().optional() });
- src/server.ts:714-727 (registration)Registers the compareBackups tool with the MCP server by assigning it to this.tools.compareBackups and calling this.server.tool, importing the handler and schema from ./tools/analysis.ts.// compareBackups tool this.tools.compareBackups = { inputSchema: compareBackupsSchema, handler: async (params) => { if (!this.dataService || !this.backupManager) { throw new Error('Services not initialized. Please configure backup path first.'); } return compareBackups(this.dataService, this.backupManager, params); } }; this.server.tool('compareBackups', compareBackupsSchema.shape, async (params: z.infer<typeof compareBackupsSchema>) => { return this.tools.compareBackups.handler(params); });