Skip to main content
Glama

OmniFocus-MCP

dumpDatabaseOptimized.ts7.09 kB
import { OmnifocusDatabase } from '../types.js'; 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?: { forceRefresh?: boolean; cacheKey?: string; }): Promise<OmnifocusDatabase> { 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(): Promise<{ taskCount: number; activeTaskCount: number; projectCount: number; activeProjectCount: number; folderCount: number; tagCount: number; overdueCount: number; nextActionCount: number; flaggedCount: number; inboxCount: number; lastModified: string; }> { 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 let lastModified = new Date(0); allTasks.forEach(task => { if (task.modificationDate && task.modificationDate > lastModified) { lastModified = task.modificationDate; } }); 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: lastModified.toISOString() }); } 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_${Date.now()}.js`; fs.writeFileSync(tempFile, script); const result = await executeOmniFocusScript(tempFile); fs.unlinkSync(tempFile); if (result.error) { throw new Error(result.error); } return result; } /** * Get incremental changes since a specific timestamp * Much more efficient for periodic updates */ export async function getChangesSince(since: Date): Promise<{ newTasks: any[]; updatedTasks: any[]; completedTasks: any[]; newProjects: any[]; updatedProjects: any[]; }> { const script = ` (() => { try { const sinceDate = new Date("${since.toISOString()}"); // Find tasks that changed since the given date const allTasks = flattenedTasks; const newTasks = allTasks.filter(task => task.creationDate && task.creationDate > sinceDate ).map(task => ({ id: task.id.primaryKey, name: task.name, creationDate: task.creationDate.toISOString() })); const updatedTasks = allTasks.filter(task => task.modificationDate && task.modificationDate > sinceDate && task.creationDate && task.creationDate <= sinceDate ).map(task => ({ id: task.id.primaryKey, name: task.name, modificationDate: task.modificationDate.toISOString() })); const completedTasks = allTasks.filter(task => task.completionDate && task.completionDate > sinceDate ).map(task => ({ id: task.id.primaryKey, name: task.name, completionDate: task.completionDate.toISOString() })); // Find projects that changed const allProjects = flattenedProjects; const newProjects = allProjects.filter(project => project.creationDate && project.creationDate > sinceDate ).map(project => ({ id: project.id.primaryKey, name: project.name, creationDate: project.creationDate.toISOString() })); const updatedProjects = allProjects.filter(project => project.modificationDate && project.modificationDate > sinceDate && project.creationDate && project.creationDate <= sinceDate ).map(project => ({ id: project.id.primaryKey, name: project.name, modificationDate: project.modificationDate.toISOString() })); return JSON.stringify({ newTasks: newTasks, updatedTasks: updatedTasks, completedTasks: completedTasks, newProjects: newProjects, updatedProjects: updatedProjects }); } catch (error) { return JSON.stringify({ error: "Failed to get changes: " + error.toString() }); } })(); `; // Write script to temp file and execute const fs = await import('fs'); const tempFile = `/tmp/omnifocus_changes_${Date.now()}.js`; fs.writeFileSync(tempFile, script); const result = await executeOmniFocusScript(tempFile); fs.unlinkSync(tempFile); if (result.error) { throw new Error(result.error); } return result; }

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/themotionmachine/OmniFocus-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server