Skip to main content
Glama

OmniFocus MCP Enhanced

by jqlts1
forecastTasks.jsโ€ข4.85 kB
// OmniJS script to get forecast tasks from OmniFocus (() => { try { // Use default values since parameters are not easily available in JXA mode const days = 7; const hideCompleted = true; // Default to true const includeDeferredOnly = false; // Helper function to format dates consistently function formatDate(date) { if (!date) return null; return date.toISOString(); } // Helper function to get date without time for grouping function getDateKey(date) { if (!date) return null; const d = new Date(date); d.setHours(0, 0, 0, 0); return d.toISOString().split('T')[0]; } // Get task status enum mapping const taskStatusMap = { [Task.Status.Available]: "Available", [Task.Status.Blocked]: "Blocked", [Task.Status.Completed]: "Completed", [Task.Status.Dropped]: "Dropped", [Task.Status.DueSoon]: "DueSoon", [Task.Status.Next]: "Next", [Task.Status.Overdue]: "Overdue" }; function getTaskStatus(status) { return taskStatusMap[status] || "Unknown"; } const exportData = { exportDate: new Date().toISOString(), tasksByDate: {} }; // Calculate date range const today = new Date(); today.setHours(0, 0, 0, 0); const endDate = new Date(today); endDate.setDate(today.getDate() + days); console.log(`Looking for forecast tasks from ${today.toISOString()} to ${endDate.toISOString()}`); // Get all active tasks let allTasks = flattenedTasks; // Filter by completion status if needed if (hideCompleted) { allTasks = allTasks.filter(task => task.taskStatus !== Task.Status.Completed && task.taskStatus !== Task.Status.Dropped ); } console.log(`Processing ${allTasks.length} active tasks for forecast`); // Process each task to see if it falls in forecast range allTasks.forEach(task => { try { let shouldInclude = false; let taskDate = null; let isDue = false; // Check if task has due date in range if (task.dueDate) { const dueDate = new Date(task.dueDate); dueDate.setHours(0, 0, 0, 0); if (dueDate >= today && dueDate <= endDate) { shouldInclude = true; taskDate = dueDate; isDue = true; } // Also include overdue tasks else if (dueDate < today) { shouldInclude = true; taskDate = dueDate; isDue = true; } } // Check if task has defer date in range (becomes available) if (!includeDeferredOnly || !shouldInclude) { if (task.deferDate && !isDue) { const deferDate = new Date(task.deferDate); deferDate.setHours(0, 0, 0, 0); if (deferDate >= today && deferDate <= endDate) { shouldInclude = true; taskDate = deferDate; isDue = false; } } } if (shouldInclude && taskDate) { const dateKey = getDateKey(taskDate); if (!exportData.tasksByDate[dateKey]) { exportData.tasksByDate[dateKey] = []; } const taskData = { id: task.id.primaryKey, name: task.name, note: task.note || "", taskStatus: getTaskStatus(task.taskStatus), flagged: task.flagged, dueDate: formatDate(task.dueDate), deferDate: formatDate(task.deferDate), estimatedMinutes: task.estimatedMinutes, projectId: task.containingProject ? task.containingProject.id.primaryKey : null, projectName: task.containingProject ? task.containingProject.name : null, inInbox: task.inInbox, isDue: isDue, // Whether this is due or just becoming available tags: task.tags.map(tag => ({ id: tag.id.primaryKey, name: tag.name })) }; exportData.tasksByDate[dateKey].push(taskData); } } catch (taskError) { console.log(`Error processing forecast task: ${taskError}`); } }); // Count total tasks const totalTasks = Object.values(exportData.tasksByDate).reduce((sum, tasks) => sum + tasks.length, 0); console.log(`Successfully processed ${totalTasks} forecast tasks across ${Object.keys(exportData.tasksByDate).length} dates`); return JSON.stringify(exportData); } catch (error) { console.error(`Error in forecastTasks script: ${error}`); return JSON.stringify({ success: false, error: `Error getting forecast tasks: ${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