omnifocus-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -0
  3. package/dist/config.d.ts +20 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +20 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +24 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/omnifocus/cache.d.ts +26 -0
  12. package/dist/omnifocus/cache.d.ts.map +1 -0
  13. package/dist/omnifocus/cache.js +68 -0
  14. package/dist/omnifocus/cache.js.map +1 -0
  15. package/dist/omnifocus/client.d.ts +84 -0
  16. package/dist/omnifocus/client.d.ts.map +1 -0
  17. package/dist/omnifocus/client.js +340 -0
  18. package/dist/omnifocus/client.js.map +1 -0
  19. package/dist/omnifocus/executor.d.ts +11 -0
  20. package/dist/omnifocus/executor.d.ts.map +1 -0
  21. package/dist/omnifocus/executor.js +62 -0
  22. package/dist/omnifocus/executor.js.map +1 -0
  23. package/dist/omnifocus/scripts/database.d.ts +6 -0
  24. package/dist/omnifocus/scripts/database.d.ts.map +1 -0
  25. package/dist/omnifocus/scripts/database.js +161 -0
  26. package/dist/omnifocus/scripts/database.js.map +1 -0
  27. package/dist/omnifocus/scripts/folders.d.ts +7 -0
  28. package/dist/omnifocus/scripts/folders.d.ts.map +1 -0
  29. package/dist/omnifocus/scripts/folders.js +73 -0
  30. package/dist/omnifocus/scripts/folders.js.map +1 -0
  31. package/dist/omnifocus/scripts/perspectives.d.ts +4 -0
  32. package/dist/omnifocus/scripts/perspectives.d.ts.map +1 -0
  33. package/dist/omnifocus/scripts/perspectives.js +62 -0
  34. package/dist/omnifocus/scripts/perspectives.js.map +1 -0
  35. package/dist/omnifocus/scripts/projects.d.ts +13 -0
  36. package/dist/omnifocus/scripts/projects.d.ts.map +1 -0
  37. package/dist/omnifocus/scripts/projects.js +235 -0
  38. package/dist/omnifocus/scripts/projects.js.map +1 -0
  39. package/dist/omnifocus/scripts/tags.d.ts +7 -0
  40. package/dist/omnifocus/scripts/tags.d.ts.map +1 -0
  41. package/dist/omnifocus/scripts/tags.js +91 -0
  42. package/dist/omnifocus/scripts/tags.js.map +1 -0
  43. package/dist/omnifocus/scripts/tasks.d.ts +23 -0
  44. package/dist/omnifocus/scripts/tasks.d.ts.map +1 -0
  45. package/dist/omnifocus/scripts/tasks.js +560 -0
  46. package/dist/omnifocus/scripts/tasks.js.map +1 -0
  47. package/dist/omnifocus/serializers.d.ts +16 -0
  48. package/dist/omnifocus/serializers.d.ts.map +1 -0
  49. package/dist/omnifocus/serializers.js +181 -0
  50. package/dist/omnifocus/serializers.js.map +1 -0
  51. package/dist/prompts.d.ts +3 -0
  52. package/dist/prompts.d.ts.map +1 -0
  53. package/dist/prompts.js +49 -0
  54. package/dist/prompts.js.map +1 -0
  55. package/dist/resources.d.ts +4 -0
  56. package/dist/resources.d.ts.map +1 -0
  57. package/dist/resources.js +48 -0
  58. package/dist/resources.js.map +1 -0
  59. package/dist/server.d.ts +7 -0
  60. package/dist/server.d.ts.map +1 -0
  61. package/dist/server.js +20 -0
  62. package/dist/server.js.map +1 -0
  63. package/dist/tools/database.d.ts +4 -0
  64. package/dist/tools/database.d.ts.map +1 -0
  65. package/dist/tools/database.js +60 -0
  66. package/dist/tools/database.js.map +1 -0
  67. package/dist/tools/folders.d.ts +4 -0
  68. package/dist/tools/folders.d.ts.map +1 -0
  69. package/dist/tools/folders.js +67 -0
  70. package/dist/tools/folders.js.map +1 -0
  71. package/dist/tools/index.d.ts +4 -0
  72. package/dist/tools/index.d.ts.map +1 -0
  73. package/dist/tools/index.js +15 -0
  74. package/dist/tools/index.js.map +1 -0
  75. package/dist/tools/perspectives.d.ts +4 -0
  76. package/dist/tools/perspectives.d.ts.map +1 -0
  77. package/dist/tools/perspectives.js +30 -0
  78. package/dist/tools/perspectives.js.map +1 -0
  79. package/dist/tools/projects.d.ts +4 -0
  80. package/dist/tools/projects.d.ts.map +1 -0
  81. package/dist/tools/projects.js +175 -0
  82. package/dist/tools/projects.js.map +1 -0
  83. package/dist/tools/tags.d.ts +4 -0
  84. package/dist/tools/tags.d.ts.map +1 -0
  85. package/dist/tools/tags.js +70 -0
  86. package/dist/tools/tags.js.map +1 -0
  87. package/dist/tools/tasks.d.ts +4 -0
  88. package/dist/tools/tasks.d.ts.map +1 -0
  89. package/dist/tools/tasks.js +356 -0
  90. package/dist/tools/tasks.js.map +1 -0
  91. package/dist/types/omnifocus.d.ts +313 -0
  92. package/dist/types/omnifocus.d.ts.map +1 -0
  93. package/dist/types/omnifocus.js +3 -0
  94. package/dist/types/omnifocus.js.map +1 -0
  95. package/dist/utils/dates.d.ts +23 -0
  96. package/dist/utils/dates.d.ts.map +1 -0
  97. package/dist/utils/dates.js +44 -0
  98. package/dist/utils/dates.js.map +1 -0
  99. package/dist/utils/errors.d.ts +25 -0
  100. package/dist/utils/errors.d.ts.map +1 -0
  101. package/dist/utils/errors.js +76 -0
  102. package/dist/utils/errors.js.map +1 -0
  103. package/dist/utils/logger.d.ts +7 -0
  104. package/dist/utils/logger.d.ts.map +1 -0
  105. package/dist/utils/logger.js +30 -0
  106. package/dist/utils/logger.js.map +1 -0
  107. package/package.json +53 -0
