Skip to main content
Glama

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
NameRequiredDescriptionDefault
hideCompletedNoSet to false to show completed and dropped tasks (default: true)
hideRecurringDuplicatesNoSet 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
        };
      }
    }
  • 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;
      }
    }

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/jqlts1/omnifocus-mcp-enhanced'

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