MCP server for reading OmniFocus tasks and projects via AppleScript
omnifocus-mcp demonstrates solid tool naming, clear descriptions, and well-structured schemas with proper Zod validation. All 8 tools follow verb_noun naming conventions and include actionable descriptions (194-char average aligns with baseline). Parameters are typed and described. However, there are notable gaps: no output schemas documented (critical for LLM planning), limited error guidance beyond basic wrapping, missing error recovery hints, no pagination for list tools, and no tool annotations (readOnlyHint/destructiveHint). The server operates over STDIO, limiting remote accessibility. File-based tool implementations (add-task.ts sample) show competent Zod schema work, but the missing pieces prevent higher scores.
Add a new task to OmniFocus. Creates the task in a specified project or in the Inbox if no project is given. Optionally sets due date, defer date, tags, flagged status, and a note.
Mark a task as complete in OmniFocus. Accepts a task_id (preferred) or exact task_name + project. Refuses to act if multiple tasks match.
Create a new project in OmniFocus. Optionally set the project type (parallel or sequential) and assign it to an existing folder.
Get completed tasks from OmniFocus for a given time period. Returns task ID, name, project, flagged status, due date, defer date, note, completion date, and tags. Requires a 'since' date to bound the query.
Get active projects from OmniFocus with their task counts.
Get all tags from OmniFocus. Returns tag names.
No output schemas documented. LLMs cannot plan downstream operations or extract return values without knowing what fields to expect. Critical for tools like omnifocus_get_tasks and omnifocus_get_projects.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). LLMs cannot distinguish safe read tools from irreversible writes. Write tools (omnifocus_complete_task, omnifocus_add_task, omnifocus_update_task, omnifocus_create_project) should be marked destructiveHint:true or idempotentHint:true.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 63 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 59 | - | v1 |
Get incomplete tasks from OmniFocus. Excludes tasks inside completed or dropped projects or parent tasks, matching what OmniFocus shows. Returns task ID, name, project, flagged status, due date, defer date, note, and tags.
Update an existing task in OmniFocus by ID. Can change name, due date, defer date, flagged status, note, and tags.
Error handling is generic (wrapHandler catches all exceptions and returns isError:true with raw message). No recovery guidance, error classification, or context about what the LLM should try next. E.g., if omnifocus_complete_task fails with 'task not found', should suggest omnifocus_get_tasks to search by name.
No pagination support for list tools. omnifocus_get_tasks and omnifocus_get_completed_tasks could return unbounded results. Should add limit, offset/cursor, and total_count to prevent context window exhaustion.
omnifocus_get_projects and omnifocus_get_tags lack detail. Descriptions are too generic ('Get active projects from OmniFocus with their task counts' and 'Get all tags from OmniFocus'). No guidance on when to call these as discovery tools before other operations.
Partial parameter documentation gap: omnifocus_get_completed_tasks requires 'since' but doesn't explain the exact format or validation rules. Should state 'ISO 8601 date (YYYY-MM-DD) required; tasks completed on or after this date'.
No confirmation or dry-run pattern for destructive tools. omnifocus_complete_task and omnifocus_add_task are irreversible, should support a 'dry_run' parameter or confirmation step to prevent accidental execution.