UNPKG

omnifocus-mcp

Version:

Model Context Protocol (MCP) server that integrates with OmniFocus for AI assistant interaction

105 lines (96 loc) 3.79 kB
import { executeOmniFocusScript } from '../utils/scriptExecution.js'; import { getCacheManager } from '../utils/cacheManager.js'; import { dumpDatabase as originalDumpDatabase } from './dumpDatabase.js'; /** * Optimized version of dumpDatabase that uses caching * Falls back to original implementation if caching fails */ export async function dumpDatabaseOptimized(options) { const cacheManager = getCacheManager({ ttlSeconds: 300, // 5 minute cache useChecksum: true // Validate with database checksum }); const cacheKey = options?.cacheKey || 'full-dump'; // Check if we should force a refresh if (!options?.forceRefresh) { const cached = await cacheManager.get(cacheKey); if (cached) { cacheManager.trackHit(); console.log(`Cache hit for ${cacheKey}. Stats:`, cacheManager.getStats()); return cached; } } cacheManager.trackMiss(); console.log(`Cache miss for ${cacheKey}. Fetching fresh data...`); // Fetch fresh data using the original implementation const freshData = await originalDumpDatabase(); // Store in cache for next time await cacheManager.set(cacheKey, freshData); return freshData; } /** * Get just database statistics without full dump * Much more efficient for overview information */ export async function getDatabaseStats() { const script = ` (() => { try { // Calculate statistics without fetching full data const allTasks = flattenedTasks; const activeTasks = allTasks.filter(task => task.taskStatus !== Task.Status.Completed && task.taskStatus !== Task.Status.Dropped ); const allProjects = flattenedProjects; const activeProjects = allProjects.filter(project => project.status === Project.Status.Active ); // Count specific task statuses const overdueCount = activeTasks.filter(task => task.taskStatus === Task.Status.Overdue ).length; const nextActionCount = activeTasks.filter(task => task.taskStatus === Task.Status.Next ).length; const flaggedCount = activeTasks.filter(task => task.flagged).length; const inboxCount = activeTasks.filter(task => task.inInbox).length; // Get latest modification time (OmniJS property is "modified", // not the AppleScript name "modificationDate") let lastModified = new Date(0); allTasks.forEach(task => { if (task.modified && task.modified > lastModified) { lastModified = task.modified; } }); return JSON.stringify({ taskCount: allTasks.length, activeTaskCount: activeTasks.length, projectCount: allProjects.length, activeProjectCount: activeProjects.length, folderCount: flattenedFolders.length, tagCount: flattenedTags.filter(tag => tag.active).length, overdueCount: overdueCount, nextActionCount: nextActionCount, flaggedCount: flaggedCount, inboxCount: inboxCount, lastModified: formatDate(lastModified) }); } catch (error) { return JSON.stringify({ error: "Failed to get database stats: " + error.toString() }); } })(); `; // Write script to temp file and execute const fs = await import('fs'); const tempFile = `/tmp/omnifocus_stats_${crypto.randomUUID()}.js`; fs.writeFileSync(tempFile, script); const result = await executeOmniFocusScript(tempFile); fs.unlinkSync(tempFile); if (result.error) { throw new Error(result.error); } return result; }