@vibetasks/mcp-server 0.1.0 → 0.2.2

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.
@@ -1,115 +0,0 @@
1
- import { TaskOperations } from '@vibetasks/core';
2
-
3
- export interface MCPResource {
4
- uri: string;
5
- name: string;
6
- description: string;
7
- mimeType: string;
8
- handler: (taskOps: TaskOperations) => Promise<any>;
9
- }
10
-
11
- export function setupResources(taskOps: TaskOperations): MCPResource[] {
12
- return [
13
- // Active tasks resource
14
- {
15
- uri: 'taskflow://tasks/active',
16
- name: 'Active Tasks',
17
- description: 'All incomplete tasks',
18
- mimeType: 'application/json',
19
- handler: async (taskOps) => {
20
- const tasks = await taskOps.getTasks('all');
21
-
22
- return {
23
- contents: [
24
- {
25
- uri: 'taskflow://tasks/active',
26
- mimeType: 'application/json',
27
- text: JSON.stringify(
28
- {
29
- tasks: tasks.map((t) => ({
30
- id: t.id,
31
- title: t.title,
32
- priority: t.priority,
33
- due_date: t.due_date,
34
- tags: t.tags?.map((tag) => tag.name) || [],
35
- })),
36
- count: tasks.length,
37
- },
38
- null,
39
- 2
40
- ),
41
- },
42
- ],
43
- };
44
- },
45
- },
46
-
47
- // Today's tasks resource
48
- {
49
- uri: 'taskflow://tasks/today',
50
- name: 'Today\'s Tasks',
51
- description: 'Tasks due today',
52
- mimeType: 'application/json',
53
- handler: async (taskOps) => {
54
- const tasks = await taskOps.getTasks('today');
55
-
56
- return {
57
- contents: [
58
- {
59
- uri: 'taskflow://tasks/today',
60
- mimeType: 'application/json',
61
- text: JSON.stringify(
62
- {
63
- tasks: tasks.map((t) => ({
64
- id: t.id,
65
- title: t.title,
66
- priority: t.priority,
67
- tags: t.tags?.map((tag) => tag.name) || [],
68
- })),
69
- count: tasks.length,
70
- date: new Date().toISOString().split('T')[0],
71
- },
72
- null,
73
- 2
74
- ),
75
- },
76
- ],
77
- };
78
- },
79
- },
80
-
81
- // Upcoming tasks resource
82
- {
83
- uri: 'taskflow://tasks/upcoming',
84
- name: 'Upcoming Tasks',
85
- description: 'Tasks due in the future',
86
- mimeType: 'application/json',
87
- handler: async (taskOps) => {
88
- const tasks = await taskOps.getTasks('upcoming');
89
-
90
- return {
91
- contents: [
92
- {
93
- uri: 'taskflow://tasks/upcoming',
94
- mimeType: 'application/json',
95
- text: JSON.stringify(
96
- {
97
- tasks: tasks.map((t) => ({
98
- id: t.id,
99
- title: t.title,
100
- priority: t.priority,
101
- due_date: t.due_date,
102
- tags: t.tags?.map((tag) => tag.name) || [],
103
- })),
104
- count: tasks.length,
105
- },
106
- null,
107
- 2
108
- ),
109
- },
110
- ],
111
- };
112
- },
113
- },
114
- ];
115
- }
@@ -1,414 +0,0 @@
1
- import { TaskOperations } from '@vibetasks/core';
2
- import { z } from 'zod';
3
-
4
- export interface MCPTool {
5
- name: string;
6
- description: string;
7
- inputSchema: z.ZodType<any>;
8
- handler: (args: any, taskOps: TaskOperations) => Promise<any>;
9
- }
10
-
11
- export function setupTools(taskOps: TaskOperations): MCPTool[] {
12
- return [
13
- // create_task
14
- {
15
- name: 'create_task',
16
- description: 'Create a new task in TaskFlow. Can optionally be a subtask by providing parent_task_id.',
17
- inputSchema: z.object({
18
- title: z.string().describe('Task title (required)'),
19
- notes: z.string().optional().describe('Task notes in markdown'),
20
- due_date: z
21
- .string()
22
- .optional()
23
- .describe('Due date (ISO 8601 format)'),
24
- priority: z
25
- .enum(['none', 'low', 'medium', 'high'])
26
- .default('none')
27
- .describe('Task priority'),
28
- tags: z
29
- .array(z.string())
30
- .optional()
31
- .describe('Tag names to attach'),
32
- parent_task_id: z
33
- .string()
34
- .optional()
35
- .describe('Parent task ID to create this as a subtask'),
36
- }),
37
- handler: async (args, taskOps) => {
38
- // Handle tags - get or create
39
- let tagIds: string[] = [];
40
- if (args.tags && args.tags.length > 0) {
41
- for (const tagName of args.tags) {
42
- const tag = await taskOps.findOrCreateTag(tagName);
43
- tagIds.push(tag.id);
44
- }
45
- }
46
-
47
- // Create task
48
- const task = await taskOps.createTask({
49
- title: args.title,
50
- notes: args.notes,
51
- notes_format: 'markdown',
52
- due_date: args.due_date,
53
- priority: args.priority,
54
- parent_task_id: args.parent_task_id,
55
- });
56
-
57
- // Link tags
58
- if (tagIds.length > 0) {
59
- await taskOps.linkTaskTags(task.id, tagIds);
60
- }
61
-
62
- return {
63
- content: [
64
- {
65
- type: 'text',
66
- text: JSON.stringify(
67
- {
68
- success: true,
69
- task: {
70
- id: task.id,
71
- title: task.title,
72
- priority: task.priority,
73
- due_date: task.due_date,
74
- parent_task_id: task.parent_task_id,
75
- created_at: task.created_at,
76
- },
77
- },
78
- null,
79
- 2
80
- ),
81
- },
82
- ],
83
- };
84
- },
85
- },
86
-
87
- // get_tasks
88
- {
89
- name: 'get_tasks',
90
- description: 'Get tasks by filter',
91
- inputSchema: z.object({
92
- filter: z
93
- .enum(['all', 'today', 'upcoming', 'completed'])
94
- .default('all')
95
- .describe('Task filter'),
96
- }),
97
- handler: async (args, taskOps) => {
98
- const tasks = await taskOps.getTasks(args.filter);
99
-
100
- return {
101
- content: [
102
- {
103
- type: 'text',
104
- text: JSON.stringify(
105
- {
106
- success: true,
107
- tasks: tasks.map((t) => ({
108
- id: t.id,
109
- title: t.title,
110
- priority: t.priority,
111
- completed: t.completed,
112
- due_date: t.due_date,
113
- tags: t.tags?.map((tag) => tag.name) || [],
114
- })),
115
- count: tasks.length,
116
- },
117
- null,
118
- 2
119
- ),
120
- },
121
- ],
122
- };
123
- },
124
- },
125
-
126
- // update_task
127
- {
128
- name: 'update_task',
129
- description: 'Update an existing task',
130
- inputSchema: z.object({
131
- task_id: z.string().describe('Task ID'),
132
- title: z.string().optional().describe('New title'),
133
- notes: z.string().optional().describe('New notes'),
134
- due_date: z.string().optional().describe('New due date (ISO 8601)'),
135
- priority: z
136
- .enum(['none', 'low', 'medium', 'high'])
137
- .optional()
138
- .describe('New priority'),
139
- completed: z.boolean().optional().describe('Completion status'),
140
- }),
141
- handler: async (args, taskOps) => {
142
- const updates: any = {};
143
-
144
- if (args.title !== undefined) updates.title = args.title;
145
- if (args.notes !== undefined) updates.notes = args.notes;
146
- if (args.due_date !== undefined) updates.due_date = args.due_date;
147
- if (args.priority !== undefined) updates.priority = args.priority;
148
- if (args.completed !== undefined) updates.completed = args.completed;
149
-
150
- const task = await taskOps.updateTask(args.task_id, updates);
151
-
152
- return {
153
- content: [
154
- {
155
- type: 'text',
156
- text: JSON.stringify(
157
- {
158
- success: true,
159
- task: {
160
- id: task.id,
161
- title: task.title,
162
- completed: task.completed,
163
- priority: task.priority,
164
- },
165
- },
166
- null,
167
- 2
168
- ),
169
- },
170
- ],
171
- };
172
- },
173
- },
174
-
175
- // complete_task
176
- {
177
- name: 'complete_task',
178
- description: 'Mark a task as complete',
179
- inputSchema: z.object({
180
- task_id: z.string().describe('Task ID'),
181
- }),
182
- handler: async (args, taskOps) => {
183
- const task = await taskOps.completeTask(args.task_id);
184
-
185
- return {
186
- content: [
187
- {
188
- type: 'text',
189
- text: JSON.stringify(
190
- {
191
- success: true,
192
- task: {
193
- id: task.id,
194
- title: task.title,
195
- completed: true,
196
- completed_at: task.completed_at,
197
- },
198
- },
199
- null,
200
- 2
201
- ),
202
- },
203
- ],
204
- };
205
- },
206
- },
207
-
208
- // delete_task
209
- {
210
- name: 'delete_task',
211
- description: 'Delete a task',
212
- inputSchema: z.object({
213
- task_id: z.string().describe('Task ID'),
214
- }),
215
- handler: async (args, taskOps) => {
216
- await taskOps.deleteTask(args.task_id);
217
-
218
- return {
219
- content: [
220
- {
221
- type: 'text',
222
- text: JSON.stringify(
223
- {
224
- success: true,
225
- message: 'Task deleted successfully',
226
- },
227
- null,
228
- 2
229
- ),
230
- },
231
- ],
232
- };
233
- },
234
- },
235
-
236
- // search_tasks
237
- {
238
- name: 'search_tasks',
239
- description: 'Search tasks by title',
240
- inputSchema: z.object({
241
- query: z.string().describe('Search query'),
242
- limit: z.number().default(20).describe('Maximum results'),
243
- }),
244
- handler: async (args, taskOps) => {
245
- const tasks = await taskOps.searchTasks(args.query, args.limit);
246
-
247
- return {
248
- content: [
249
- {
250
- type: 'text',
251
- text: JSON.stringify(
252
- {
253
- success: true,
254
- tasks: tasks.map((t) => ({
255
- id: t.id,
256
- title: t.title,
257
- priority: t.priority,
258
- due_date: t.due_date,
259
- tags: t.tags?.map((tag) => tag.name) || [],
260
- })),
261
- count: tasks.length,
262
- },
263
- null,
264
- 2
265
- ),
266
- },
267
- ],
268
- };
269
- },
270
- },
271
-
272
- // create_task_with_subtasks
273
- {
274
- name: 'create_task_with_subtasks',
275
- description: 'Create a parent task with multiple subtasks in one call. Use this when using TodoWrite - it automatically mirrors your todo list to TaskFlow for persistent tracking.',
276
- inputSchema: z.object({
277
- title: z.string().describe('Parent task title (the overall goal)'),
278
- subtasks: z
279
- .array(z.string())
280
- .describe('Array of subtask titles (one for each todo item)'),
281
- notes: z.string().optional().describe('Notes for parent task'),
282
- due_date: z
283
- .string()
284
- .optional()
285
- .describe('Due date for parent task (ISO 8601 format)'),
286
- priority: z
287
- .enum(['none', 'low', 'medium', 'high'])
288
- .default('none')
289
- .describe('Priority for parent task'),
290
- tags: z
291
- .array(z.string())
292
- .optional()
293
- .describe('Tag names to attach to parent task'),
294
- }),
295
- handler: async (args, taskOps) => {
296
- // Handle tags - get or create
297
- let tagIds: string[] = [];
298
- if (args.tags && args.tags.length > 0) {
299
- for (const tagName of args.tags) {
300
- const tag = await taskOps.findOrCreateTag(tagName);
301
- tagIds.push(tag.id);
302
- }
303
- }
304
-
305
- // Create parent task
306
- const parentTask = await taskOps.createTask({
307
- title: args.title,
308
- notes: args.notes,
309
- notes_format: 'markdown',
310
- due_date: args.due_date,
311
- priority: args.priority,
312
- });
313
-
314
- // Link tags to parent
315
- if (tagIds.length > 0) {
316
- await taskOps.linkTaskTags(parentTask.id, tagIds);
317
- }
318
-
319
- // Create all subtasks
320
- const subtasks = [];
321
- for (const subtaskTitle of args.subtasks) {
322
- const subtask = await taskOps.createTask({
323
- title: subtaskTitle,
324
- notes_format: 'markdown',
325
- priority: 'none',
326
- parent_task_id: parentTask.id,
327
- });
328
- subtasks.push(subtask);
329
- }
330
-
331
- return {
332
- content: [
333
- {
334
- type: 'text',
335
- text: JSON.stringify(
336
- {
337
- success: true,
338
- parent_task: {
339
- id: parentTask.id,
340
- title: parentTask.title,
341
- priority: parentTask.priority,
342
- subtask_count: subtasks.length,
343
- },
344
- subtasks: subtasks.map((s) => ({
345
- id: s.id,
346
- title: s.title,
347
- })),
348
- },
349
- null,
350
- 2
351
- ),
352
- },
353
- ],
354
- };
355
- },
356
- },
357
-
358
- // log_ai_session
359
- {
360
- name: 'log_ai_session',
361
- description: 'Manually log an AI session as a completed task',
362
- inputSchema: z.object({
363
- summary: z.string().describe('What was accomplished'),
364
- files: z
365
- .array(z.string())
366
- .optional()
367
- .describe('Files changed'),
368
- duration_minutes: z
369
- .number()
370
- .optional()
371
- .describe('Session duration'),
372
- }),
373
- handler: async (args, taskOps) => {
374
- const notes = `# AI Session Summary
375
-
376
- ${args.summary}
377
-
378
- ${args.files && args.files.length > 0 ? `## Files Changed\n${args.files.map((f) => `- ${f}`).join('\n')}` : ''}
379
-
380
- ${args.duration_minutes ? `Duration: ${args.duration_minutes} minutes` : ''}
381
-
382
- Generated by TaskFlow MCP Server`;
383
-
384
- const task = await taskOps.createTask({
385
- title: `AI Session: ${args.summary.substring(0, 50)}${args.summary.length > 50 ? '...' : ''}`,
386
- notes,
387
- notes_format: 'markdown',
388
- completed: true,
389
- priority: 'none',
390
- });
391
-
392
- return {
393
- content: [
394
- {
395
- type: 'text',
396
- text: JSON.stringify(
397
- {
398
- success: true,
399
- task: {
400
- id: task.id,
401
- title: task.title,
402
- completed: true,
403
- },
404
- },
405
- null,
406
- 2
407
- ),
408
- },
409
- ],
410
- };
411
- },
412
- },
413
- ];
414
- }
package/tsconfig.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "lib": ["ES2022"],
6
- "moduleResolution": "bundler",
7
- "resolveJsonModule": true,
8
- "allowJs": true,
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "declaration": true,
14
- "declarationMap": true,
15
- "outDir": "./dist",
16
- "rootDir": "./src",
17
- "types": ["node"]
18
- },
19
- "include": ["src/**/*"],
20
- "exclude": ["node_modules", "dist"]
21
- }