Skip to main content
Glama
jqlts1

OmniFocus MCP Enhanced

by jqlts1

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