OmniFocus MCP Server
# of-mcp
> An MCP server for OmniFocus. Originally forked from [jqlts1/omnifocus-mcp-enhanced](https://github.com/jqlts1/omnifocus-mcp-enhanced), now maintained independently with additional features.
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
[](https://www.apple.com/macos/)
> **Transform OmniFocus into an AI-powered productivity powerhouse**
Enhanced Model Context Protocol (MCP) server for OmniFocus featuring **project review workflow**, **planned date support**, **repeating task support**, **native custom perspective access**, hierarchical task display, AI-optimized tool selection, and comprehensive task management. Perfect integration with Claude AI for intelligent workflows.
## ✨ Key Features
### 📋 **Project Review Workflow**
- **🔍 Find Due Reviews** - Get projects that need review with `get_projects_for_review`
- **✅ Mark Reviewed** - Mark projects as reviewed individually or in batch
- **⏰ Set Intervals** - Configure review intervals in days
- **📊 Track Progress** - View next review date, last reviewed, and interval for each project
### 📋 **Planned Date Support**
- **📅 Schedule Work** - Set when you intend to work on a task (separate from due date)
- **🔍 Filter by Planned** - Find tasks planned for today, this week, or date ranges
- **📊 Sort by Planned** - Order tasks by their planned date
- **🔄 Full CRUD** - Create, read, update, and clear planned dates
### 🔄 **Repeating Tasks**
- **📅 Flexible Frequencies** - Daily, weekly, monthly, or yearly repetition
- **🎯 Custom Intervals** - Repeat every N days/weeks/months
- **📆 Specific Days** - Weekly tasks on specific days (e.g., Mon/Wed/Fri)
- **📅 Weekday-of-Month** - First Monday, last Friday, third Wednesday patterns
- **🔁 Repeat From** - Choose to repeat from due date or completion date
### 🌟 **Native Custom Perspective Access**
- **🎯 Direct Integration** - Native access to your OmniFocus custom perspectives via `Perspective.Custom` API
- **🌳 Hierarchical Display** - Tree-style task visualization with parent-child relationships
- **🧠 AI-Optimized** - Enhanced tool descriptions prevent AI confusion between perspectives and tags
- **⚡ Zero Setup** - Works with your existing custom perspectives instantly
### 🏗️ **Complete Task Management**
- **🏗️ Subtask Support** - Create hierarchical tasks with parent-child relationships
- **📁 Folder Management** - Create and nest folders for project organization
- **🔍 Built-in Perspectives** - Access Inbox, Flagged, Forecast, and Tag-based views
- **🚀 Ultimate Task Filter** - Advanced filtering beyond OmniFocus native capabilities
- **🎯 Batch Operations** - Add/edit/remove multiple items with true batching (9-12x faster)
- **📊 Smart Querying** - Find tasks, projects, or folders by ID or name
- **🔗 Consistent ID Support** - All tools accept both IDs and names (IDs take priority for reliability)
- **🔄 Full CRUD Operations** - Create, read, update, delete tasks, projects, and folders
- **📅 Time Management** - Due dates, defer dates, planned dates, creation dates (displayed in all task outputs), estimates, and scheduling
- **🏷️ Advanced Tagging** - Multi-tag filtering with any/all matching, exact/partial search, and auto-creation of missing tags
- **🤖 AI Integration** - Seamless Claude AI integration for intelligent workflows
## 📦 Installation
1. Clone the repository:
```bash
git clone https://github.com/mojenmojen/of-mcp.git
cd of-mcp
npm install && npm run build
```
**Faster build** (skips type checking):
```bash
npm run build:fast
```
This uses esbuild (~14ms) instead of tsc. See [Troubleshooting](#troubleshooting) for details.
2. Add to Claude Code:
```bash
claude mcp add omnifocus -- node "/path/to/of-mcp/dist/server.js"
```
## 📋 Requirements
- **macOS 10.15+** - OmniFocus is macOS-only
- **OmniFocus 3+** - The application must be installed and running
- **OmniFocus Pro** - Required for custom perspectives (new features in v1.6.0)
- **Node.js 18+** - For running the MCP server
- **Claude Code** - For MCP integration
## 🎯 Core Capabilities
### 1. 🏗️ Subtask Management
Create complex task hierarchies with ease:
```json
// Create task in project (by name or ID)
{
"name": "Analyze competitor keywords",
"projectName": "SEO Strategy",
"note": "Focus on top 10 competitors",
"dueDate": "2025-01-15",
"estimatedMinutes": 120,
"tags": ["SEO", "Research"]
}
// Create task by project ID
{
"name": "Write content outline",
"projectId": "projectId123",
"flagged": true,
"estimatedMinutes": 60
}
// Create subtask by parent task ID
{
"name": "Research top competitors",
"parentTaskId": "loK2xEAY4H1",
"estimatedMinutes": 30
}
```
### 2. 📁 Folder Management
Organize projects with nested folders:
```bash
# Create a top-level folder
add_folder {
"name": "Work Projects"
}
# Create a nested folder (by name or ID)
add_folder {
"name": "Q1 2025",
"parentFolderName": "Work Projects"
}
add_folder {
"name": "Marketing",
"parentFolderId": "folderId123"
}
# Create a project in a folder (by name or ID)
add_project {
"name": "New Website",
"folderName": "Work Projects"
}
add_project {
"name": "Mobile App",
"folderId": "folderId123"
}
```
#### Folder Path Disambiguation
When folders share the same name at different levels (e.g., both `Personal > Areas` and `Work > Areas`), use the full path with ` > ` separators to disambiguate:
```bash
# Disambiguate folders with the same name
get_folder_by_id { "folderName": "Work > Areas" }
get_folder_by_id { "folderName": "Personal > Areas" }
# Filter projects by disambiguated folder
list_projects { "folderName": "Work > Areas" }
# A plain name shared by more than one folder is ambiguous and returns an error
# listing each candidate's full path and ID (v2.0.0+)
get_folder_by_id { "folderName": "Areas" }
```
Path syntax is supported everywhere a folder-name parameter (`folderName`, `parentFolderName` or `newFolderName`) is accepted: `add_project`, `add_folder`, `edit_item`, `duplicate_project`, `batch_add_items`, `batch_edit_items`, `list_projects`, and `get_folder_by_id`.
**Duplicate folder names:** if a folder name or path (`folderName`, `newFolderName` or `parentFolderName`) matches more than one folder, the call fails (in `batch_add_items` and `batch_edit_items`, only that item fails) with an error listing each candidate's full path and folder ID. Disambiguate with `"Parent > Child"` path syntax, or pass the candidate's ID (`folderId`, `newFolderId` or `parentFolderId`; the error names the one your tool takes). When a top-level folder shares its name with a nested one, the path selects the nested copy, so only the top-level copy needs its ID. Two folders with the same full path both need their IDs. A candidate that is dropped, or sits inside a dropped folder, is marked `dropped` or `inside a dropped folder` after its ID, because a project filed into it would be dropped too. `edit_item` and `batch_edit_items` check the folder before changing anything else. Known limitation (v2.0.0): a `batch_add_items` or `batch_edit_items` call in which every item fails shows a generic error instead of the candidate list (#146).
### 3. 🔍 Perspective Views
Access all major OmniFocus perspectives:
```bash
# Inbox perspective
get_inbox_tasks {"hideCompleted": true}
# Flagged tasks (filter by project name or ID)
get_flagged_tasks {"projectFilter": "SEO Project"}
get_flagged_tasks {"projectId": "abc123xyz"}
# Forecast (next 7 days)
get_forecast_tasks {"days": 7, "hideCompleted": true}
# Tasks by tag name (single or multiple)
get_tasks_by_tag {"tagName": "AI", "exactMatch": false}
get_tasks_by_tag {"tagName": ["work", "urgent", "focus"]}
# Tasks by tag ID (single or multiple)
get_tasks_by_tag {"tagId": "tagId123"}
get_tasks_by_tag {"tagId": ["tagId1", "tagId2"]}
# Tasks by multiple tags (AND - all of these tags)
get_tasks_by_tag {"tagName": ["home", "errands"], "tagMatchMode": "all"}
# Include dropped/inactive tags in search
get_tasks_by_tag {"tagId": "droppedTagId", "includeDropped": true}
# List all tags (fast - ~400ms)
list_tags {}
# List all tags with task counts (slower - ~15s)
list_tags {"showTaskCounts": true}
# Include dropped/inactive tags
list_tags {"includeDropped": true}
```
### 4. 🚀 Ultimate Task Filter
Create any perspective imaginable with advanced filtering:
```bash
# Time management view (30min tasks due this week)
filter_tasks {
"taskStatus": ["Available", "Next"],
"estimateMax": 30,
"dueThisWeek": true
}
# Deep work view (60+ minute tasks with notes)
filter_tasks {
"estimateMin": 60,
"hasNote": true,
"taskStatus": ["Available"]
}
# Project overdue tasks (filter by name or ID)
filter_tasks {
"projectFilter": "Website Redesign",
"taskStatus": ["Overdue", "DueSoon"]
}
# Find untagged tasks (useful after bulk tag cleanup)
filter_tasks {
"untagged": true,
"taskStatus": ["Available", "Next"]
}
# Filter by project ID and tag ID (for programmatic use)
filter_tasks {
"projectId": "projectId123",
"tagId": ["tagId1", "tagId2"],
"taskStatus": ["Available"]
}
```
### 5. 🔄 Repeating Tasks
Create and manage recurring tasks with flexible repetition rules:
```bash
# Daily repeating task
add_omnifocus_task {
"name": "Daily standup notes",
"projectName": "Work",
"dueDate": "2025-01-15",
"repetitionRule": {
"frequency": "daily"
}
}
# Weekly task on Mon/Wed/Fri
add_omnifocus_task {
"name": "Exercise",
"dueDate": "2025-01-15",
"repetitionRule": {
"frequency": "weekly",
"daysOfWeek": [1, 3, 5]
}
}
# Monthly task on the 15th, repeat from completion
add_omnifocus_task {
"name": "Pay bills",
"dueDate": "2025-01-15",
"repetitionRule": {
"frequency": "monthly",
"dayOfMonth": 15,
"repeatFrom": "completion"
}
}
# First Monday of every month (weekday-of-month pattern)
add_omnifocus_task {
"name": "Prepare for monthly HOA meeting",
"dueDate": "2026-02-02",
"repetitionRule": {
"frequency": "monthly",
"weekdayOfMonth": {
"week": 1,
"day": 1
},
"repeatFrom": "due"
}
}
# Last Friday of every month
add_omnifocus_task {
"name": "Monthly expense report",
"dueDate": "2026-01-31",
"repetitionRule": {
"frequency": "monthly",
"weekdayOfMonth": {
"week": -1,
"day": 5
}
}
}
# Third Wednesday of every 2 months
add_omnifocus_task {
"name": "Quarterly planning prep",
"dueDate": "2026-01-21",
"repetitionRule": {
"frequency": "monthly",
"interval": 2,
"weekdayOfMonth": {
"week": 3,
"day": 3
}
}
}
# Edit task to add/remove repetition
edit_item {
"id": "taskId123",
"itemType": "task",
"newRepetitionRule": {"frequency": "weekly", "interval": 2}
}
# Remove repetition from a task
edit_item {
"id": "taskId123",
"itemType": "task",
"newRepetitionRule": null
}
# Move a task to a different project (by ID)
edit_item {
"id": "taskId123",
"itemType": "task",
"newProjectId": "projectId456"
}
# Move a project to a different folder (by ID)
edit_item {
"id": "projectId123",
"itemType": "project",
"newFolderId": "folderId456"
}
```
### 6. 🌟 Native Custom Perspective Access
Access your OmniFocus custom perspectives with hierarchical task display:
```bash
# List all your custom perspectives
list_custom_perspectives {"format": "detailed"}
# Get tasks from custom perspective by name
get_custom_perspective_tasks {
"perspectiveName": "Today's Work", # Your custom perspective name
"showHierarchy": true, # Enable tree display
"hideCompleted": true,
"ignoreFocus": true # Clear Focus mode to see all tasks (default: true)
}
# Get tasks from custom perspective by ID
get_custom_perspective_tasks {
"perspectiveId": "perspectiveId123",
"showHierarchy": true
}
# Examples with different perspectives
get_custom_perspective_tasks {
"perspectiveName": "Today Review",
"showHierarchy": true
}
get_custom_perspective_tasks {
"perspectiveName": "Weekly Planning",
"showHierarchy": false # Flat display
}
# Example output (flat view):
# 1. **Review quarterly goals** [ID: j-Q4cm6ewVF]
# Tags: planning
# Due: 1/31/2025
# Example output (hierarchical view):
# ├─ **Launch Product Campaign**
# │ ID: abc123xyz
# │ Tags: Campaign, Priority
# │ Due: 2/15/2025
```
**Why This Is Powerful:**
- ✅ **Native Integration** - Uses OmniFocus `Perspective.Custom` API directly
- ✅ **Tree Structure** - Visual parent-child task relationships with ├─, └─ symbols
- ✅ **Task IDs Included** - Build `omnifocus:///task/{id}` deep links directly from output
- ✅ **AI-Friendly** - Enhanced descriptions prevent tool selection confusion
- ✅ **Professional Output** - Clean, readable task hierarchies
### 7. 🔍 Batch Filter Tasks
Filter tasks across multiple projects in a single call (much faster than multiple filter_tasks calls):
```bash
# Get tasks from multiple projects at once
batch_filter_tasks {
"projectNames": ["Website Redesign", "Marketing Campaign", "Q1 Planning"],
"taskStatus": ["Available", "Next", "Blocked"],
"limit": 50
}
# Filter by project IDs for reliability
batch_filter_tasks {
"projectIds": ["projectId1", "projectId2", "projectId3"],
"taskStatus": ["Available", "Overdue"],
"flagged": true
}
# Combine with due date filters
batch_filter_tasks {
"projectNames": ["Daily Tasks", "Weekly Review"],
"dueThisWeek": true,
"sortBy": "dueDate"
}
```
**Benefits:**
- Single API call instead of N calls for N projects
- Results grouped by project with task counts
- Supports all common filters (status, flagged, due dates)
- Returns project IDs for follow-up operations
### 8. 🎯 Batch Write Operations
Efficiently manage multiple tasks with true batching (9-12x faster than individual calls):
```bash
# Batch add multiple tasks/projects (by name or ID)
batch_add_items {
"items": [
{
"type": "task",
"name": "Website Technical SEO",
"projectName": "SEO Project", # or use projectId
"note": "Optimize technical aspects"
},
{
"type": "task",
"name": "Page Speed Optimization",
"parentTaskName": "Website Technical SEO", # or use parentTaskId
"estimatedMinutes": 180,
"flagged": true
},
{
"type": "project",
"name": "New Project",
"folderId": "folderId123" # or use folderName
}
]
}
# Batch edit multiple items
batch_edit_items {
"edits": [
{
"id": "taskId1",
"itemType": "task",
"newStatus": "completed"
},
{
"id": "taskId2",
"itemType": "task",
"newDueDate": "2025-02-01",
"newFlagged": true,
"newProjectId": "projectId123" # Move task to another project by ID
},
{
"id": "projectId1",
"itemType": "project",
"newNote": "Updated via batch edit",
"newFolderName": "Work Projects" # Move project to another folder by name
}
]
}
# Batch update tags (works on both tasks AND projects, auto-creates missing tags)
batch_edit_items {
"edits": [
{
"id": "taskId1",
"itemType": "task",
"addTags": ["urgent", "review"],
"removeTags": ["someday"]
},
{
"id": "projectId1",
"itemType": "project",
"addTags": ["Q1", "active"]
},
{
"id": "taskId2",
"itemType": "task",
"replaceTags": ["priority", "work"]
}
]
}
# Batch remove multiple items
batch_remove_items {
"items": [
{"id": "taskId1", "itemType": "task"},
{"id": "taskId2", "itemType": "task"},
{"name": "Old Project", "itemType": "project"}
]
}
```
### 9. 📋 Project Review Workflow
Automate your weekly review process:
```bash
# Get all projects due for review
get_projects_for_review {
"includeOnHold": false,
"limit": 50
}
# Mark a single project as reviewed
edit_item {
"id": "projectId123",
"itemType": "project",
"markReviewed": true
}
# Set a project's review interval to 14 days
edit_item {
"id": "projectId123",
"itemType": "project",
"newReviewInterval": 14
}
# Batch mark multiple projects as reviewed (by ID)
batch_mark_reviewed {
"projectIds": ["projectId1", "projectId2", "projectId3"]
}
# Batch mark by project names
batch_mark_reviewed {
"projectNames": ["Marketing Campaign", "Website Redesign"]
}
# View project review info
get_project_by_id {
"projectName": "My Project"
}
# Returns: reviewInterval, nextReviewDate, lastReviewDate
```
**Review Workflow Benefits:**
- Automate finding projects that need attention
- Mark multiple projects reviewed in one operation
- Track when each project was last reviewed
- Set custom review intervals per project
## 🛠️ Complete Tool Reference
### 📊 Database & Task Management
1. **add_omnifocus_task** - Create tasks (enhanced with subtask support)
2. **add_project** - Create projects
3. **add_folder** - Create folders (with nesting support)
4. **remove_item** - Delete tasks or projects
5. **edit_item** - Edit tasks or projects
6. **batch_add_items** - Bulk add tasks/projects (true batching - 9x faster)
7. **batch_edit_items** - Bulk edit tasks/projects (true batching - 12x faster)
8. **batch_remove_items** - Bulk remove (true batching - 9x faster)
9. **get_task_by_id** - Query task information (includes subtasks with status, flags, and nesting depth)
10. **list_projects** - List projects with folder/status filtering
### 🔍 Built-in Perspective Tools
11. **get_inbox_tasks** - Inbox perspective
12. **get_flagged_tasks** - Flagged perspective
13. **get_forecast_tasks** - Forecast perspective (due/deferred tasks)
14. **get_tasks_by_tag** - Tag-based filtering (single or multiple tags with any/all matching)
15. **list_tags** - List all tags with task counts and hierarchy
16. **filter_tasks** - Ultimate filtering with unlimited combinations
17. **batch_filter_tasks** - Filter multiple projects in one call (faster than multiple filter_tasks)
### 🌟 Custom Perspective Tools
18. **list_custom_perspectives** - List all custom perspectives with details
19. **get_custom_perspective_tasks** - Access custom perspective with hierarchical display
### 📊 Analytics & Tracking
20. **get_today_completed_tasks** - View today's completed tasks
### 📋 Project Review Tools
21. **get_projects_for_review** - Get projects due for review
22. **batch_mark_reviewed** - Mark multiple projects as reviewed
### 🔧 Utility Tools
23. **get_server_version** - Get server version and build information
24. **get_project_by_id** - Query project information by ID or name (includes review data)
25. **get_folder_by_id** - Query folder information by ID or name
26. **diagnose_connection** - Check OmniFocus connectivity and permissions
### 🆕 New Tools (v1.23.0)
27. **search_tasks** - Full-text search across task names and notes (simpler than filter_tasks)
28. **duplicate_project** - Create a copy of a project including all tasks (great for templates)
29. **edit_tag** - Edit tag properties: rename, change status, move to parent, or set allowsNextAction
### 🆕 New Tools (v1.27.0) - AI Assistant Optimizations
30. **get_system_health** - Get all health metrics in ONE call (inbox, projects, tasks, tags, flagged, untagged)
31. **get_completion_stats** - Get completion counts grouped by project/tag/folder for a date range
## 🚀 Quick Start Examples
### Basic Task Creation
```bash
# Simple task
add_omnifocus_task {
"name": "Review quarterly goals",
"projectName": "Planning",
"dueDate": "2025-01-31"
}
```
### Advanced Task Management
```bash
# Create parent task
add_omnifocus_task {
"name": "Launch Product Campaign",
"projectName": "Marketing",
"dueDate": "2025-02-15",
"tags": ["Campaign", "Priority"]
}
# Add subtasks
add_omnifocus_task {
"name": "Design landing page",
"parentTaskName": "Launch Product Campaign",
"estimatedMinutes": 240,
"flagged": true
}
```
### Smart Task Discovery
```bash
# Find high-priority work
filter_tasks {
"flagged": true,
"taskStatus": ["Available"],
"estimateMax": 120,
"hasEstimate": true
}
# Today's completed work
filter_tasks {
"completedToday": true,
"taskStatus": ["Completed"],
"sortBy": "project"
}
```
### Custom Perspective Usage
```bash
# List your custom perspectives
list_custom_perspectives {"format": "detailed"}
# Access a custom perspective with hierarchy
get_custom_perspective_tasks {
"perspectiveName": "Today Review",
"showHierarchy": true,
"hideCompleted": true
}
# Quick flat view of weekly planning
get_custom_perspective_tasks {
"perspectiveName": "Weekly Planning",
"showHierarchy": false
}
```
### 🔍 Search Tasks (New in v1.23.0)
```bash
# Simple text search across names and notes
search_tasks {
"query": "budget report"
}
# Search with match modes
search_tasks {
"query": "meeting budget",
"matchMode": "anyWord" # matches either "meeting" or "budget"
}
search_tasks {
"query": "quarterly review",
"matchMode": "allWords", # must contain both words
"includeCompleted": true
}
# Search within a specific project
search_tasks {
"query": "design",
"projectName": "Website Redesign",
"searchIn": "name" # only search task names, not notes
}
```
### 📋 Duplicate Project (New in v1.23.0)
```bash
# Create a copy of a template project
duplicate_project {
"sourceProjectName": "Sprint Template",
"newName": "Sprint 15"
}
# Duplicate with date shifting (great for recurring workflows)
duplicate_project {
"sourceProjectName": "Weekly Review Checklist",
"newName": "Week 3 Review",
"shiftDates": {
"referenceDate": "2026-01-20",
"basedOn": "defer"
}
}
# Duplicate into a specific folder
duplicate_project {
"sourceProjectId": "templateProjectId123",
"newName": "Q1 Marketing Campaign",
"folderName": "2026 Projects",
"clearCompleted": true,
"copyTags": true
}
```
### 🏷️ Edit Tag (New in v1.23.0)
```bash
# Reactivate a dropped tag
edit_tag {
"tagName": "prep",
"newStatus": "active"
}
# Put a tag on hold (tasks with this tag become blocked)
edit_tag {
"tagName": "office",
"newStatus": "onHold"
}
# Rename a tag
edit_tag {
"tagId": "tagId123",
"newName": "high-priority"
}
# Move tag to a different parent
edit_tag {
"tagName": "errands",
"newParentTagName": "personal"
}
# Make a tag top-level (remove from parent)
edit_tag {
"tagName": "urgent",
"newParentTagId": ""
}
```
## 🤖 AI Assistant Efficiency Guide
### Use `batch_filter_tasks` for Multi-Project Queries
Instead of making separate `filter_tasks` calls for each project:
```bash
# ❌ Inefficient - 5 API calls
filter_tasks { "projectFilter": "Project A", "taskStatus": [...] }
filter_tasks { "projectFilter": "Project B", "taskStatus": [...] }
filter_tasks { "projectFilter": "Project C", "taskStatus": [...] }
# ... etc
```
Use a single batch call:
```bash
# ✅ Efficient - 1 API call
batch_filter_tasks {
"projectNames": ["Project A", "Project B", "Project C", "Project D", "Project E"],
"taskStatus": ["Available", "Next", "Blocked", "DueSoon", "Overdue"],
"limit": 100
}
```
### Use IDs for Reliability
All tools support both name and ID parameters. **IDs are more reliable** because they don't change when items are renamed.
| Tool | ID Parameter | Alternative To |
|------|--------------|----------------|
| `add_omnifocus_task` | `projectId` | `projectName` |
| `add_project` | `folderId` | `folderName` |
| `add_folder` | `parentFolderId` | `parentFolderName` |
| `duplicate_project` | `sourceProjectId`, `folderId` | name equivalents |
| `get_folder_by_id` | `folderId` | `folderName` |
| `list_projects` | `folderId` | `folderName` |
| `edit_item` | `newProjectId`, `newFolderId` | name equivalents |
| `batch_edit_items` | `newProjectId`, `newFolderId` | name equivalents |
| `batch_add_items` | `projectId`, `folderId` | name equivalents |
| `filter_tasks` | `projectId`, `tagId` | `projectFilter`, `tagFilter` |
| `get_tasks_by_tag` | `tagId` | `tagName` |
| `get_flagged_tasks` | `projectId` | `projectFilter` |
| `get_custom_perspective_tasks` | `perspectiveId` | `perspectiveName` |
| `batch_filter_tasks` | `projectIds` | `projectNames` |
**Rule:** When both ID and name are provided, ID takes priority. If a folder ID matches no folder, tools differ (#148). `add_folder` and `duplicate_project` fail. `list_projects` returns an empty list without consulting the name. `add_project`, `batch_add_items`, `edit_item`, `batch_edit_items` and `get_folder_by_id` fall back to the name, and fail if that doesn't resolve either.
### Batch Operations for Writes
Use batch tools for multiple write operations:
- `batch_add_items` - Add multiple tasks/projects (9x faster)
- `batch_edit_items` - Edit multiple items (12x faster)
- `batch_remove_items` - Remove multiple items (9x faster)
## 🔧 Configuration
### Verify Installation
```bash
# Check MCP status
claude mcp list
# Verify server version (returns version + build provenance block)
get_server_version
# Response includes a `build` object: { commit, dirty, contentHash, buildStale }
# buildStale: true → running process predates the on-disk build; restart the server
# To confirm you are also on the right source, compare build.commit with:
# git rev-parse --short HEAD (buildStale alone only proves process = disk)
# Test basic connection
get_inbox_tasks
# Test custom perspective features
list_custom_perspectives
```
### Analytics & Health Checks (v1.27.0)
```bash
# Get all health metrics in ONE call (replaces 6+ separate calls)
get_system_health
# Get completion stats by project for last month
get_completion_stats {
"completedAfter": "2026-01-01",
"completedBefore": "2026-02-01",
"groupBy": "project"
}
# Get completion stats by tag
get_completion_stats {
"completedAfter": "2026-01-01",
"completedBefore": "2026-02-01",
"groupBy": "tag"
}
# Fast count-only query (no task data returned)
filter_tasks {
"taskStatus": ["Available", "Next"],
"countOnly": true
}
```
### Troubleshooting
**Build issues:**
- If `npm run build` hangs or runs out of memory, check `npx tsc --version`. TypeScript 5.8.3 and 5.9.3 run out of memory type-checking this project against MCP SDK 1.25.2 (#136), so `package.json` caps it at `~5.6.3`. An install made before the cap may still have a newer version; run `npm ci` to reinstall from the lockfile.
- `npm run build:fast` uses esbuild, which skips type checking but produces a working server
- For type checking, run `npx tsc --noEmit` separately or rely on your IDE
**Runtime issues:**
- Ensure OmniFocus 3+ is installed and running
- Verify Node.js 18+ is installed
- Check Claude Code MCP configuration
- Enable accessibility permissions for terminal apps if needed
- Use `get_server_version` to verify the correct version is loaded after updates. The response now includes a `build` object (`commit`, `dirty`, `contentHash`, `buildStale`). `buildStale: true` means the running process predates the on-disk build — restart the server to clear it. Note that `buildStale: false` only proves the process matches the on-disk build; to confirm you are on the intended source, also compare `build.commit` against `git rev-parse --short HEAD`.
## 🎯 Use Cases
- **Project Management** - Create detailed project hierarchies with subtasks
- **GTD Workflow** - Leverage perspectives for Getting Things Done methodology
- **Time Blocking** - Filter by estimated time for schedule planning
- **Weekly Reviews** - Automate project reviews with `get_projects_for_review` and `batch_mark_reviewed`
- **Team Coordination** - Batch operations for team task assignment
- **AI-Powered Planning** - Let Claude analyze and organize your tasks
## 📈 Performance
- **True Batch Operations** - All batch tools execute in a single OmniFocus script call
- `batch_add_items`: ~138ms per item (9x faster than individual calls)
- `batch_edit_items`: ~76ms per item (12x faster than individual calls)
- `batch_remove_items`: ~65ms per item (9x faster than individual calls)
- **Fast ID Lookups** - Direct `Task.byIdentifier()` / `Project.byIdentifier()` API calls
- **Lazy Loading** - OmniFocus collections only loaded when needed
- **Fast Filtering** - Native AppleScript/OmniJS performance
- **Memory Optimized** - Minimal resource usage
- **Scalable** - Handles large task databases efficiently
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request
### Release Checklist
When releasing a new version:
1. Bump version in `package.json`
2. Update this README with any new features or tools
3. Commit and push changes
## 📄 License
MIT License - see [LICENSE](LICENSE) file for details.
## 🔗 Links
- **This Fork**: https://github.com/mojenmojen/of-mcp
- **Original Project**: https://github.com/jqlts1/omnifocus-mcp-enhanced
- **OmniFocus**: https://www.omnigroup.com/omnifocus/
- **Model Context Protocol**: https://modelcontextprotocol.io/
- **Claude Code**: https://docs.anthropic.com/en/docs/claude-code
## 🙏 Acknowledgments
Based on the original OmniFocus MCP server by [themotionmachine](https://github.com/themotionmachine/OmniFocus-MCP). Enhanced with perspective views, advanced filtering, and complete subtask support.
---
**⭐ Star this repo if it helps boost your productivity!**TDQS
Scored across 31 tools
Most tools have clearly distinct purposes, and descriptions actively steer agents between single-item and batch variants. However, the query surface (get_tasks_by_tag, filter_tasks, batch_filter_tasks, search_tasks, get_custom_perspective_tasks, get_system_health) has enough conceptual overlap that misselection is still plausible.
The set is predominantly snake_case verb_noun and is generally predictable. Minor deviations like add_omnifocus_task, batch_add_items, and the mix of get_task_by_id vs get_tasks_by_tag keep it from being perfectly consistent.
At 31 tools, the surface is heavy for a single MCP server, and much of the count comes from paired single-item and batch tools for the same operations. While OmniFocus is a broad domain, the duplication makes the set larger than necessary.
Task and project operations are well covered, including batch workflows, reviews, perspectives, search, and stats. However, folder and tag lifecycle coverage is incomplete (e.g., no clear folder edit/delete/list tools and no explicit tag creation/deletion), creating notable gaps.