Skip to main content
Glama

OmniFocus-MCP

scriptExecution.ts4.07 kB
import { exec } from 'child_process'; import { promisify } from 'util'; import { writeFileSync, unlinkSync, readFileSync } from 'fs'; import { join } from 'path'; import { tmpdir } from 'os'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; import { existsSync } from 'fs'; const execAsync = promisify(exec); // Helper function to execute OmniFocus scripts export async function executeJXA(script: string): Promise<any[]> { try { // Write the script to a temporary file in the system temp directory const tempFile = join(tmpdir(), `jxa_script_${Date.now()}.js`); // Write the script to the temporary file writeFileSync(tempFile, script); // Execute the script using osascript const { stdout, stderr } = await execAsync(`osascript -l JavaScript ${tempFile}`); if (stderr) { console.error("Script stderr output:", stderr); } // Clean up the temporary file unlinkSync(tempFile); // Parse the output as JSON try { const result = JSON.parse(stdout); return result; } catch (e) { console.error("Failed to parse script output as JSON:", e); // If this contains a "Found X tasks" message, treat it as a successful non-JSON response if (stdout.includes("Found") && stdout.includes("tasks")) { return []; } return []; } } catch (error) { console.error("Failed to execute JXA script:", error); throw error; } } // Function to execute scripts in OmniFocus using the URL scheme // Update src/utils/scriptExecution.ts export async function executeOmniFocusScript(scriptPath: string, args?: any): Promise<any> { try { // Get the actual script path (existing code remains the same) let actualPath; if (scriptPath.startsWith('@')) { const scriptName = scriptPath.substring(1); const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const distPath = join(__dirname, '..', 'utils', 'omnifocusScripts', scriptName); const srcPath = join(__dirname, '..', '..', 'src', 'utils', 'omnifocusScripts', scriptName); if (existsSync(distPath)) { actualPath = distPath; } else if (existsSync(srcPath)) { actualPath = srcPath; } else { actualPath = join(__dirname, '..', 'omnifocusScripts', scriptName); } } else { actualPath = scriptPath; } // Read the script file const scriptContent = readFileSync(actualPath, 'utf8'); // Create a temporary file for our JXA wrapper script const tempFile = join(tmpdir(), `jxa_wrapper_${Date.now()}.js`); // Escape the script content properly for use in JXA const escapedScript = scriptContent.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$'); // Create a JXA script that will execute our OmniJS script in OmniFocus const jxaScript = ` function run() { try { const app = Application('OmniFocus'); app.includeStandardAdditions = true; // Run the OmniJS script in OmniFocus and capture the output const result = app.evaluateJavascript(\`${escapedScript}\`); // Return the result return result; } catch (e) { return JSON.stringify({ error: e.message }); } } `; // Write the JXA script to the temporary file writeFileSync(tempFile, jxaScript); // Execute the JXA script using osascript const { stdout, stderr } = await execAsync(`osascript -l JavaScript ${tempFile}`); // Clean up the temporary file unlinkSync(tempFile); if (stderr) { console.error("Script stderr output:", stderr); } // Parse the output as JSON try { return JSON.parse(stdout); } catch (parseError) { console.error("Error parsing script output:", parseError); return stdout; } } catch (error) { console.error("Failed to execute OmniFocus script:", error); throw error; } }

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