add_project
Add a new project to OmniFocus with details like name, notes, due date, tags, and folder. Define sequential tasks, estimated time, and flag status for enhanced task management.
Instructions
Add a new project to OmniFocus
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| deferDate | No | The defer date of the project in ISO format (YYYY-MM-DD or full ISO date) | |
| dueDate | No | The due date of the project in ISO format (YYYY-MM-DD or full ISO date) | |
| estimatedMinutes | No | Estimated time to complete the project, in minutes | |
| flagged | No | Whether the project is flagged or not | |
| folderName | No | The name of the folder to add the project to (will add to root if not specified) | |
| name | Yes | The name of the project | |
| note | No | Additional notes for the project | |
| sequential | No | Whether tasks in the project should be sequential (default: false) | |
| tags | No | Tags to assign to the project |
Implementation Reference
- src/server.ts:48-53 (registration)Registers the 'add_project' tool with the MCP server, specifying its name, description, input schema, and handler function imported from './tools/definitions/addProject.js'.server.tool( "add_project", "Add a new project to OmniFocus", addProjectTool.schema.shape, addProjectTool.handler );
- Zod schema defining the input parameters for the 'add_project' tool, including project name, notes, dates, flags, estimates, tags, folder, and sequential setting.export const schema = z.object({ name: z.string().describe("The name of the project"), note: z.string().optional().describe("Additional notes for the project"), dueDate: z.string().optional().describe("The due date of the project in ISO format (YYYY-MM-DD or full ISO date)"), deferDate: z.string().optional().describe("The defer date of the project in ISO format (YYYY-MM-DD or full ISO date)"), flagged: z.boolean().optional().describe("Whether the project is flagged or not"), estimatedMinutes: z.number().optional().describe("Estimated time to complete the project, in minutes"), tags: z.array(z.string()).optional().describe("Tags to assign to the project"), folderName: z.string().optional().describe("The name of the folder to add the project to (will add to root if not specified)"), sequential: z.boolean().optional().describe("Whether tasks in the project should be sequential (default: false)") });
- MCP tool handler for 'add_project' that validates input, calls the primitive addProject function, and returns formatted success or error response.export async function handler(args: z.infer<typeof schema>, extra: RequestHandlerExtra) { try { // Call the addProject function const result = await addProject(args as AddProjectParams); if (result.success) { // Project was added successfully let locationText = args.folderName ? `in folder "${args.folderName}"` : "at the root level"; let tagText = args.tags && args.tags.length > 0 ? ` with tags: ${args.tags.join(', ')}` : ""; let dueDateText = args.dueDate ? ` due on ${new Date(args.dueDate).toLocaleDateString()}` : ""; let sequentialText = args.sequential ? " (sequential)" : " (parallel)"; return { content: [{ type: "text" as const, text: `✅ Project "${args.name}" created successfully ${locationText}${dueDateText}${tagText}${sequentialText}.` }] }; } else { // Project creation failed return { content: [{ type: "text" as const, text: `Failed to create project: ${result.error}` }], isError: true }; } } catch (err: unknown) { const error = err as Error; console.error(`Tool execution error: ${error.message}`); return { content: [{ type: "text" as const, text: `Error creating project: ${error.message}` }], isError: true }; } }
- Core helper function that generates AppleScript for creating an OmniFocus project and executes it via osascript, returning success status, project ID, or error.export async function addProject(params: AddProjectParams): Promise<{success: boolean, projectId?: string, error?: string}> { try { // Generate AppleScript const script = generateAppleScript(params); console.error("Executing AppleScript directly..."); // Execute AppleScript directly const { stdout, stderr } = await execAsync(`osascript -e '${script}'`); if (stderr) { console.error("AppleScript stderr:", stderr); } console.error("AppleScript stdout:", stdout); // Parse the result try { const result = JSON.parse(stdout); // Return the result return { success: result.success, projectId: result.projectId, error: result.error }; } catch (parseError) { console.error("Error parsing AppleScript result:", parseError); return { success: false, error: `Failed to parse result: ${stdout}` }; } } catch (error: any) { console.error("Error in addProject:", error); return { success: false, error: error?.message || "Unknown error in addProject" }; } }