@@ -0,0 +1,175 @@
1
+ import { z } from "zod";
2
+ import { formatMcpError } from "../utils/errors.js";
3
+ export function registerProjectTools(server, client) {
4
+ server.tool("list_projects", "List projects from OmniFocus with optional filters for status, folder, and text search", {
5
+ status: z.enum(["active", "onHold", "done", "dropped"]).optional().describe("Filter by project status"),
6
+ folderId: z.string().optional().describe("Filter by containing folder ID"),
7
+ folderName: z.string().optional().describe("Filter by containing folder name"),
8
+ search: z.string().optional().describe("Full-text search in project name and note"),
9
+ limit: z.number().min(1).max(1000).optional().describe("Maximum results (default 100)"),
10
+ offset: z.number().min(0).optional().describe("Skip this many results"),
11
+ }, async (args) => {
12
+ try {
13
+ const projects = await client.listProjects(args);
14
+ return { content: [{ type: "text", text: JSON.stringify(projects, null, 2) }] };
15
+ }
16
+ catch (error) {
17
+ const { message } = formatMcpError(error);
18
+ return { content: [{ type: "text", text: message }], isError: true };
19
+ }
20
+ });
21
+ server.tool("get_project", "Get detailed information about a specific project by ID or name", {
22
+ idOrName: z.string().describe("The project ID or exact name"),
23
+ }, async ({ idOrName }) => {
24
+ try {
25
+ const project = await client.getProject(idOrName);
26
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
27
+ }
28
+ catch (error) {
29
+ const { message } = formatMcpError(error);
30
+ return { content: [{ type: "text", text: message }], isError: true };
31
+ }
32
+ });
33
+ server.tool("create_project", "Create a new project in OmniFocus", {
34
+ name: z.string().describe("Project name"),
35
+ note: z.string().optional().describe("Project note/description"),
36
+ folderId: z.string().optional().describe("Parent folder ID"),
37
+ folderName: z.string().optional().describe("Parent folder name"),
38
+ sequential: z.boolean().optional().describe("Whether tasks must be completed in order"),
39
+ singleActionList: z.boolean().optional().describe("Whether this is a single-action list"),
40
+ completedByChildren: z.boolean().optional().describe("Auto-complete when all children are completed"),
41
+ deferDate: z.string().optional().describe("Defer date (ISO 8601)"),
42
+ dueDate: z.string().optional().describe("Due date (ISO 8601)"),
43
+ flagged: z.boolean().optional().describe("Whether to flag the project"),
44
+ tags: z.array(z.string()).optional().describe("Tag names to apply"),
45
+ reviewInterval: z
46
+ .object({
47
+ steps: z.number().describe("Number of units between reviews"),
48
+ unit: z.enum(["day", "week", "month", "year"]).describe("Unit: 'day', 'week', 'month', 'year'"),
49
+ })
50
+ .optional()
51
+ .describe("Review interval"),
52
+ }, async (args) => {
53
+ try {
54
+ const project = await client.createProject(args);
55
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
56
+ }
57
+ catch (error) {
58
+ const { message } = formatMcpError(error);
59
+ return { content: [{ type: "text", text: message }], isError: true };
60
+ }
61
+ });
62
+ server.tool("update_project", "Update properties of an existing project", {
63
+ id: z.string().describe("The project ID"),
64
+ name: z.string().optional().describe("New project name"),
65
+ note: z.string().optional().describe("New project note"),
66
+ status: z.enum(["active", "onHold", "done", "dropped"]).optional().describe("New project status"),
67
+ sequential: z.boolean().optional().describe("Whether tasks must be completed in order"),
68
+ singleActionList: z.boolean().optional().describe("Whether this is a single-action list"),
69
+ completedByChildren: z.boolean().optional().describe("Auto-complete when all children are completed"),
70
+ deferDate: z.string().nullable().optional().describe("New defer date (ISO 8601) or null to clear"),
71
+ dueDate: z.string().nullable().optional().describe("New due date (ISO 8601) or null to clear"),
72
+ flagged: z.boolean().optional().describe("New flagged status"),
73
+ reviewInterval: z
74
+ .object({
75
+ steps: z.number().describe("Number of units between reviews"),
76
+ unit: z.enum(["day", "week", "month", "year"]).describe("Unit: 'day', 'week', 'month', 'year'"),
77
+ })
78
+ .optional()
79
+ .describe("New review interval"),
80
+ }, async (args) => {
81
+ try {
82
+ const project = await client.updateProject(args);
83
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
84
+ }
85
+ catch (error) {
86
+ const { message } = formatMcpError(error);
87
+ return { content: [{ type: "text", text: message }], isError: true };
88
+ }
89
+ });
90
+ server.tool("complete_project", "Mark a project as completed (done)", {
91
+ id: z.string().describe("The project ID to complete"),
92
+ }, async ({ id }) => {
93
+ try {
94
+ const project = await client.completeProject(id);
95
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
96
+ }
97
+ catch (error) {
98
+ const { message } = formatMcpError(error);
99
+ return { content: [{ type: "text", text: message }], isError: true };
100
+ }
101
+ });
102
+ server.tool("drop_project", "Mark a project as dropped (cancelled)", {
103
+ id: z.string().describe("The project ID to drop"),
104
+ }, async ({ id }) => {
105
+ try {
106
+ const project = await client.dropProject(id);
107
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
108
+ }
109
+ catch (error) {
110
+ const { message } = formatMcpError(error);
111
+ return { content: [{ type: "text", text: message }], isError: true };
112
+ }
113
+ });
114
+ server.tool("move_project", "Move a project to a different folder", {
115
+ projectId: z.string().describe("The project ID to move"),
116
+ folderId: z.string().describe("The destination folder ID"),
117
+ }, async ({ projectId, folderId }) => {
118
+ try {
119
+ const project = await client.moveProject(projectId, folderId);
120
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
121
+ }
122
+ catch (error) {
123
+ const { message } = formatMcpError(error);
124
+ return { content: [{ type: "text", text: message }], isError: true };
125
+ }
126
+ });
127
+ server.tool("delete_project", "Permanently delete a project from OmniFocus", {
128
+ id: z.string().describe("The project ID to delete"),
129
+ }, async ({ id }) => {
130
+ try {
131
+ const result = await client.deleteProject(id);
132
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
133
+ }
134
+ catch (error) {
135
+ const { message } = formatMcpError(error);
136
+ return { content: [{ type: "text", text: message }], isError: true };
137
+ }
138
+ });
139
+ server.tool("get_review_queue", "Get projects that are due for review", {}, async () => {
140
+ try {
141
+ const projects = await client.getReviewQueue();
142
+ return { content: [{ type: "text", text: JSON.stringify(projects, null, 2) }] };
143
+ }
144
+ catch (error) {
145
+ const { message } = formatMcpError(error);
146
+ return { content: [{ type: "text", text: message }], isError: true };
147
+ }
148
+ });
149
+ server.tool("mark_reviewed", "Mark a project as reviewed, advancing its next review date", {
150
+ id: z.string().describe("The project ID to mark as reviewed"),
151
+ }, async ({ id }) => {
152
+ try {
153
+ const project = await client.markReviewed(id);
154
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
155
+ }
156
+ catch (error) {
157
+ const { message } = formatMcpError(error);
158
+ return { content: [{ type: "text", text: message }], isError: true };
159
+ }
160
+ });
161
+ server.tool("get_project_tasks", "Get all tasks belonging to a specific project", {
162
+ projectId: z.string().describe("The project ID"),
163
+ includeCompleted: z.boolean().optional().describe("Include completed/dropped tasks (default false)"),
164
+ }, async (args) => {
165
+ try {
166
+ const tasks = await client.getProjectTasks(args);
167
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
168
+ }
169
+ catch (error) {
170
+ const { message } = formatMcpError(error);
171
+ return { content: [{ type: "text", text: message }], isError: true };
172
+ }
173
+ });
174
+ }
175
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/tools/projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { OmniFocusClient } from "../omnifocus/client.js";
3
+ export declare function registerTagTools(server: McpServer, client: OmniFocusClient): void;
4
+ //# sourceMappingURL=tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CA0FjF"}
@@ -0,0 +1,70 @@
1
+ import { z } from "zod";
2
+ import { formatMcpError } from "../utils/errors.js";
3
+ export function registerTagTools(server, client) {
4
+ server.tool("list_tags", "List all tags in OmniFocus", {}, async () => {
5
+ try {
6
+ const tags = await client.listTags();
7
+ return { content: [{ type: "text", text: JSON.stringify(tags, null, 2) }] };
8
+ }
9
+ catch (error) {
10
+ const { message } = formatMcpError(error);
11
+ return { content: [{ type: "text", text: message }], isError: true };
12
+ }
13
+ });
14
+ server.tool("get_tag", "Get detailed information about a tag including its child tags", {
15
+ id: z.string().describe("The tag ID"),
16
+ }, async ({ id }) => {
17
+ try {
18
+ const tag = await client.getTag(id);
19
+ return { content: [{ type: "text", text: JSON.stringify(tag, null, 2) }] };
20
+ }
21
+ catch (error) {
22
+ const { message } = formatMcpError(error);
23
+ return { content: [{ type: "text", text: message }], isError: true };
24
+ }
25
+ });
26
+ server.tool("create_tag", "Create a new tag in OmniFocus", {
27
+ name: z.string().describe("Tag name"),
28
+ parentTagId: z.string().optional().describe("Parent tag ID for nested tags"),
29
+ parentTagName: z.string().optional().describe("Parent tag name for nested tags"),
30
+ allowsNextAction: z.boolean().optional().describe("Whether tasks with this tag can be next actions (default true)"),
31
+ status: z.enum(["active", "onHold", "dropped"]).optional().describe("Tag status"),
32
+ }, async (args) => {
33
+ try {
34
+ const tag = await client.createTag(args);
35
+ return { content: [{ type: "text", text: JSON.stringify(tag, null, 2) }] };
36
+ }
37
+ catch (error) {
38
+ const { message } = formatMcpError(error);
39
+ return { content: [{ type: "text", text: message }], isError: true };
40
+ }
41
+ });
42
+ server.tool("update_tag", "Update a tag's properties", {
43
+ id: z.string().describe("The tag ID"),
44
+ name: z.string().optional().describe("New tag name"),
45
+ allowsNextAction: z.boolean().optional().describe("Whether tasks with this tag can be next actions"),
46
+ status: z.enum(["active", "onHold", "dropped"]).optional().describe("New tag status"),
47
+ }, async (args) => {
48
+ try {
49
+ const tag = await client.updateTag(args);
50
+ return { content: [{ type: "text", text: JSON.stringify(tag, null, 2) }] };
51
+ }
52
+ catch (error) {
53
+ const { message } = formatMcpError(error);
54
+ return { content: [{ type: "text", text: message }], isError: true };
55
+ }
56
+ });
57
+ server.tool("delete_tag", "Permanently delete a tag from OmniFocus", {
58
+ id: z.string().describe("The tag ID to delete"),
59
+ }, async ({ id }) => {
60
+ try {
61
+ const result = await client.deleteTag(id);
62
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
63
+ }
64
+ catch (error) {
65
+ const { message } = formatMcpError(error);
66
+ return { content: [{ type: "text", text: message }], isError: true };
67
+ }
68
+ });
69
+ }
70
+ //# sourceMappingURL=tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../src/tools/tags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { OmniFocusClient } from "../omnifocus/client.js";
3
+ export declare function registerTaskTools(server: McpServer, client: OmniFocusClient): void;
4
+ //# sourceMappingURL=tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/tools/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAuBzD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAkclF"}
@@ -0,0 +1,356 @@
1
+ import { z } from "zod";
2
+ import { formatMcpError } from "../utils/errors.js";
3
+ const repetitionRuleSchema = z.object({
4
+ ruleString: z.string().describe("ICS RRULE string e.g. 'FREQ=WEEKLY;INTERVAL=1'"),
5
+ method: z.enum(["fixed", "startAfterCompletion", "dueAfterCompletion"]).describe("Repetition method"),
6
+ }).optional().describe("Repetition rule for recurring tasks");
7
+ const batchTaskItemSchema = z.lazy(() => z.object({
8
+ name: z.string().describe("Task name"),
9
+ note: z.string().optional().describe("Task note"),
10
+ flagged: z.boolean().optional().describe("Whether to flag"),
11
+ deferDate: z.string().optional().describe("Defer date (ISO 8601)"),
12
+ dueDate: z.string().optional().describe("Due date (ISO 8601)"),
13
+ estimatedMinutes: z.number().min(0).optional().describe("Estimated duration in minutes"),
14
+ completedByChildren: z.boolean().optional().describe("Auto-complete when children complete"),
15
+ tags: z.array(z.string()).optional().describe("Tag names"),
16
+ repetitionRule: repetitionRuleSchema,
17
+ children: z.array(batchTaskItemSchema).optional().describe("Subtasks"),
18
+ }));
19
+ export function registerTaskTools(server, client) {
20
+ server.tool("list_tasks", "List tasks from OmniFocus with optional filters for status, flags, tags, projects, date ranges, and text search", {
21
+ completed: z.boolean().optional().describe("Filter by completion status"),
22
+ flagged: z.boolean().optional().describe("Filter by flagged status"),
23
+ available: z.boolean().optional().describe("Only show available (actionable) tasks"),
24
+ inInbox: z.boolean().optional().describe("Only show inbox tasks"),
25
+ projectId: z.string().optional().describe("Filter by project ID"),
26
+ projectName: z.string().optional().describe("Filter by project name"),
27
+ tagNames: z.array(z.string()).optional().describe("Filter by tag names (all must match)"),
28
+ dueAfter: z.string().optional().describe("Filter tasks due after this ISO date"),
29
+ dueBefore: z.string().optional().describe("Filter tasks due before this ISO date"),
30
+ deferAfter: z.string().optional().describe("Filter tasks deferred after this ISO date"),
31
+ deferBefore: z.string().optional().describe("Filter tasks deferred before this ISO date"),
32
+ search: z.string().optional().describe("Full-text search in task name and note"),
33
+ taskStatus: z.enum(["available", "remaining", "completed", "dropped"]).optional().describe("Filter by task status"),
34
+ limit: z.number().min(1).max(1000).optional().describe("Maximum results (default 100)"),
35
+ offset: z.number().min(0).optional().describe("Skip this many results"),
36
+ }, async (args) => {
37
+ try {
38
+ const tasks = await client.listTasks(args);
39
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
40
+ }
41
+ catch (error) {
42
+ const { message } = formatMcpError(error);
43
+ return { content: [{ type: "text", text: message }], isError: true };
44
+ }
45
+ });
46
+ server.tool("get_task", "Get detailed information about a specific task by its ID, optionally including subtask hierarchy", {
47
+ id: z.string().describe("The task ID"),
48
+ includeChildren: z.boolean().optional().describe("Include subtask tree (default false)"),
49
+ maxDepth: z.number().min(0).optional().describe("Max subtask depth (0 = unlimited)"),
50
+ }, async (args) => {
51
+ try {
52
+ const task = await client.getTask(args);
53
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
54
+ }
55
+ catch (error) {
56
+ const { message } = formatMcpError(error);
57
+ return { content: [{ type: "text", text: message }], isError: true };
58
+ }
59
+ });
60
+ server.tool("create_task", "Create a new task in OmniFocus. By default creates in inbox; specify projectId or projectName to add to a project.", {
61
+ name: z.string().describe("Task name"),
62
+ note: z.string().optional().describe("Task note/description"),
63
+ flagged: z.boolean().optional().describe("Whether to flag the task"),
64
+ deferDate: z.string().optional().describe("Defer date (ISO 8601)"),
65
+ dueDate: z.string().optional().describe("Due date (ISO 8601)"),
66
+ estimatedMinutes: z.number().min(0).optional().describe("Estimated duration in minutes"),
67
+ completedByChildren: z.boolean().optional().describe("Auto-complete when all children are completed"),
68
+ projectId: z.string().optional().describe("Project ID to add task to"),
69
+ projectName: z.string().optional().describe("Project name to add task to"),
70
+ tags: z.array(z.string()).optional().describe("Tag names to apply (created if they don't exist)"),
71
+ repetitionRule: repetitionRuleSchema,
72
+ }, async (args) => {
73
+ try {
74
+ const task = await client.createTask(args);
75
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
76
+ }
77
+ catch (error) {
78
+ const { message } = formatMcpError(error);
79
+ return { content: [{ type: "text", text: message }], isError: true };
80
+ }
81
+ });
82
+ server.tool("update_task", "Update properties of an existing task", {
83
+ id: z.string().describe("The task ID to update"),
84
+ name: z.string().optional().describe("New task name"),
85
+ note: z.string().optional().describe("New task note"),
86
+ flagged: z.boolean().optional().describe("New flagged status"),
87
+ deferDate: z.string().nullable().optional().describe("New defer date (ISO 8601) or null to clear"),
88
+ dueDate: z.string().nullable().optional().describe("New due date (ISO 8601) or null to clear"),
89
+ estimatedMinutes: z.number().min(0).nullable().optional().describe("New estimated minutes or null to clear"),
90
+ sequential: z.boolean().optional().describe("Whether subtasks must be completed in order"),
91
+ completedByChildren: z.boolean().optional().describe("Auto-complete when all children are completed"),
92
+ repetitionRule: z.object({
93
+ ruleString: z.string().describe("ICS RRULE string"),
94
+ method: z.enum(["fixed", "startAfterCompletion", "dueAfterCompletion"]).describe("Repetition method"),
95
+ }).nullable().optional().describe("Repetition rule or null to clear"),
96
+ }, async (args) => {
97
+ try {
98
+ const task = await client.updateTask(args);
99
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
100
+ }
101
+ catch (error) {
102
+ const { message } = formatMcpError(error);
103
+ return { content: [{ type: "text", text: message }], isError: true };
104
+ }
105
+ });
106
+ server.tool("complete_task", "Mark a task as completed", {
107
+ id: z.string().describe("The task ID to complete"),
108
+ }, async ({ id }) => {
109
+ try {
110
+ const task = await client.completeTask(id);
111
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
112
+ }
113
+ catch (error) {
114
+ const { message } = formatMcpError(error);
115
+ return { content: [{ type: "text", text: message }], isError: true };
116
+ }
117
+ });
118
+ server.tool("uncomplete_task", "Mark a completed task as incomplete (re-open it)", {
119
+ id: z.string().describe("The task ID to uncomplete"),
120
+ }, async ({ id }) => {
121
+ try {
122
+ const task = await client.uncompleteTask(id);
123
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
124
+ }
125
+ catch (error) {
126
+ const { message } = formatMcpError(error);
127
+ return { content: [{ type: "text", text: message }], isError: true };
128
+ }
129
+ });
130
+ server.tool("drop_task", "Mark a task as dropped (cancelled)", {
131
+ id: z.string().describe("The task ID to drop"),
132
+ }, async ({ id }) => {
133
+ try {
134
+ const task = await client.dropTask(id);
135
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
136
+ }
137
+ catch (error) {
138
+ const { message } = formatMcpError(error);
139
+ return { content: [{ type: "text", text: message }], isError: true };
140
+ }
141
+ });
142
+ server.tool("delete_task", "Permanently delete a task from OmniFocus", {
143
+ id: z.string().describe("The task ID to delete"),
144
+ }, async ({ id }) => {
145
+ try {
146
+ const result = await client.deleteTask(id);
147
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
148
+ }
149
+ catch (error) {
150
+ const { message } = formatMcpError(error);
151
+ return { content: [{ type: "text", text: message }], isError: true };
152
+ }
153
+ });
154
+ server.tool("move_tasks", "Move one or more tasks to a different project or parent task. Omit destination to move to inbox.", {
155
+ taskIds: z.array(z.string()).describe("Task IDs to move"),
156
+ projectId: z.string().optional().describe("Destination project ID"),
157
+ projectName: z.string().optional().describe("Destination project name"),
158
+ parentTaskId: z.string().optional().describe("Destination parent task ID (for subtasks)"),
159
+ }, async (args) => {
160
+ try {
161
+ const tasks = await client.moveTasks(args);
162
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
163
+ }
164
+ catch (error) {
165
+ const { message } = formatMcpError(error);
166
+ return { content: [{ type: "text", text: message }], isError: true };
167
+ }
168
+ });
169
+ server.tool("duplicate_tasks", "Duplicate one or more tasks, optionally into a different project", {
170
+ taskIds: z.array(z.string()).describe("Task IDs to duplicate"),
171
+ projectId: z.string().optional().describe("Destination project ID"),
172
+ projectName: z.string().optional().describe("Destination project name"),
173
+ }, async (args) => {
174
+ try {
175
+ const tasks = await client.duplicateTasks(args);
176
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
177
+ }
178
+ catch (error) {
179
+ const { message } = formatMcpError(error);
180
+ return { content: [{ type: "text", text: message }], isError: true };
181
+ }
182
+ });
183
+ server.tool("set_task_tags", "Set, add, or remove tags on a task", {
184
+ taskId: z.string().describe("The task ID"),
185
+ tagNames: z.array(z.string()).describe("Tag names to set/add/remove"),
186
+ mode: z.enum(["replace", "add", "remove"]).describe("How to modify tags: replace all, add to existing, or remove specific tags"),
187
+ }, async (args) => {
188
+ try {
189
+ const task = await client.setTaskTags(args);
190
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
191
+ }
192
+ catch (error) {
193
+ const { message } = formatMcpError(error);
194
+ return { content: [{ type: "text", text: message }], isError: true };
195
+ }
196
+ });
197
+ server.tool("add_task_notification", "Add a notification/reminder to a task", {
198
+ taskId: z.string().describe("The task ID"),
199
+ type: z.enum(["absolute", "dueRelative", "deferRelative"]).describe("Notification type"),
200
+ absoluteDate: z.string().optional().describe("For 'absolute' type: ISO 8601 date for notification"),
201
+ relativeOffset: z.number().optional().describe("For relative types: offset in seconds (negative = before)"),
202
+ }, async (args) => {
203
+ try {
204
+ const task = await client.addTaskNotification(args);
205
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
206
+ }
207
+ catch (error) {
208
+ const { message } = formatMcpError(error);
209
+ return { content: [{ type: "text", text: message }], isError: true };
210
+ }
211
+ });
212
+ server.tool("get_inbox_tasks", "Get all tasks currently in the OmniFocus inbox (not yet assigned to a project)", {}, async () => {
213
+ try {
214
+ const tasks = await client.listTasks({ inInbox: true, taskStatus: "available" });
215
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
216
+ }
217
+ catch (error) {
218
+ const { message } = formatMcpError(error);
219
+ return { content: [{ type: "text", text: message }], isError: true };
220
+ }
221
+ });
222
+ server.tool("get_flagged_tasks", "Get all available flagged tasks", {}, async () => {
223
+ try {
224
+ const tasks = await client.listTasks({ flagged: true, taskStatus: "available" });
225
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
226
+ }
227
+ catch (error) {
228
+ const { message } = formatMcpError(error);
229
+ return { content: [{ type: "text", text: message }], isError: true };
230
+ }
231
+ });
232
+ server.tool("get_today_completed_tasks", "Get all tasks completed today", {}, async () => {
233
+ try {
234
+ const tasks = await client.getTodayCompletedTasks();
235
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
236
+ }
237
+ catch (error) {
238
+ const { message } = formatMcpError(error);
239
+ return { content: [{ type: "text", text: message }], isError: true };
240
+ }
241
+ });
242
+ server.tool("append_task_note", "Append text to an existing task's note", {
243
+ taskId: z.string().describe("The task ID"),
244
+ text: z.string().describe("Text to append to the note"),
245
+ }, async ({ taskId, text }) => {
246
+ try {
247
+ const task = await client.appendTaskNote(taskId, text);
248
+ return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
249
+ }
250
+ catch (error) {
251
+ const { message } = formatMcpError(error);
252
+ return { content: [{ type: "text", text: message }], isError: true };
253
+ }
254
+ });
255
+ server.tool("batch_create_tasks", "Create multiple tasks at once, with support for subtask hierarchies. Much more efficient than creating tasks one by one.", {
256
+ tasks: z.array(batchTaskItemSchema).min(1).describe("Array of tasks to create (can include nested children)"),
257
+ projectId: z.string().optional().describe("Project ID to add tasks to"),
258
+ projectName: z.string().optional().describe("Project name to add tasks to"),
259
+ parentTaskId: z.string().optional().describe("Parent task ID for subtasks"),
260
+ }, async (args) => {
261
+ try {
262
+ const tasks = await client.batchCreateTasks(args);
263
+ return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
264
+ }
265
+ catch (error) {
266
+ const { message } = formatMcpError(error);
267
+ return { content: [{ type: "text", text: message }], isError: true };
268
+ }
269
+ });
270
+ server.tool("list_task_notifications", "List all notifications/reminders on a task", {
271
+ taskId: z.string().describe("The task ID"),
272
+ }, async ({ taskId }) => {
273
+ try {
274
+ const notifications = await client.listTaskNotifications(taskId);
275
+ return { content: [{ type: "text", text: JSON.stringify(notifications, null, 2) }] };
276
+ }
277
+ catch (error) {
278
+ const { message } = formatMcpError(error);
279
+ return { content: [{ type: "text", text: message }], isError: true };
280
+ }
281
+ });
282
+ server.tool("remove_task_notification", "Remove a specific notification from a task", {
283
+ taskId: z.string().describe("The task ID"),
284
+ notificationId: z.string().describe("The notification ID to remove"),
285
+ }, async ({ taskId, notificationId }) => {
286
+ try {
287
+ const result = await client.removeTaskNotification(taskId, notificationId);
288
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
289
+ }
290
+ catch (error) {
291
+ const { message } = formatMcpError(error);
292
+ return { content: [{ type: "text", text: message }], isError: true };
293
+ }
294
+ });
295
+ server.tool("convert_task_to_project", "Convert an existing task into a new project, preserving subtasks", {
296
+ taskId: z.string().describe("The task ID to convert"),
297
+ }, async ({ taskId }) => {
298
+ try {
299
+ const project = await client.convertTaskToProject(taskId);
300
+ return { content: [{ type: "text", text: JSON.stringify(project, null, 2) }] };
301
+ }
302
+ catch (error) {
303
+ const { message } = formatMcpError(error);
304
+ return { content: [{ type: "text", text: message }], isError: true };
305
+ }
306
+ });
307
+ server.tool("batch_delete_tasks", "Delete multiple tasks at once. More efficient than deleting one by one.", {
308
+ taskIds: z.array(z.string()).min(1).describe("Array of task IDs to delete"),
309
+ }, async (args) => {
310
+ try {
311
+ const results = await client.batchDeleteTasks(args);
312
+ return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
313
+ }
314
+ catch (error) {
315
+ const { message } = formatMcpError(error);
316
+ return { content: [{ type: "text", text: message }], isError: true };
317
+ }
318
+ });
319
+ server.tool("batch_complete_tasks", "Complete multiple tasks at once. More efficient than completing one by one.", {
320
+ taskIds: z.array(z.string()).min(1).describe("Array of task IDs to complete"),
321
+ }, async (args) => {
322
+ try {
323
+ const results = await client.batchCompleteTasks(args);
324
+ return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
325
+ }
326
+ catch (error) {
327
+ const { message } = formatMcpError(error);
328
+ return { content: [{ type: "text", text: message }], isError: true };
329
+ }
330
+ });
331
+ server.tool("get_task_count", "Get count of tasks matching filters without fetching full data. Faster than list_tasks when you only need the count.", {
332
+ completed: z.boolean().optional().describe("Filter by completion status"),
333
+ flagged: z.boolean().optional().describe("Filter by flagged status"),
334
+ available: z.boolean().optional().describe("Only count available (actionable) tasks"),
335
+ inInbox: z.boolean().optional().describe("Only count inbox tasks"),
336
+ projectId: z.string().optional().describe("Filter by project ID"),
337
+ projectName: z.string().optional().describe("Filter by project name"),
338
+ tagNames: z.array(z.string()).optional().describe("Filter by tag names (all must match)"),
339
+ dueAfter: z.string().optional().describe("Filter tasks due after this ISO date"),
340
+ dueBefore: z.string().optional().describe("Filter tasks due before this ISO date"),
341
+ deferAfter: z.string().optional().describe("Filter tasks deferred after this ISO date"),
342
+ deferBefore: z.string().optional().describe("Filter tasks deferred before this ISO date"),
343
+ search: z.string().optional().describe("Full-text search in task name and note"),
344
+ taskStatus: z.enum(["available", "remaining", "completed", "dropped"]).optional().describe("Filter by task status"),
345
+ }, async (args) => {
346
+ try {
347
+ const result = await client.getTaskCount(args);
348
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
349
+ }
350
+ catch (error) {
351
+ const { message } = formatMcpError(error);
352
+ return { content: [{ type: "text", text: message }], isError: true };
353
+ }
354
+ });
355
+ }
356
+ //# sourceMappingURL=tasks.js.map