dump_database
Retrieve the current state of your OmniFocus database, with options to hide completed tasks or recurring duplicates, enabling efficient task management and organization.
Instructions
Gets the current state of your OmniFocus database
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| hideCompleted | No | Set to false to show completed and dropped tasks (default: true) | |
| hideRecurringDuplicates | No | Set to true to hide duplicate instances of recurring tasks (default: true) |
Implementation Reference
- src/server.ts:34-39 (registration)Registers the 'dump_database' tool in the MCP server using the schema and handler exported from './tools/definitions/dumpDatabase.js'.server.tool( "dump_database", "Gets the current state of your OmniFocus database", dumpDatabaseTool.schema.shape, dumpDatabaseTool.handler );
- Zod schema for the tool input parameters: optional booleans to control hiding of completed tasks and recurring duplicates.export const schema = z.object({ hideCompleted: z.boolean().optional().describe("Set to false to show completed and dropped tasks (default: true)"), hideRecurringDuplicates: z.boolean().optional().describe("Set to true to hide duplicate instances of recurring tasks (default: true)") });
- Tool handler that dumps the OmniFocus database using dumpDatabase(), applies formatting with options, and returns a compact text report. Handles errors gracefully.export async function handler(args: z.infer<typeof schema>, extra: RequestHandlerExtra) { try { // Get raw database const database = await dumpDatabase(); // Format as compact report const formattedReport = formatCompactReport(database, { hideCompleted: args.hideCompleted !== false, // Default to true hideRecurringDuplicates: args.hideRecurringDuplicates !== false // Default to true }); return { content: [{ type: "text" as const, text: formattedReport }] }; } catch (err: unknown) { return { content: [{ type: "text" as const, text: `Error generating report. Please ensure OmniFocus is running and try again.` }], isError: true }; } }
- src/tools/dumpDatabase.ts:69-195 (helper)Helper function that executes AppleScript to dump the raw OmniFocus database and transforms it into a structured OmnifocusDatabase object used by the tool handler.export async function dumpDatabase(): Promise<OmnifocusDatabase> { try { // Execute the OmniFocus script const data = await executeOmniFocusScript('@omnifocusDump.js') as OmnifocusDumpData; // wait 1 second await new Promise(resolve => setTimeout(resolve, 1000)); // Create an empty database if no data returned if (!data) { return { exportDate: new Date().toISOString(), tasks: [], projects: {}, folders: {}, tags: {} }; } // Initialize the database object const database: OmnifocusDatabase = { exportDate: data.exportDate, tasks: [], projects: {}, folders: {}, tags: {} }; // Process tasks if (data.tasks && Array.isArray(data.tasks)) { // Convert the tasks to our OmnifocusTask format database.tasks = data.tasks.map((task: OmnifocusDumpTask) => { // Get tag names from the tag IDs const tagNames = (task.tags || []).map(tagId => { return data.tags[tagId]?.name || 'Unknown Tag'; }); return { id: String(task.id), name: String(task.name), note: String(task.note || ""), flagged: Boolean(task.flagged), completed: task.taskStatus === "Completed", completionDate: null, // Not available in the new format dropDate: null, // Not available in the new format taskStatus: String(task.taskStatus), active: task.taskStatus !== "Completed" && task.taskStatus !== "Dropped", dueDate: task.dueDate, deferDate: task.deferDate, estimatedMinutes: task.estimatedMinutes ? Number(task.estimatedMinutes) : null, tags: task.tags || [], tagNames: tagNames, parentId: task.parentTaskID || null, containingProjectId: task.projectID || null, projectId: task.projectID || null, childIds: task.children || [], hasChildren: (task.children && task.children.length > 0) || false, sequential: Boolean(task.sequential), completedByChildren: Boolean(task.completedByChildren), isRepeating: false, // Not available in the new format repetitionMethod: null, // Not available in the new format repetitionRule: null, // Not available in the new format attachments: [], // Default empty array linkedFileURLs: [], // Default empty array notifications: [], // Default empty array shouldUseFloatingTimeZone: false // Default value }; }); } // Process projects if (data.projects) { for (const [id, project] of Object.entries(data.projects)) { database.projects[id] = { id: String(project.id), name: String(project.name), status: String(project.status), folderID: project.folderID || null, sequential: Boolean(project.sequential), effectiveDueDate: project.effectiveDueDate, effectiveDeferDate: project.effectiveDeferDate, dueDate: project.dueDate, deferDate: project.deferDate, completedByChildren: Boolean(project.completedByChildren), containsSingletonActions: Boolean(project.containsSingletonActions), note: String(project.note || ""), tasks: project.tasks || [], flagged: false, // Default value estimatedMinutes: null // Default value }; } } // Process folders if (data.folders) { for (const [id, folder] of Object.entries(data.folders)) { database.folders[id] = { id: String(folder.id), name: String(folder.name), parentFolderID: folder.parentFolderID || null, status: String(folder.status), projects: folder.projects || [], subfolders: folder.subfolders || [] }; } } // Process tags if (data.tags) { for (const [id, tag] of Object.entries(data.tags)) { database.tags[id] = { id: String(tag.id), name: String(tag.name), parentTagID: tag.parentTagID || null, active: Boolean(tag.active), allowsNextAction: Boolean(tag.allowsNextAction), tasks: tag.tasks || [] }; } } return database; } catch (error) { console.error("Error in dumpDatabase:", error); throw error; } }