@vibetasks/mcp-server 0.3.0 → 0.4.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.
- package/dist/index.js +205 -6
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -18,14 +18,19 @@ function setupTools(taskOps) {
|
|
|
18
18
|
// create_task
|
|
19
19
|
{
|
|
20
20
|
name: "create_task",
|
|
21
|
-
description: "Create a new task in
|
|
21
|
+
description: "Create a new task in VibeTasks. Use this instead of TodoWrite - tasks persist across sessions and sync everywhere.",
|
|
22
22
|
inputSchema: z.object({
|
|
23
23
|
title: z.string().describe("Task title (required)"),
|
|
24
|
-
|
|
24
|
+
description: z.string().optional().describe("Brief description of what this task involves"),
|
|
25
|
+
notes: z.string().optional().describe("Detailed notes in markdown"),
|
|
26
|
+
subtasks: z.array(z.object({
|
|
27
|
+
title: z.string().describe("Subtask title"),
|
|
28
|
+
done: z.boolean().default(false).describe("Is this subtask completed?"),
|
|
29
|
+
notes: z.string().optional().describe("Progress notes for this subtask")
|
|
30
|
+
})).optional().describe("Inline subtasks - each with title, done status, and optional notes"),
|
|
25
31
|
due_date: z.string().optional().describe("Due date (ISO 8601 format)"),
|
|
26
32
|
priority: z.enum(["none", "low", "medium", "high"]).default("none").describe("Task priority"),
|
|
27
|
-
tags: z.array(z.string()).optional().describe("Tag names to attach")
|
|
28
|
-
parent_task_id: z.string().optional().describe("Parent task ID to create this as a subtask")
|
|
33
|
+
tags: z.array(z.string()).optional().describe("Tag names to attach")
|
|
29
34
|
}),
|
|
30
35
|
handler: async (args, taskOps2) => {
|
|
31
36
|
let tagIds = [];
|
|
@@ -35,13 +40,20 @@ function setupTools(taskOps) {
|
|
|
35
40
|
tagIds.push(tag.id);
|
|
36
41
|
}
|
|
37
42
|
}
|
|
43
|
+
const subtasksJson = args.subtasks?.map((st) => ({
|
|
44
|
+
id: crypto.randomUUID(),
|
|
45
|
+
title: st.title,
|
|
46
|
+
done: st.done || false,
|
|
47
|
+
notes: st.notes
|
|
48
|
+
})) || [];
|
|
38
49
|
const task = await taskOps2.createTask({
|
|
39
50
|
title: args.title,
|
|
51
|
+
description: args.description,
|
|
40
52
|
notes: args.notes,
|
|
41
53
|
notes_format: "markdown",
|
|
42
54
|
due_date: args.due_date,
|
|
43
55
|
priority: args.priority,
|
|
44
|
-
|
|
56
|
+
subtasks_json: subtasksJson
|
|
45
57
|
});
|
|
46
58
|
if (tagIds.length > 0) {
|
|
47
59
|
await taskOps2.linkTaskTags(task.id, tagIds);
|
|
@@ -56,9 +68,10 @@ function setupTools(taskOps) {
|
|
|
56
68
|
task: {
|
|
57
69
|
id: task.id,
|
|
58
70
|
title: task.title,
|
|
71
|
+
description: task.description,
|
|
59
72
|
priority: task.priority,
|
|
60
73
|
due_date: task.due_date,
|
|
61
|
-
|
|
74
|
+
subtasks: subtasksJson,
|
|
62
75
|
created_at: task.created_at
|
|
63
76
|
}
|
|
64
77
|
},
|
|
@@ -669,6 +682,192 @@ Generated by TaskFlow MCP Server`;
|
|
|
669
682
|
]
|
|
670
683
|
};
|
|
671
684
|
}
|
|
685
|
+
},
|
|
686
|
+
// update_subtask
|
|
687
|
+
{
|
|
688
|
+
name: "update_subtask",
|
|
689
|
+
description: "Update a subtask within a task. Mark it done, add progress notes, or update the title. Use this to track progress on individual steps.",
|
|
690
|
+
inputSchema: z.object({
|
|
691
|
+
task_id: z.string().describe("Parent task ID"),
|
|
692
|
+
subtask_id: z.string().describe("Subtask ID to update"),
|
|
693
|
+
done: z.boolean().optional().describe("Mark subtask as done/not done"),
|
|
694
|
+
title: z.string().optional().describe("Update subtask title"),
|
|
695
|
+
notes: z.string().optional().describe('Add progress notes (e.g., "Completed auth module, need to test edge cases")')
|
|
696
|
+
}),
|
|
697
|
+
handler: async (args, taskOps2) => {
|
|
698
|
+
const task = await taskOps2.getTask(args.task_id);
|
|
699
|
+
const subtasks = task.subtasks_json || task.subtasks || [];
|
|
700
|
+
const subtaskIndex = subtasks.findIndex((st) => st.id === args.subtask_id);
|
|
701
|
+
if (subtaskIndex === -1) {
|
|
702
|
+
return {
|
|
703
|
+
content: [
|
|
704
|
+
{
|
|
705
|
+
type: "text",
|
|
706
|
+
text: JSON.stringify({ success: false, error: `Subtask ${args.subtask_id} not found` }, null, 2)
|
|
707
|
+
}
|
|
708
|
+
]
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
if (args.done !== void 0) subtasks[subtaskIndex].done = args.done;
|
|
712
|
+
if (args.title !== void 0) subtasks[subtaskIndex].title = args.title;
|
|
713
|
+
if (args.notes !== void 0) subtasks[subtaskIndex].notes = args.notes;
|
|
714
|
+
const updated = await taskOps2.updateTask(args.task_id, { subtasks_json: subtasks });
|
|
715
|
+
return {
|
|
716
|
+
content: [
|
|
717
|
+
{
|
|
718
|
+
type: "text",
|
|
719
|
+
text: JSON.stringify(
|
|
720
|
+
{
|
|
721
|
+
success: true,
|
|
722
|
+
task_id: args.task_id,
|
|
723
|
+
subtask: subtasks[subtaskIndex],
|
|
724
|
+
all_subtasks: subtasks,
|
|
725
|
+
progress: `${subtasks.filter((s) => s.done).length}/${subtasks.length} done`
|
|
726
|
+
},
|
|
727
|
+
null,
|
|
728
|
+
2
|
|
729
|
+
)
|
|
730
|
+
}
|
|
731
|
+
]
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
},
|
|
735
|
+
// add_subtask
|
|
736
|
+
{
|
|
737
|
+
name: "add_subtask",
|
|
738
|
+
description: "Add a new subtask to an existing task. Use this when you discover new steps while working.",
|
|
739
|
+
inputSchema: z.object({
|
|
740
|
+
task_id: z.string().describe("Parent task ID"),
|
|
741
|
+
title: z.string().describe("Subtask title"),
|
|
742
|
+
notes: z.string().optional().describe("Optional notes")
|
|
743
|
+
}),
|
|
744
|
+
handler: async (args, taskOps2) => {
|
|
745
|
+
const task = await taskOps2.getTask(args.task_id);
|
|
746
|
+
const subtasks = task.subtasks_json || task.subtasks || [];
|
|
747
|
+
const newSubtask = {
|
|
748
|
+
id: crypto.randomUUID(),
|
|
749
|
+
title: args.title,
|
|
750
|
+
done: false,
|
|
751
|
+
notes: args.notes
|
|
752
|
+
};
|
|
753
|
+
subtasks.push(newSubtask);
|
|
754
|
+
await taskOps2.updateTask(args.task_id, { subtasks_json: subtasks });
|
|
755
|
+
return {
|
|
756
|
+
content: [
|
|
757
|
+
{
|
|
758
|
+
type: "text",
|
|
759
|
+
text: JSON.stringify(
|
|
760
|
+
{
|
|
761
|
+
success: true,
|
|
762
|
+
task_id: args.task_id,
|
|
763
|
+
new_subtask: newSubtask,
|
|
764
|
+
total_subtasks: subtasks.length
|
|
765
|
+
},
|
|
766
|
+
null,
|
|
767
|
+
2
|
|
768
|
+
)
|
|
769
|
+
}
|
|
770
|
+
]
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
// get_task_images
|
|
775
|
+
{
|
|
776
|
+
name: "get_task_images",
|
|
777
|
+
description: "Get image attachments for a task. Returns signed URLs that can be viewed. Use this to see mockups, screenshots, or error images attached to a task.",
|
|
778
|
+
inputSchema: z.object({
|
|
779
|
+
task_id: z.string().describe("Task ID to get images for")
|
|
780
|
+
}),
|
|
781
|
+
handler: async (args, taskOps2) => {
|
|
782
|
+
const task = await taskOps2.getTask(args.task_id);
|
|
783
|
+
const attachments = task.attachments || [];
|
|
784
|
+
const images = attachments.filter((a) => a.is_image || a.file_type?.startsWith("image/"));
|
|
785
|
+
const imageData = await Promise.all(
|
|
786
|
+
images.map(async (img) => {
|
|
787
|
+
const url = await taskOps2.getAttachmentUrl(img.storage_path);
|
|
788
|
+
return {
|
|
789
|
+
id: img.id,
|
|
790
|
+
file_name: img.file_name,
|
|
791
|
+
file_type: img.file_type,
|
|
792
|
+
url,
|
|
793
|
+
alt_text: img.alt_text,
|
|
794
|
+
ai_description: img.ai_description
|
|
795
|
+
};
|
|
796
|
+
})
|
|
797
|
+
);
|
|
798
|
+
return {
|
|
799
|
+
content: [
|
|
800
|
+
{
|
|
801
|
+
type: "text",
|
|
802
|
+
text: JSON.stringify(
|
|
803
|
+
{
|
|
804
|
+
success: true,
|
|
805
|
+
task_id: args.task_id,
|
|
806
|
+
task_title: task.title,
|
|
807
|
+
images: imageData,
|
|
808
|
+
count: imageData.length
|
|
809
|
+
},
|
|
810
|
+
null,
|
|
811
|
+
2
|
|
812
|
+
)
|
|
813
|
+
}
|
|
814
|
+
]
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
// get_current_task
|
|
819
|
+
{
|
|
820
|
+
name: "get_current_task",
|
|
821
|
+
description: 'Get the task you should be working on right now. Returns the first "vibing" task with full details including subtasks, description, context notes, and images. Call this at the start of a session to know where you left off.',
|
|
822
|
+
inputSchema: z.object({}),
|
|
823
|
+
handler: async (_args, taskOps2) => {
|
|
824
|
+
const allTasks = await taskOps2.getTasks("all");
|
|
825
|
+
const vibingTasks = allTasks.filter((t) => t.status === "vibing");
|
|
826
|
+
if (vibingTasks.length === 0) {
|
|
827
|
+
return {
|
|
828
|
+
content: [
|
|
829
|
+
{
|
|
830
|
+
type: "text",
|
|
831
|
+
text: JSON.stringify(
|
|
832
|
+
{
|
|
833
|
+
success: true,
|
|
834
|
+
current_task: null,
|
|
835
|
+
message: "No tasks currently vibing. Use list_tasks to see available tasks, or create_task to add one."
|
|
836
|
+
},
|
|
837
|
+
null,
|
|
838
|
+
2
|
|
839
|
+
)
|
|
840
|
+
}
|
|
841
|
+
]
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
const task = await taskOps2.getTask(vibingTasks[0].id);
|
|
845
|
+
return {
|
|
846
|
+
content: [
|
|
847
|
+
{
|
|
848
|
+
type: "text",
|
|
849
|
+
text: JSON.stringify(
|
|
850
|
+
{
|
|
851
|
+
success: true,
|
|
852
|
+
current_task: {
|
|
853
|
+
id: task.id,
|
|
854
|
+
title: task.title,
|
|
855
|
+
description: task.description,
|
|
856
|
+
context_notes: task.context_notes,
|
|
857
|
+
subtasks: task.subtasks_json || task.subtasks || [],
|
|
858
|
+
progress: task.subtasks_json ? `${task.subtasks_json.filter((s) => s.done).length}/${task.subtasks_json.length} subtasks done` : null,
|
|
859
|
+
priority: task.priority,
|
|
860
|
+
has_images: (task.attachments || []).some((a) => a.is_image || a.file_type?.startsWith("image/"))
|
|
861
|
+
},
|
|
862
|
+
other_vibing_count: vibingTasks.length - 1
|
|
863
|
+
},
|
|
864
|
+
null,
|
|
865
|
+
2
|
|
866
|
+
)
|
|
867
|
+
}
|
|
868
|
+
]
|
|
869
|
+
};
|
|
870
|
+
}
|
|
672
871
|
}
|
|
673
872
|
];
|
|
674
873
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibetasks/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "VibeTasks MCP Server for Claude Code, Cursor, and AI coding tools. Status-based task management: todo → vibing → done.",
|
|
5
5
|
"author": "Vyas",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
48
|
-
"@vibetasks/core": "^0.
|
|
48
|
+
"@vibetasks/core": "^0.4.2",
|
|
49
49
|
"zod": "^3.22.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|