@stephendolan/omnifocus-cli 2.1.0 → 2.3.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.
- package/README.md +88 -431
- package/dist/cli.js +318 -54
- package/dist/cli.js.map +1 -1
- package/package.json +4 -2
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command9 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/lib/output.ts
|
|
7
7
|
var globalOutputOptions = {};
|
|
@@ -369,7 +369,7 @@ var OmniFocus = class {
|
|
|
369
369
|
updates.push(`task.flagged = ${options.flagged};`);
|
|
370
370
|
}
|
|
371
371
|
if (options.completed !== void 0) {
|
|
372
|
-
updates.push(
|
|
372
|
+
updates.push(options.completed ? "task.markComplete();" : "task.markIncomplete();");
|
|
373
373
|
}
|
|
374
374
|
if (options.estimatedMinutes !== void 0) {
|
|
375
375
|
updates.push(`task.estimatedMinutes = ${options.estimatedMinutes};`);
|
|
@@ -997,21 +997,21 @@ function createTaskCommand() {
|
|
|
997
997
|
command.description("Manage OmniFocus tasks");
|
|
998
998
|
command.command("list").alias("ls").description("List tasks").option("-f, --flagged", "Show only flagged tasks").option("-p, --project <name>", "Filter by project").option("-t, --tag <name>", "Filter by tag").option("-c, --completed", "Include completed tasks").action(
|
|
999
999
|
withErrorHandling(async (options) => {
|
|
1000
|
-
const
|
|
1000
|
+
const of2 = new OmniFocus();
|
|
1001
1001
|
const filters = {
|
|
1002
1002
|
includeCompleted: options.completed,
|
|
1003
1003
|
...options.flagged && { flagged: true },
|
|
1004
1004
|
...options.project && { project: options.project },
|
|
1005
1005
|
...options.tag && { tag: options.tag }
|
|
1006
1006
|
};
|
|
1007
|
-
const tasks = await
|
|
1007
|
+
const tasks = await of2.listTasks(filters);
|
|
1008
1008
|
outputJson(tasks);
|
|
1009
1009
|
})
|
|
1010
1010
|
);
|
|
1011
1011
|
command.command("create <name>").description("Create a new task").option("-p, --project <name>", "Assign to project").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
|
|
1012
1012
|
withErrorHandling(async (name, options) => {
|
|
1013
|
-
const
|
|
1014
|
-
const task = await
|
|
1013
|
+
const of2 = new OmniFocus();
|
|
1014
|
+
const task = await of2.createTask({
|
|
1015
1015
|
name,
|
|
1016
1016
|
note: options.note,
|
|
1017
1017
|
project: options.project,
|
|
@@ -1026,7 +1026,7 @@ function createTaskCommand() {
|
|
|
1026
1026
|
);
|
|
1027
1027
|
command.command("update <idOrName>").description("Update an existing task").option("-n, --name <name>", "New name").option("--note <text>", "New note").option("-p, --project <name>", "Move to project").option("-t, --tag <tags...>", "Replace tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flag", "Flag the task").option("-F, --unflag", "Unflag the task").option("-c, --complete", "Mark as completed").option("-C, --incomplete", "Mark as incomplete").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
|
|
1028
1028
|
withErrorHandling(async (idOrName, options) => {
|
|
1029
|
-
const
|
|
1029
|
+
const of2 = new OmniFocus();
|
|
1030
1030
|
const updates = {
|
|
1031
1031
|
...options.name && { name: options.name },
|
|
1032
1032
|
...options.note !== void 0 && { note: options.note },
|
|
@@ -1044,28 +1044,28 @@ function createTaskCommand() {
|
|
|
1044
1044
|
...options.incomplete && { completed: false },
|
|
1045
1045
|
...options.estimate !== void 0 && { estimatedMinutes: options.estimate }
|
|
1046
1046
|
};
|
|
1047
|
-
const task = await
|
|
1047
|
+
const task = await of2.updateTask(idOrName, updates);
|
|
1048
1048
|
outputJson(task);
|
|
1049
1049
|
})
|
|
1050
1050
|
);
|
|
1051
1051
|
command.command("delete <idOrName>").alias("rm").description("Delete a task").action(
|
|
1052
1052
|
withErrorHandling(async (idOrName) => {
|
|
1053
|
-
const
|
|
1054
|
-
await
|
|
1053
|
+
const of2 = new OmniFocus();
|
|
1054
|
+
await of2.deleteTask(idOrName);
|
|
1055
1055
|
outputJson({ message: "Task deleted successfully" });
|
|
1056
1056
|
})
|
|
1057
1057
|
);
|
|
1058
1058
|
command.command("view <idOrName>").description("View task details").action(
|
|
1059
1059
|
withErrorHandling(async (idOrName) => {
|
|
1060
|
-
const
|
|
1061
|
-
const task = await
|
|
1060
|
+
const of2 = new OmniFocus();
|
|
1061
|
+
const task = await of2.getTask(idOrName);
|
|
1062
1062
|
outputJson(task);
|
|
1063
1063
|
})
|
|
1064
1064
|
);
|
|
1065
1065
|
command.command("stats").description("Show task statistics").action(
|
|
1066
1066
|
withErrorHandling(async () => {
|
|
1067
|
-
const
|
|
1068
|
-
const stats = await
|
|
1067
|
+
const of2 = new OmniFocus();
|
|
1068
|
+
const stats = await of2.getTaskStats();
|
|
1069
1069
|
outputJson(stats);
|
|
1070
1070
|
})
|
|
1071
1071
|
);
|
|
@@ -1079,20 +1079,20 @@ function createProjectCommand() {
|
|
|
1079
1079
|
command.description("Manage OmniFocus projects");
|
|
1080
1080
|
command.command("list").alias("ls").description("List projects").option("-f, --folder <name>", "Filter by folder").option("-s, --status <status>", "Filter by status (active, on hold, dropped)").option("-d, --dropped", "Include dropped projects").action(
|
|
1081
1081
|
withErrorHandling(async (options) => {
|
|
1082
|
-
const
|
|
1082
|
+
const of2 = new OmniFocus();
|
|
1083
1083
|
const filters = {
|
|
1084
1084
|
includeDropped: options.dropped,
|
|
1085
1085
|
...options.folder && { folder: options.folder },
|
|
1086
1086
|
...options.status && { status: options.status }
|
|
1087
1087
|
};
|
|
1088
|
-
const projects = await
|
|
1088
|
+
const projects = await of2.listProjects(filters);
|
|
1089
1089
|
outputJson(projects);
|
|
1090
1090
|
})
|
|
1091
1091
|
);
|
|
1092
1092
|
command.command("create <name>").description("Create a new project").option("-f, --folder <name>", "Assign to folder").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-s, --sequential", "Make it a sequential project").option("--status <status>", "Set status (active, on hold, dropped)").action(
|
|
1093
1093
|
withErrorHandling(async (name, options) => {
|
|
1094
|
-
const
|
|
1095
|
-
const project = await
|
|
1094
|
+
const of2 = new OmniFocus();
|
|
1095
|
+
const project = await of2.createProject({
|
|
1096
1096
|
name,
|
|
1097
1097
|
note: options.note,
|
|
1098
1098
|
folder: options.folder,
|
|
@@ -1105,7 +1105,7 @@ function createProjectCommand() {
|
|
|
1105
1105
|
);
|
|
1106
1106
|
command.command("update <idOrName>").description("Update an existing project").option("-n, --name <name>", "Rename project").option("--note <text>", "New note").option("-f, --folder <name>", "Move to folder").option("-t, --tag <tags...>", "Replace tags").option("-s, --sequential", "Make it sequential").option("-p, --parallel", "Make it parallel").option("--status <status>", "Set status (active, on hold, dropped)").action(
|
|
1107
1107
|
withErrorHandling(async (idOrName, options) => {
|
|
1108
|
-
const
|
|
1108
|
+
const of2 = new OmniFocus();
|
|
1109
1109
|
const updates = {
|
|
1110
1110
|
...options.name && { name: options.name },
|
|
1111
1111
|
...options.note !== void 0 && { note: options.note },
|
|
@@ -1115,28 +1115,28 @@ function createProjectCommand() {
|
|
|
1115
1115
|
...options.parallel && { sequential: false },
|
|
1116
1116
|
...options.status && { status: options.status }
|
|
1117
1117
|
};
|
|
1118
|
-
const project = await
|
|
1118
|
+
const project = await of2.updateProject(idOrName, updates);
|
|
1119
1119
|
outputJson(project);
|
|
1120
1120
|
})
|
|
1121
1121
|
);
|
|
1122
1122
|
command.command("delete <idOrName>").alias("rm").description("Delete a project").action(
|
|
1123
1123
|
withErrorHandling(async (idOrName) => {
|
|
1124
|
-
const
|
|
1125
|
-
await
|
|
1124
|
+
const of2 = new OmniFocus();
|
|
1125
|
+
await of2.deleteProject(idOrName);
|
|
1126
1126
|
outputJson({ message: "Project deleted successfully" });
|
|
1127
1127
|
})
|
|
1128
1128
|
);
|
|
1129
1129
|
command.command("view <idOrName>").description("View project details").action(
|
|
1130
1130
|
withErrorHandling(async (idOrName) => {
|
|
1131
|
-
const
|
|
1132
|
-
const project = await
|
|
1131
|
+
const of2 = new OmniFocus();
|
|
1132
|
+
const project = await of2.getProject(idOrName);
|
|
1133
1133
|
outputJson(project);
|
|
1134
1134
|
})
|
|
1135
1135
|
);
|
|
1136
1136
|
command.command("stats").description("Show project statistics").action(
|
|
1137
1137
|
withErrorHandling(async () => {
|
|
1138
|
-
const
|
|
1139
|
-
const stats = await
|
|
1138
|
+
const of2 = new OmniFocus();
|
|
1139
|
+
const stats = await of2.getProjectStats();
|
|
1140
1140
|
outputJson(stats);
|
|
1141
1141
|
})
|
|
1142
1142
|
);
|
|
@@ -1150,18 +1150,33 @@ function createInboxCommand() {
|
|
|
1150
1150
|
command.description("Manage OmniFocus inbox");
|
|
1151
1151
|
command.command("list").alias("ls").description("List inbox tasks").action(
|
|
1152
1152
|
withErrorHandling(async () => {
|
|
1153
|
-
const
|
|
1154
|
-
const tasks = await
|
|
1153
|
+
const of2 = new OmniFocus();
|
|
1154
|
+
const tasks = await of2.listInboxTasks();
|
|
1155
1155
|
outputJson(tasks);
|
|
1156
1156
|
})
|
|
1157
1157
|
);
|
|
1158
1158
|
command.command("count").description("Get inbox count").action(
|
|
1159
1159
|
withErrorHandling(async () => {
|
|
1160
|
-
const
|
|
1161
|
-
const count = await
|
|
1160
|
+
const of2 = new OmniFocus();
|
|
1161
|
+
const count = await of2.getInboxCount();
|
|
1162
1162
|
outputJson({ count });
|
|
1163
1163
|
})
|
|
1164
1164
|
);
|
|
1165
|
+
command.command("add <name>").description("Add a task to inbox").option("--note <text>", "Add note").option("-t, --tag <tags...>", "Add tags").option("-d, --due <date>", "Set due date").option("-D, --defer <date>", "Set defer date").option("-f, --flagged", "Flag the task").option("-e, --estimate <minutes>", "Estimated time in minutes", parseInt).action(
|
|
1166
|
+
withErrorHandling(async (name, options) => {
|
|
1167
|
+
const of2 = new OmniFocus();
|
|
1168
|
+
const task = await of2.createTask({
|
|
1169
|
+
name,
|
|
1170
|
+
note: options.note,
|
|
1171
|
+
tags: options.tag,
|
|
1172
|
+
due: options.due ? parseDateTime(options.due) : void 0,
|
|
1173
|
+
defer: options.defer ? parseDateTime(options.defer) : void 0,
|
|
1174
|
+
flagged: options.flagged,
|
|
1175
|
+
estimatedMinutes: options.estimate
|
|
1176
|
+
});
|
|
1177
|
+
outputJson(task);
|
|
1178
|
+
})
|
|
1179
|
+
);
|
|
1165
1180
|
return command;
|
|
1166
1181
|
}
|
|
1167
1182
|
|
|
@@ -1173,8 +1188,8 @@ function createSearchCommand() {
|
|
|
1173
1188
|
command.argument("<query>", "Search query");
|
|
1174
1189
|
command.action(
|
|
1175
1190
|
withErrorHandling(async (query) => {
|
|
1176
|
-
const
|
|
1177
|
-
const tasks = await
|
|
1191
|
+
const of2 = new OmniFocus();
|
|
1192
|
+
const tasks = await of2.searchTasks(query);
|
|
1178
1193
|
outputJson(tasks);
|
|
1179
1194
|
})
|
|
1180
1195
|
);
|
|
@@ -1188,15 +1203,15 @@ function createPerspectiveCommand() {
|
|
|
1188
1203
|
command.description("Manage OmniFocus perspectives");
|
|
1189
1204
|
command.command("list").alias("ls").description("List all perspectives").action(
|
|
1190
1205
|
withErrorHandling(async () => {
|
|
1191
|
-
const
|
|
1192
|
-
const perspectives = await
|
|
1206
|
+
const of2 = new OmniFocus();
|
|
1207
|
+
const perspectives = await of2.listPerspectives();
|
|
1193
1208
|
outputJson(perspectives);
|
|
1194
1209
|
})
|
|
1195
1210
|
);
|
|
1196
1211
|
command.command("view <name>").description("View tasks in a perspective").action(
|
|
1197
1212
|
withErrorHandling(async (name) => {
|
|
1198
|
-
const
|
|
1199
|
-
const tasks = await
|
|
1213
|
+
const of2 = new OmniFocus();
|
|
1214
|
+
const tasks = await of2.getPerspectiveTasks(name);
|
|
1200
1215
|
outputJson(tasks);
|
|
1201
1216
|
})
|
|
1202
1217
|
);
|
|
@@ -1210,8 +1225,8 @@ function createTagCommand() {
|
|
|
1210
1225
|
command.description("Manage and analyze OmniFocus tags");
|
|
1211
1226
|
command.command("list").alias("ls").description("List tags with usage information").option("-u, --unused-days <days>", "Show tags unused for N days", parseInt).option("-s, --sort <field>", "Sort by: name, usage, activity (default: name)", "name").option("-a, --active-only", "Only count active (incomplete) tasks").action(
|
|
1212
1227
|
withErrorHandling(async (options) => {
|
|
1213
|
-
const
|
|
1214
|
-
const tags = await
|
|
1228
|
+
const of2 = new OmniFocus();
|
|
1229
|
+
const tags = await of2.listTags({
|
|
1215
1230
|
unusedDays: options.unusedDays,
|
|
1216
1231
|
sortBy: options.sort,
|
|
1217
1232
|
activeOnly: options.activeOnly
|
|
@@ -1221,8 +1236,8 @@ function createTagCommand() {
|
|
|
1221
1236
|
);
|
|
1222
1237
|
command.command("create <name>").description("Create a new tag").option("-p, --parent <name>", "Create as child of parent tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(
|
|
1223
1238
|
withErrorHandling(async (name, options) => {
|
|
1224
|
-
const
|
|
1225
|
-
const tag = await
|
|
1239
|
+
const of2 = new OmniFocus();
|
|
1240
|
+
const tag = await of2.createTag({
|
|
1226
1241
|
name,
|
|
1227
1242
|
parent: options.parent,
|
|
1228
1243
|
status: options.status
|
|
@@ -1232,33 +1247,33 @@ function createTagCommand() {
|
|
|
1232
1247
|
);
|
|
1233
1248
|
command.command("view <idOrName>").description("View tag details").action(
|
|
1234
1249
|
withErrorHandling(async (idOrName) => {
|
|
1235
|
-
const
|
|
1236
|
-
const tag = await
|
|
1250
|
+
const of2 = new OmniFocus();
|
|
1251
|
+
const tag = await of2.getTag(idOrName);
|
|
1237
1252
|
outputJson(tag);
|
|
1238
1253
|
})
|
|
1239
1254
|
);
|
|
1240
1255
|
command.command("update <idOrName>").description("Update an existing tag").option("-n, --name <name>", "Rename tag").option("-s, --status <status>", "Set status (active, on hold, dropped)").action(
|
|
1241
1256
|
withErrorHandling(async (idOrName, options) => {
|
|
1242
|
-
const
|
|
1257
|
+
const of2 = new OmniFocus();
|
|
1243
1258
|
const updates = {
|
|
1244
1259
|
...options.name && { name: options.name },
|
|
1245
1260
|
...options.status && { status: options.status }
|
|
1246
1261
|
};
|
|
1247
|
-
const tag = await
|
|
1262
|
+
const tag = await of2.updateTag(idOrName, updates);
|
|
1248
1263
|
outputJson(tag);
|
|
1249
1264
|
})
|
|
1250
1265
|
);
|
|
1251
1266
|
command.command("delete <idOrName>").alias("rm").description("Delete a tag").action(
|
|
1252
1267
|
withErrorHandling(async (idOrName) => {
|
|
1253
|
-
const
|
|
1254
|
-
await
|
|
1268
|
+
const of2 = new OmniFocus();
|
|
1269
|
+
await of2.deleteTag(idOrName);
|
|
1255
1270
|
outputJson({ message: "Tag deleted successfully" });
|
|
1256
1271
|
})
|
|
1257
1272
|
);
|
|
1258
1273
|
command.command("stats").description("Show tag usage statistics").action(
|
|
1259
1274
|
withErrorHandling(async () => {
|
|
1260
|
-
const
|
|
1261
|
-
const stats = await
|
|
1275
|
+
const of2 = new OmniFocus();
|
|
1276
|
+
const stats = await of2.getTagStats();
|
|
1262
1277
|
outputJson(stats);
|
|
1263
1278
|
})
|
|
1264
1279
|
);
|
|
@@ -1272,25 +1287,273 @@ function createFolderCommand() {
|
|
|
1272
1287
|
command.description("View OmniFocus folder hierarchy");
|
|
1273
1288
|
command.command("list").alias("ls").description("List top-level folders with nested children").option("-d, --dropped", "Include dropped folders").action(
|
|
1274
1289
|
withErrorHandling(async (options) => {
|
|
1275
|
-
const
|
|
1276
|
-
const folders = await
|
|
1290
|
+
const of2 = new OmniFocus();
|
|
1291
|
+
const folders = await of2.listFolders({ includeDropped: options.dropped });
|
|
1277
1292
|
outputJson(folders);
|
|
1278
1293
|
})
|
|
1279
1294
|
);
|
|
1280
1295
|
command.command("view <idOrName>").description("View folder details and children").option("-d, --dropped", "Include dropped child folders").action(
|
|
1281
1296
|
withErrorHandling(async (idOrName, options) => {
|
|
1282
|
-
const
|
|
1297
|
+
const of2 = new OmniFocus();
|
|
1283
1298
|
const filters = { includeDropped: options.dropped };
|
|
1284
|
-
const folder = await
|
|
1299
|
+
const folder = await of2.getFolder(idOrName, filters);
|
|
1285
1300
|
outputJson(folder);
|
|
1286
1301
|
})
|
|
1287
1302
|
);
|
|
1288
1303
|
return command;
|
|
1289
1304
|
}
|
|
1290
1305
|
|
|
1306
|
+
// src/commands/mcp.ts
|
|
1307
|
+
import { Command as Command8 } from "commander";
|
|
1308
|
+
|
|
1309
|
+
// src/mcp/server.ts
|
|
1310
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
1311
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1312
|
+
import { z } from "zod";
|
|
1313
|
+
var server = new McpServer({
|
|
1314
|
+
name: "omnifocus",
|
|
1315
|
+
version: "1.0.0"
|
|
1316
|
+
});
|
|
1317
|
+
var of = new OmniFocus();
|
|
1318
|
+
function jsonResponse(data) {
|
|
1319
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
1320
|
+
}
|
|
1321
|
+
server.tool(
|
|
1322
|
+
"list_tasks",
|
|
1323
|
+
"List tasks with optional filtering",
|
|
1324
|
+
{
|
|
1325
|
+
includeCompleted: z.boolean().optional().describe("Include completed tasks"),
|
|
1326
|
+
includeDropped: z.boolean().optional().describe("Include dropped tasks"),
|
|
1327
|
+
flagged: z.boolean().optional().describe("Only show flagged tasks"),
|
|
1328
|
+
project: z.string().optional().describe("Filter by project name"),
|
|
1329
|
+
tag: z.string().optional().describe("Filter by tag name")
|
|
1330
|
+
},
|
|
1331
|
+
async (filters) => jsonResponse(await of.listTasks(filters))
|
|
1332
|
+
);
|
|
1333
|
+
server.tool(
|
|
1334
|
+
"get_task",
|
|
1335
|
+
"Get a specific task by ID or name",
|
|
1336
|
+
{ idOrName: z.string().describe("Task ID or name") },
|
|
1337
|
+
async ({ idOrName }) => jsonResponse(await of.getTask(idOrName))
|
|
1338
|
+
);
|
|
1339
|
+
server.tool(
|
|
1340
|
+
"create_task",
|
|
1341
|
+
"Create a new task",
|
|
1342
|
+
{
|
|
1343
|
+
name: z.string().describe("Task name"),
|
|
1344
|
+
note: z.string().optional().describe("Task note"),
|
|
1345
|
+
project: z.string().optional().describe("Project to add task to"),
|
|
1346
|
+
tags: z.array(z.string()).optional().describe("Tags to assign"),
|
|
1347
|
+
defer: z.string().optional().describe("Defer date (ISO 8601)"),
|
|
1348
|
+
due: z.string().optional().describe("Due date (ISO 8601)"),
|
|
1349
|
+
flagged: z.boolean().optional().describe("Flag the task"),
|
|
1350
|
+
estimatedMinutes: z.number().optional().describe("Estimated duration in minutes")
|
|
1351
|
+
},
|
|
1352
|
+
async (options) => jsonResponse(await of.createTask(options))
|
|
1353
|
+
);
|
|
1354
|
+
server.tool(
|
|
1355
|
+
"update_task",
|
|
1356
|
+
"Update an existing task",
|
|
1357
|
+
{
|
|
1358
|
+
idOrName: z.string().describe("Task ID or name"),
|
|
1359
|
+
name: z.string().optional().describe("New task name"),
|
|
1360
|
+
note: z.string().optional().describe("New task note"),
|
|
1361
|
+
project: z.string().optional().describe("Move to project"),
|
|
1362
|
+
tags: z.array(z.string()).optional().describe("Replace tags"),
|
|
1363
|
+
defer: z.string().optional().describe("New defer date (ISO 8601)"),
|
|
1364
|
+
due: z.string().optional().describe("New due date (ISO 8601)"),
|
|
1365
|
+
flagged: z.boolean().optional().describe("Flag/unflag the task"),
|
|
1366
|
+
estimatedMinutes: z.number().optional().describe("New estimated duration"),
|
|
1367
|
+
completed: z.boolean().optional().describe("Mark complete/incomplete")
|
|
1368
|
+
},
|
|
1369
|
+
async ({ idOrName, ...options }) => jsonResponse(await of.updateTask(idOrName, options))
|
|
1370
|
+
);
|
|
1371
|
+
server.tool(
|
|
1372
|
+
"delete_task",
|
|
1373
|
+
"Delete a task",
|
|
1374
|
+
{ idOrName: z.string().describe("Task ID or name") },
|
|
1375
|
+
async ({ idOrName }) => {
|
|
1376
|
+
await of.deleteTask(idOrName);
|
|
1377
|
+
return jsonResponse({ deleted: true });
|
|
1378
|
+
}
|
|
1379
|
+
);
|
|
1380
|
+
server.tool(
|
|
1381
|
+
"search_tasks",
|
|
1382
|
+
"Search tasks by name or note content",
|
|
1383
|
+
{ query: z.string().describe("Search query") },
|
|
1384
|
+
async ({ query }) => jsonResponse(await of.searchTasks(query))
|
|
1385
|
+
);
|
|
1386
|
+
server.tool(
|
|
1387
|
+
"get_task_stats",
|
|
1388
|
+
"Get task statistics",
|
|
1389
|
+
{},
|
|
1390
|
+
async () => jsonResponse(await of.getTaskStats())
|
|
1391
|
+
);
|
|
1392
|
+
server.tool(
|
|
1393
|
+
"list_inbox",
|
|
1394
|
+
"List all inbox tasks",
|
|
1395
|
+
{},
|
|
1396
|
+
async () => jsonResponse(await of.listInboxTasks())
|
|
1397
|
+
);
|
|
1398
|
+
server.tool(
|
|
1399
|
+
"get_inbox_count",
|
|
1400
|
+
"Get the number of inbox tasks",
|
|
1401
|
+
{},
|
|
1402
|
+
async () => jsonResponse({ count: await of.getInboxCount() })
|
|
1403
|
+
);
|
|
1404
|
+
server.tool(
|
|
1405
|
+
"list_projects",
|
|
1406
|
+
"List projects with optional filtering",
|
|
1407
|
+
{
|
|
1408
|
+
includeDropped: z.boolean().optional().describe("Include dropped projects"),
|
|
1409
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("Filter by status"),
|
|
1410
|
+
folder: z.string().optional().describe("Filter by folder name")
|
|
1411
|
+
},
|
|
1412
|
+
async (filters) => jsonResponse(await of.listProjects(filters))
|
|
1413
|
+
);
|
|
1414
|
+
server.tool(
|
|
1415
|
+
"get_project",
|
|
1416
|
+
"Get a specific project by ID or name",
|
|
1417
|
+
{ idOrName: z.string().describe("Project ID or name") },
|
|
1418
|
+
async ({ idOrName }) => jsonResponse(await of.getProject(idOrName))
|
|
1419
|
+
);
|
|
1420
|
+
server.tool(
|
|
1421
|
+
"create_project",
|
|
1422
|
+
"Create a new project",
|
|
1423
|
+
{
|
|
1424
|
+
name: z.string().describe("Project name"),
|
|
1425
|
+
note: z.string().optional().describe("Project note"),
|
|
1426
|
+
folder: z.string().optional().describe("Folder to create project in"),
|
|
1427
|
+
sequential: z.boolean().optional().describe("Sequential project (tasks must be done in order)"),
|
|
1428
|
+
tags: z.array(z.string()).optional().describe("Tags to assign"),
|
|
1429
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("Initial status")
|
|
1430
|
+
},
|
|
1431
|
+
async (options) => jsonResponse(await of.createProject(options))
|
|
1432
|
+
);
|
|
1433
|
+
server.tool(
|
|
1434
|
+
"update_project",
|
|
1435
|
+
"Update an existing project",
|
|
1436
|
+
{
|
|
1437
|
+
idOrName: z.string().describe("Project ID or name"),
|
|
1438
|
+
name: z.string().optional().describe("New project name"),
|
|
1439
|
+
note: z.string().optional().describe("New project note"),
|
|
1440
|
+
folder: z.string().optional().describe("Move to folder"),
|
|
1441
|
+
sequential: z.boolean().optional().describe("Set sequential/parallel"),
|
|
1442
|
+
tags: z.array(z.string()).optional().describe("Replace tags"),
|
|
1443
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("New status")
|
|
1444
|
+
},
|
|
1445
|
+
async ({ idOrName, ...options }) => jsonResponse(await of.updateProject(idOrName, options))
|
|
1446
|
+
);
|
|
1447
|
+
server.tool(
|
|
1448
|
+
"delete_project",
|
|
1449
|
+
"Delete a project",
|
|
1450
|
+
{ idOrName: z.string().describe("Project ID or name") },
|
|
1451
|
+
async ({ idOrName }) => {
|
|
1452
|
+
await of.deleteProject(idOrName);
|
|
1453
|
+
return jsonResponse({ deleted: true });
|
|
1454
|
+
}
|
|
1455
|
+
);
|
|
1456
|
+
server.tool(
|
|
1457
|
+
"get_project_stats",
|
|
1458
|
+
"Get project statistics",
|
|
1459
|
+
{},
|
|
1460
|
+
async () => jsonResponse(await of.getProjectStats())
|
|
1461
|
+
);
|
|
1462
|
+
server.tool(
|
|
1463
|
+
"list_perspectives",
|
|
1464
|
+
"List all available perspectives",
|
|
1465
|
+
{},
|
|
1466
|
+
async () => jsonResponse(await of.listPerspectives())
|
|
1467
|
+
);
|
|
1468
|
+
server.tool(
|
|
1469
|
+
"get_perspective_tasks",
|
|
1470
|
+
"Get tasks from a specific perspective",
|
|
1471
|
+
{ name: z.string().describe("Perspective name (e.g., Inbox, Flagged, or custom perspective)") },
|
|
1472
|
+
async ({ name }) => jsonResponse(await of.getPerspectiveTasks(name))
|
|
1473
|
+
);
|
|
1474
|
+
server.tool(
|
|
1475
|
+
"list_tags",
|
|
1476
|
+
"List all tags with optional filtering and sorting",
|
|
1477
|
+
{
|
|
1478
|
+
unusedDays: z.number().optional().describe("Only show tags unused for this many days"),
|
|
1479
|
+
sortBy: z.enum(["name", "usage", "activity"]).optional().describe("Sort order"),
|
|
1480
|
+
activeOnly: z.boolean().optional().describe("Only count active tasks")
|
|
1481
|
+
},
|
|
1482
|
+
async (options) => jsonResponse(await of.listTags(options))
|
|
1483
|
+
);
|
|
1484
|
+
server.tool(
|
|
1485
|
+
"get_tag",
|
|
1486
|
+
"Get a specific tag by ID or name",
|
|
1487
|
+
{ idOrName: z.string().describe('Tag ID, name, or path (e.g., "Parent/Child")') },
|
|
1488
|
+
async ({ idOrName }) => jsonResponse(await of.getTag(idOrName))
|
|
1489
|
+
);
|
|
1490
|
+
server.tool(
|
|
1491
|
+
"create_tag",
|
|
1492
|
+
"Create a new tag",
|
|
1493
|
+
{
|
|
1494
|
+
name: z.string().describe("Tag name"),
|
|
1495
|
+
parent: z.string().optional().describe("Parent tag name or path"),
|
|
1496
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("Initial status")
|
|
1497
|
+
},
|
|
1498
|
+
async (options) => jsonResponse(await of.createTag(options))
|
|
1499
|
+
);
|
|
1500
|
+
server.tool(
|
|
1501
|
+
"update_tag",
|
|
1502
|
+
"Update an existing tag",
|
|
1503
|
+
{
|
|
1504
|
+
idOrName: z.string().describe("Tag ID, name, or path"),
|
|
1505
|
+
name: z.string().optional().describe("New tag name"),
|
|
1506
|
+
status: z.enum(["active", "on hold", "dropped"]).optional().describe("New status")
|
|
1507
|
+
},
|
|
1508
|
+
async ({ idOrName, ...options }) => jsonResponse(await of.updateTag(idOrName, options))
|
|
1509
|
+
);
|
|
1510
|
+
server.tool(
|
|
1511
|
+
"delete_tag",
|
|
1512
|
+
"Delete a tag",
|
|
1513
|
+
{ idOrName: z.string().describe("Tag ID, name, or path") },
|
|
1514
|
+
async ({ idOrName }) => {
|
|
1515
|
+
await of.deleteTag(idOrName);
|
|
1516
|
+
return jsonResponse({ deleted: true });
|
|
1517
|
+
}
|
|
1518
|
+
);
|
|
1519
|
+
server.tool(
|
|
1520
|
+
"get_tag_stats",
|
|
1521
|
+
"Get tag statistics",
|
|
1522
|
+
{},
|
|
1523
|
+
async () => jsonResponse(await of.getTagStats())
|
|
1524
|
+
);
|
|
1525
|
+
server.tool(
|
|
1526
|
+
"list_folders",
|
|
1527
|
+
"List all folders",
|
|
1528
|
+
{ includeDropped: z.boolean().optional().describe("Include dropped folders") },
|
|
1529
|
+
async (filters) => jsonResponse(await of.listFolders(filters))
|
|
1530
|
+
);
|
|
1531
|
+
server.tool(
|
|
1532
|
+
"get_folder",
|
|
1533
|
+
"Get a specific folder by ID or name",
|
|
1534
|
+
{
|
|
1535
|
+
idOrName: z.string().describe("Folder ID or name"),
|
|
1536
|
+
includeDropped: z.boolean().optional().describe("Include dropped children")
|
|
1537
|
+
},
|
|
1538
|
+
async ({ idOrName, includeDropped }) => jsonResponse(await of.getFolder(idOrName, { includeDropped }))
|
|
1539
|
+
);
|
|
1540
|
+
async function runMcpServer() {
|
|
1541
|
+
const transport = new StdioServerTransport();
|
|
1542
|
+
await server.connect(transport);
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// src/commands/mcp.ts
|
|
1546
|
+
function createMcpCommand() {
|
|
1547
|
+
const cmd = new Command8("mcp").description("Run OmniFocus MCP server");
|
|
1548
|
+
cmd.action(async () => {
|
|
1549
|
+
await runMcpServer();
|
|
1550
|
+
});
|
|
1551
|
+
return cmd;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1291
1554
|
// src/cli.ts
|
|
1292
|
-
var program = new
|
|
1293
|
-
program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.
|
|
1555
|
+
var program = new Command9();
|
|
1556
|
+
program.name("of").description("A command-line interface for OmniFocus on macOS").version("2.3.0").option("-c, --compact", "Minified JSON output (single line)").hook("preAction", (thisCommand) => {
|
|
1294
1557
|
const options = thisCommand.opts();
|
|
1295
1558
|
setOutputOptions({
|
|
1296
1559
|
compact: options.compact
|
|
@@ -1303,6 +1566,7 @@ program.addCommand(createSearchCommand());
|
|
|
1303
1566
|
program.addCommand(createPerspectiveCommand());
|
|
1304
1567
|
program.addCommand(createTagCommand());
|
|
1305
1568
|
program.addCommand(createFolderCommand());
|
|
1569
|
+
program.addCommand(createMcpCommand());
|
|
1306
1570
|
program.parseAsync().catch(() => {
|
|
1307
1571
|
process.exit(1);
|
|
1308
1572
|
});
|