Skip to main content
Glama

get_forecast_tasks

Retrieve tasks from OmniFocus by filtering due or deferred tasks within a specified date range. Customize results by selecting days ahead, hiding completed tasks, or focusing solely on deferred items.

Instructions

Get tasks from OmniFocus forecast perspective (due/deferred tasks in date range)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
daysNoNumber of days to look ahead for forecast (default: 7)
hideCompletedNoSet to false to show completed tasks in forecast (default: true)
includeDeferredOnlyNoSet to true to show only deferred tasks becoming available (default: false)

Implementation Reference

  • MCP tool handler function that calls the primitive getForecastTasks and formats response as text content
    export async function handler(args: z.infer<typeof schema>, extra: RequestHandlerExtra) {
      try {
        const result = await getForecastTasks({
          days: args.days || 7,
          hideCompleted: args.hideCompleted !== false, // Default to true
          includeDeferredOnly: args.includeDeferredOnly || false
        });
        
        return {
          content: [{
            type: "text" as const,
            text: result
          }]
        };
      } catch (err: unknown) {
        const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
        return {
          content: [{
            type: "text" as const,
            text: `Error getting forecast tasks: ${errorMessage}`
          }],
          isError: true
        };
      }
    }
  • Zod schema defining input parameters for the get_forecast_tasks tool: days, hideCompleted, includeDeferredOnly
    export const schema = z.object({
      days: z.number().min(1).max(30).optional().describe("Number of days to look ahead for forecast (default: 7)"),
      hideCompleted: z.boolean().optional().describe("Set to false to show completed tasks in forecast (default: true)"),
      includeDeferredOnly: z.boolean().optional().describe("Set to true to show only deferred tasks becoming available (default: false)")
    });
  • src/server.ts:113-118 (registration)
    Registration of the get_forecast_tasks tool on the MCP server using its schema and handler
    server.tool(
      "get_forecast_tasks",
      "Get tasks from OmniFocus forecast perspective (due/deferred tasks in date range)", 
      getForecastTasksTool.schema.shape,
      getForecastTasksTool.handler
    );
  • Core helper function that executes OmniFocus forecast script and formats the task output into markdown with dates, summaries, and task details
    export async function getForecastTasks(options: GetForecastTasksOptions = {}): Promise<string> {
      const { days = 7, hideCompleted = true, includeDeferredOnly = false } = options;
      
      try {
        // Execute the forecast tasks script
        const result = await executeOmniFocusScript('@forecastTasks.js', { 
          days: days,
          hideCompleted: hideCompleted,
          includeDeferredOnly: includeDeferredOnly
        });
        
        if (typeof result === 'string') {
          return result;
        }
        
        // If result is an object, format it
        if (result && typeof result === 'object') {
          const data = result as any;
          
          if (data.error) {
            throw new Error(data.error);
          }
          
          // Format the forecast tasks
          let output = `# πŸ“… FORECAST - Next ${days} days\n\n`;
          
          if (data.tasksByDate && typeof data.tasksByDate === 'object') {
            const dates = Object.keys(data.tasksByDate).sort();
            
            if (dates.length === 0) {
              output += "πŸŽ‰ No tasks due in the forecast period - enjoy the calm!\n";
            } else {
              const today = new Date();
              today.setHours(0, 0, 0, 0);
              
              dates.forEach(dateStr => {
                const tasks = data.tasksByDate[dateStr];
                if (!tasks || tasks.length === 0) return;
                
                const taskDate = new Date(dateStr);
                const isToday = taskDate.getTime() === today.getTime();
                const isTomorrow = taskDate.getTime() === today.getTime() + 24 * 60 * 60 * 1000;
                const isOverdue = taskDate < today;
                
                let dateHeader = '';
                if (isOverdue) {
                  dateHeader = `## ⚠️ OVERDUE - ${taskDate.toLocaleDateString()}`;
                } else if (isToday) {
                  dateHeader = `## πŸ”₯ TODAY - ${taskDate.toLocaleDateString()}`;
                } else if (isTomorrow) {
                  dateHeader = `## ⏰ TOMORROW - ${taskDate.toLocaleDateString()}`;
                } else {
                  const dayOfWeek = taskDate.toLocaleDateString('en-US', { weekday: 'long' });
                  dateHeader = `## πŸ“… ${dayOfWeek} - ${taskDate.toLocaleDateString()}`;
                }
                
                output += `${dateHeader}\n`;
                
                tasks.forEach((task: any) => {
                  const flagSymbol = task.flagged ? '🚩 ' : '';
                  const projectStr = task.projectName ? ` (${task.projectName})` : ' (Inbox)';
                  const statusStr = task.taskStatus !== 'Available' ? ` [${task.taskStatus}]` : '';
                  const estimateStr = task.estimatedMinutes ? ` ⏱${task.estimatedMinutes}m` : '';
                  const typeIndicator = task.isDue ? 'πŸ“…' : 'πŸš€'; // Due vs Deferred
                  
                  output += `β€’ ${typeIndicator} ${flagSymbol}${task.name}${projectStr}${statusStr}${estimateStr}\n`;
                  
                  if (task.note && task.note.trim()) {
                    output += `  πŸ“ ${task.note.trim()}\n`;
                  }
                });
                
                output += '\n';
              });
              
              // Summary
              const totalTasks = dates.reduce((sum, date) => sum + data.tasksByDate[date].length, 0);
              output += `πŸ“Š **Summary**: ${totalTasks} task${totalTasks === 1 ? '' : 's'} in forecast\n`;
            }
          } else {
            output += "No forecast data available\n";
          }
          
          return output;
        }
        
        return "Unexpected result format from OmniFocus";
        
      } catch (error) {
        console.error("Error in getForecastTasks:", error);
        throw new Error(`Failed to get forecast tasks: ${error instanceof Error ? error.message : 'Unknown 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