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;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. While 'Gets' implies a read operation, it doesn't specify what 'current state' includes (tasks, projects, tags, etc.), the format of the output, whether this is a heavy operation, or any performance considerations. For a database dump tool with zero annotation coverage, this is insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that states the core purpose upfront. However, given the complexity of a database dump operation and the many sibling alternatives, this extreme conciseness comes at the cost of helpful context that would aid tool selection.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a database dump tool with no annotations, no output schema, and 15 sibling retrieval tools, the description is incomplete. It doesn't explain what data is included in the dump, the output format, how this differs from more targeted retrieval tools, or any performance implications. The agent lacks sufficient context to use this tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents both parameters (hideCompleted and hideRecurringDuplicates). The description adds no parameter information beyond what's in the schema, meeting the baseline 3 for high schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Gets') and resource ('current state of your OmniFocus database'), providing a specific verb+resource combination. However, it doesn't explicitly distinguish this tool from its many sibling tools that also retrieve task/project data (like get_flagged_tasks, get_inbox_tasks, etc.), which would require a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. With 15 sibling tools that retrieve various subsets of OmniFocus data, the agent receives no help in choosing between a full database dump and more targeted retrieval tools like get_flagged_tasks or filter_tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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