@vibescope/mcp-server 0.1.0 → 0.2.1

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 (76) hide show
  1. package/README.md +1 -1
  2. package/dist/api-client.d.ts +120 -2
  3. package/dist/api-client.js +51 -5
  4. package/dist/handlers/bodies-of-work.js +84 -50
  5. package/dist/handlers/cost.js +62 -54
  6. package/dist/handlers/decisions.js +29 -16
  7. package/dist/handlers/deployment.js +114 -107
  8. package/dist/handlers/discovery.d.ts +3 -0
  9. package/dist/handlers/discovery.js +55 -657
  10. package/dist/handlers/fallback.js +42 -28
  11. package/dist/handlers/file-checkouts.d.ts +18 -0
  12. package/dist/handlers/file-checkouts.js +101 -0
  13. package/dist/handlers/findings.d.ts +14 -1
  14. package/dist/handlers/findings.js +104 -28
  15. package/dist/handlers/git-issues.js +36 -32
  16. package/dist/handlers/ideas.js +44 -26
  17. package/dist/handlers/index.d.ts +2 -0
  18. package/dist/handlers/index.js +6 -0
  19. package/dist/handlers/milestones.js +34 -27
  20. package/dist/handlers/organizations.js +86 -78
  21. package/dist/handlers/progress.js +22 -11
  22. package/dist/handlers/project.js +62 -22
  23. package/dist/handlers/requests.js +15 -11
  24. package/dist/handlers/roles.d.ts +18 -0
  25. package/dist/handlers/roles.js +130 -0
  26. package/dist/handlers/session.js +52 -15
  27. package/dist/handlers/sprints.js +78 -65
  28. package/dist/handlers/tasks.js +135 -74
  29. package/dist/handlers/tool-docs.d.ts +4 -3
  30. package/dist/handlers/tool-docs.js +252 -5
  31. package/dist/handlers/validation.js +30 -14
  32. package/dist/index.js +25 -7
  33. package/dist/tools.js +417 -4
  34. package/package.json +1 -1
  35. package/src/api-client.ts +161 -8
  36. package/src/handlers/__test-setup__.ts +12 -0
  37. package/src/handlers/bodies-of-work.ts +127 -111
  38. package/src/handlers/cost.test.ts +34 -44
  39. package/src/handlers/cost.ts +77 -92
  40. package/src/handlers/decisions.test.ts +3 -2
  41. package/src/handlers/decisions.ts +32 -27
  42. package/src/handlers/deployment.ts +144 -190
  43. package/src/handlers/discovery.test.ts +4 -5
  44. package/src/handlers/discovery.ts +60 -746
  45. package/src/handlers/fallback.test.ts +78 -0
  46. package/src/handlers/fallback.ts +51 -38
  47. package/src/handlers/file-checkouts.test.ts +477 -0
  48. package/src/handlers/file-checkouts.ts +127 -0
  49. package/src/handlers/findings.test.ts +274 -2
  50. package/src/handlers/findings.ts +123 -57
  51. package/src/handlers/git-issues.ts +40 -80
  52. package/src/handlers/ideas.ts +56 -54
  53. package/src/handlers/index.ts +6 -0
  54. package/src/handlers/milestones.test.ts +1 -1
  55. package/src/handlers/milestones.ts +47 -45
  56. package/src/handlers/organizations.ts +104 -129
  57. package/src/handlers/progress.ts +24 -22
  58. package/src/handlers/project.ts +89 -57
  59. package/src/handlers/requests.ts +18 -14
  60. package/src/handlers/roles.test.ts +303 -0
  61. package/src/handlers/roles.ts +208 -0
  62. package/src/handlers/session.test.ts +37 -2
  63. package/src/handlers/session.ts +64 -21
  64. package/src/handlers/sprints.ts +114 -134
  65. package/src/handlers/tasks.test.ts +61 -0
  66. package/src/handlers/tasks.ts +170 -139
  67. package/src/handlers/tool-docs.ts +1024 -0
  68. package/src/handlers/validation.test.ts +53 -1
  69. package/src/handlers/validation.ts +32 -21
  70. package/src/index.ts +25 -7
  71. package/src/tools.ts +417 -4
  72. package/dist/config/tool-categories.d.ts +0 -31
  73. package/dist/config/tool-categories.js +0 -253
  74. package/dist/knowledge.d.ts +0 -6
  75. package/dist/knowledge.js +0 -218
  76. package/src/knowledge.ts +0 -230
@@ -15,8 +15,82 @@
15
15
  * - add_subtask
16
16
  * - get_subtasks
17
17
  */
18
- import { validateRequired, validateUUID, validateTaskStatus, validatePriority, validateProgressPercentage, validateEstimatedMinutes, ValidationError, } from '../validators.js';
18
+ import { parseArgs, uuidValidator, taskStatusValidator, priorityValidator, progressValidator, minutesValidator, createEnumValidator, ValidationError, } from '../validators.js';
19
19
  import { getApiClient } from '../api-client.js';
20
+ // Valid task types
21
+ const VALID_TASK_TYPES = [
22
+ 'frontend', 'backend', 'database', 'feature', 'bugfix',
23
+ 'design', 'mcp', 'testing', 'docs', 'infra', 'other'
24
+ ];
25
+ // ============================================================================
26
+ // Argument Schemas
27
+ // ============================================================================
28
+ const getTasksSchema = {
29
+ project_id: { type: 'string', required: true, validate: uuidValidator },
30
+ status: { type: 'string', validate: taskStatusValidator },
31
+ limit: { type: 'number', default: 50 },
32
+ offset: { type: 'number', default: 0 },
33
+ search_query: { type: 'string' },
34
+ include_subtasks: { type: 'boolean', default: false },
35
+ include_metadata: { type: 'boolean', default: false },
36
+ };
37
+ const getNextTaskSchema = {
38
+ project_id: { type: 'string', required: true, validate: uuidValidator },
39
+ };
40
+ const addTaskSchema = {
41
+ project_id: { type: 'string', required: true, validate: uuidValidator },
42
+ title: { type: 'string', required: true },
43
+ description: { type: 'string' },
44
+ priority: { type: 'number', default: 3, validate: priorityValidator },
45
+ estimated_minutes: { type: 'number', validate: minutesValidator },
46
+ blocking: { type: 'boolean', default: false },
47
+ task_type: { type: 'string', validate: createEnumValidator(VALID_TASK_TYPES) },
48
+ };
49
+ const updateTaskSchema = {
50
+ task_id: { type: 'string', required: true, validate: uuidValidator },
51
+ title: { type: 'string' },
52
+ description: { type: 'string' },
53
+ priority: { type: 'number', validate: priorityValidator },
54
+ status: { type: 'string', validate: taskStatusValidator },
55
+ progress_percentage: { type: 'number', validate: progressValidator },
56
+ progress_note: { type: 'string' },
57
+ estimated_minutes: { type: 'number', validate: minutesValidator },
58
+ git_branch: { type: 'string' },
59
+ task_type: { type: 'string', validate: createEnumValidator(VALID_TASK_TYPES) },
60
+ };
61
+ const completeTaskSchema = {
62
+ task_id: { type: 'string', required: true, validate: uuidValidator },
63
+ summary: { type: 'string' },
64
+ };
65
+ const deleteTaskSchema = {
66
+ task_id: { type: 'string', required: true, validate: uuidValidator },
67
+ };
68
+ const addTaskReferenceSchema = {
69
+ task_id: { type: 'string', required: true, validate: uuidValidator },
70
+ url: { type: 'string', required: true },
71
+ label: { type: 'string' },
72
+ };
73
+ const removeTaskReferenceSchema = {
74
+ task_id: { type: 'string', required: true, validate: uuidValidator },
75
+ url: { type: 'string', required: true },
76
+ };
77
+ const batchUpdateTasksSchema = {
78
+ updates: { type: 'array', required: true },
79
+ };
80
+ const batchCompleteTasksSchema = {
81
+ completions: { type: 'array', required: true },
82
+ };
83
+ const addSubtaskSchema = {
84
+ parent_task_id: { type: 'string', required: true, validate: uuidValidator },
85
+ title: { type: 'string', required: true },
86
+ description: { type: 'string' },
87
+ priority: { type: 'number', validate: priorityValidator },
88
+ estimated_minutes: { type: 'number', validate: minutesValidator },
89
+ };
90
+ const getSubtasksSchema = {
91
+ parent_task_id: { type: 'string', required: true, validate: uuidValidator },
92
+ status: { type: 'string', validate: taskStatusValidator },
93
+ };
20
94
  function getTaskCompleteGitInstructions(gitWorkflow, gitMainBranch, gitDevelopBranch, taskBranch, taskTitle, taskId) {
21
95
  if (gitWorkflow === 'none') {
22
96
  return undefined;
@@ -68,14 +142,11 @@ export function getValidationApprovedGitInstructions(config, taskBranch) {
68
142
  // Task Handlers - Using API Client
69
143
  // ============================================================================
70
144
  export const getTasks = async (args, ctx) => {
71
- const { project_id, status, limit = 50, offset = 0, search_query, include_subtasks = false, include_metadata = false } = args;
72
- validateRequired(project_id, 'project_id');
73
- validateUUID(project_id, 'project_id');
74
- validateTaskStatus(status);
145
+ const { project_id, status, limit, offset, search_query, include_subtasks, include_metadata } = parseArgs(args, getTasksSchema);
75
146
  const api = getApiClient();
76
147
  const response = await api.getTasks(project_id, {
77
148
  status,
78
- limit: Math.min(limit, 200),
149
+ limit: Math.min(limit ?? 50, 200),
79
150
  offset,
80
151
  include_subtasks,
81
152
  search_query,
@@ -93,9 +164,7 @@ export const getTasks = async (args, ctx) => {
93
164
  };
94
165
  };
95
166
  export const getNextTask = async (args, ctx) => {
96
- const { project_id } = args;
97
- validateRequired(project_id, 'project_id');
98
- validateUUID(project_id, 'project_id');
167
+ const { project_id } = parseArgs(args, getNextTaskSchema);
99
168
  const api = getApiClient();
100
169
  const response = await api.getNextTask(project_id, ctx.session.currentSessionId || undefined);
101
170
  if (!response.ok) {
@@ -138,12 +207,7 @@ export const getNextTask = async (args, ctx) => {
138
207
  return { result };
139
208
  };
140
209
  export const addTask = async (args, ctx) => {
141
- const { project_id, title, description, priority = 3, estimated_minutes, blocking = false, task_type } = args;
142
- validateRequired(project_id, 'project_id');
143
- validateRequired(title, 'title');
144
- validateUUID(project_id, 'project_id');
145
- validatePriority(priority);
146
- validateEstimatedMinutes(estimated_minutes);
210
+ const { project_id, title, description, priority, estimated_minutes, blocking, task_type } = parseArgs(args, addTaskSchema);
147
211
  const api = getApiClient();
148
212
  const response = await api.createTask(project_id, {
149
213
  title,
@@ -152,6 +216,7 @@ export const addTask = async (args, ctx) => {
152
216
  estimated_minutes,
153
217
  blocking,
154
218
  session_id: ctx.session.currentSessionId || undefined,
219
+ task_type,
155
220
  });
156
221
  if (!response.ok) {
157
222
  throw new Error(`Failed to add task: ${response.error}`);
@@ -169,13 +234,8 @@ export const addTask = async (args, ctx) => {
169
234
  return { result };
170
235
  };
171
236
  export const updateTask = async (args, ctx) => {
172
- const { task_id, progress_note, ...updates } = args;
173
- validateRequired(task_id, 'task_id');
174
- validateUUID(task_id, 'task_id');
175
- validateTaskStatus(updates.status);
176
- validatePriority(updates.priority);
177
- validateProgressPercentage(updates.progress_percentage);
178
- validateEstimatedMinutes(updates.estimated_minutes);
237
+ const { task_id, title, description, priority, status, progress_percentage, progress_note, estimated_minutes, git_branch, task_type } = parseArgs(args, updateTaskSchema);
238
+ const updates = { title, description, priority, status, progress_percentage, estimated_minutes, git_branch, task_type };
179
239
  const api = getApiClient();
180
240
  const response = await api.updateTask(task_id, {
181
241
  ...updates,
@@ -208,14 +268,39 @@ export const updateTask = async (args, ctx) => {
208
268
  },
209
269
  };
210
270
  }
271
+ if (response.error?.includes('branch_conflict')) {
272
+ return {
273
+ result: {
274
+ error: 'branch_conflict',
275
+ message: response.error,
276
+ conflicting_task_id: response.data?.conflicting_task_id,
277
+ conflicting_task_title: response.data?.conflicting_task_title,
278
+ },
279
+ };
280
+ }
211
281
  throw new Error(`Failed to update task: ${response.error}`);
212
282
  }
213
- return { result: { success: true, task_id } };
283
+ // Build result - include git workflow info when transitioning to in_progress
284
+ const data = response.data;
285
+ const result = { success: true, task_id };
286
+ if (data?.git_workflow) {
287
+ result.git_workflow = data.git_workflow;
288
+ }
289
+ if (data?.worktree_setup) {
290
+ result.worktree_setup = data.worktree_setup;
291
+ }
292
+ if (data?.next_step) {
293
+ result.next_step = data.next_step;
294
+ }
295
+ // Warn if transitioning to in_progress without git_branch
296
+ if (updates.status === 'in_progress' && !updates.git_branch) {
297
+ result.warning = 'git_branch not set. For multi-agent collaboration, set git_branch when marking in_progress to track your worktree.';
298
+ result.hint = 'Call update_task again with git_branch parameter after creating your worktree.';
299
+ }
300
+ return { result };
214
301
  };
215
302
  export const completeTask = async (args, ctx) => {
216
- const { task_id, summary } = args;
217
- validateRequired(task_id, 'task_id');
218
- validateUUID(task_id, 'task_id');
303
+ const { task_id, summary } = parseArgs(args, completeTaskSchema);
219
304
  const api = getApiClient();
220
305
  const response = await api.completeTask(task_id, {
221
306
  summary,
@@ -239,15 +324,17 @@ export const completeTask = async (args, ctx) => {
239
324
  if (data.context) {
240
325
  result.context = data.context;
241
326
  }
327
+ // Pass through warnings (e.g., missing git_branch)
328
+ if (data.warnings) {
329
+ result.warnings = data.warnings;
330
+ }
242
331
  // Git workflow instructions are already in API response but we need to fetch
243
332
  // task details if we want to include them (API should return these)
244
333
  result.next_action = data.next_action;
245
334
  return { result };
246
335
  };
247
336
  export const deleteTask = async (args, ctx) => {
248
- const { task_id } = args;
249
- validateRequired(task_id, 'task_id');
250
- validateUUID(task_id, 'task_id');
337
+ const { task_id } = parseArgs(args, deleteTaskSchema);
251
338
  const api = getApiClient();
252
339
  const response = await api.deleteTask(task_id);
253
340
  if (!response.ok) {
@@ -256,10 +343,7 @@ export const deleteTask = async (args, ctx) => {
256
343
  return { result: { success: true, deleted_id: task_id } };
257
344
  };
258
345
  export const addTaskReference = async (args, ctx) => {
259
- const { task_id, url, label } = args;
260
- validateRequired(task_id, 'task_id');
261
- validateUUID(task_id, 'task_id');
262
- validateRequired(url, 'url');
346
+ const { task_id, url, label } = parseArgs(args, addTaskReferenceSchema);
263
347
  const api = getApiClient();
264
348
  const response = await api.addTaskReference(task_id, url, label);
265
349
  if (!response.ok) {
@@ -276,10 +360,7 @@ export const addTaskReference = async (args, ctx) => {
276
360
  };
277
361
  };
278
362
  export const removeTaskReference = async (args, ctx) => {
279
- const { task_id, url } = args;
280
- validateRequired(task_id, 'task_id');
281
- validateUUID(task_id, 'task_id');
282
- validateRequired(url, 'url');
363
+ const { task_id, url } = parseArgs(args, removeTaskReferenceSchema);
283
364
  const api = getApiClient();
284
365
  const response = await api.removeTaskReference(task_id, url);
285
366
  if (!response.ok) {
@@ -291,61 +372,52 @@ export const removeTaskReference = async (args, ctx) => {
291
372
  return { result: { success: true } };
292
373
  };
293
374
  export const batchUpdateTasks = async (args, ctx) => {
294
- const { updates } = args;
295
- if (!updates || !Array.isArray(updates) || updates.length === 0) {
375
+ const { updates } = parseArgs(args, batchUpdateTasksSchema);
376
+ const typedUpdates = updates;
377
+ if (!Array.isArray(typedUpdates) || typedUpdates.length === 0) {
296
378
  throw new ValidationError('updates must be a non-empty array', {
297
379
  field: 'updates',
298
380
  hint: 'Provide an array of task updates with at least one item',
299
381
  });
300
382
  }
301
- if (updates.length > 50) {
383
+ if (typedUpdates.length > 50) {
302
384
  throw new ValidationError('Too many updates. Maximum is 50 per batch.', {
303
385
  field: 'updates',
304
386
  hint: 'Split your updates into smaller batches',
305
387
  });
306
388
  }
307
- // Validate all inputs first
308
- for (const update of updates) {
309
- validateRequired(update.task_id, 'task_id');
310
- validateUUID(update.task_id, 'task_id');
311
- validateTaskStatus(update.status);
312
- validatePriority(update.priority);
313
- validateProgressPercentage(update.progress_percentage);
314
- }
389
+ // Individual item validation happens at API level
315
390
  const api = getApiClient();
316
- const response = await api.batchUpdateTasks(updates);
391
+ const response = await api.batchUpdateTasks(typedUpdates);
317
392
  if (!response.ok) {
318
393
  throw new Error(`Failed to batch update tasks: ${response.error}`);
319
394
  }
320
395
  return {
321
396
  result: {
322
397
  success: response.data?.success || false,
323
- total: updates.length,
398
+ total: typedUpdates.length,
324
399
  succeeded: response.data?.updated_count || 0,
325
400
  },
326
401
  };
327
402
  };
328
403
  export const batchCompleteTasks = async (args, ctx) => {
329
- const { completions } = args;
330
- if (!completions || !Array.isArray(completions) || completions.length === 0) {
404
+ const { completions } = parseArgs(args, batchCompleteTasksSchema);
405
+ const typedCompletions = completions;
406
+ if (!Array.isArray(typedCompletions) || typedCompletions.length === 0) {
331
407
  throw new ValidationError('completions must be a non-empty array', {
332
408
  field: 'completions',
333
409
  hint: 'Provide an array of task completions with at least one item',
334
410
  });
335
411
  }
336
- if (completions.length > 50) {
412
+ if (typedCompletions.length > 50) {
337
413
  throw new ValidationError('Too many completions. Maximum is 50 per batch.', {
338
414
  field: 'completions',
339
415
  hint: 'Split your completions into smaller batches',
340
416
  });
341
417
  }
342
- // Validate all inputs first
343
- for (const completion of completions) {
344
- validateRequired(completion.task_id, 'task_id');
345
- validateUUID(completion.task_id, 'task_id');
346
- }
418
+ // Individual item validation happens at API level
347
419
  const api = getApiClient();
348
- const response = await api.batchCompleteTasks(completions);
420
+ const response = await api.batchCompleteTasks(typedCompletions);
349
421
  if (!response.ok) {
350
422
  throw new Error(`Failed to batch complete tasks: ${response.error}`);
351
423
  }
@@ -353,9 +425,9 @@ export const batchCompleteTasks = async (args, ctx) => {
353
425
  return {
354
426
  result: {
355
427
  success: data?.success || false,
356
- total: completions.length,
428
+ total: typedCompletions.length,
357
429
  succeeded: data?.completed_count || 0,
358
- failed: completions.length - (data?.completed_count || 0),
430
+ failed: typedCompletions.length - (data?.completed_count || 0),
359
431
  next_task: data?.next_task,
360
432
  },
361
433
  };
@@ -364,14 +436,7 @@ export const batchCompleteTasks = async (args, ctx) => {
364
436
  // Subtask Handlers
365
437
  // ============================================================================
366
438
  export const addSubtask = async (args, ctx) => {
367
- const { parent_task_id, title, description, priority, estimated_minutes } = args;
368
- validateRequired(parent_task_id, 'parent_task_id');
369
- validateUUID(parent_task_id, 'parent_task_id');
370
- validateRequired(title, 'title');
371
- if (priority !== undefined)
372
- validatePriority(priority);
373
- if (estimated_minutes !== undefined)
374
- validateEstimatedMinutes(estimated_minutes);
439
+ const { parent_task_id, title, description, priority, estimated_minutes } = parseArgs(args, addSubtaskSchema);
375
440
  const api = getApiClient();
376
441
  const response = await api.addSubtask(parent_task_id, {
377
442
  title,
@@ -400,11 +465,7 @@ export const addSubtask = async (args, ctx) => {
400
465
  };
401
466
  };
402
467
  export const getSubtasks = async (args, ctx) => {
403
- const { parent_task_id, status } = args;
404
- validateRequired(parent_task_id, 'parent_task_id');
405
- validateUUID(parent_task_id, 'parent_task_id');
406
- if (status)
407
- validateTaskStatus(status);
468
+ const { parent_task_id, status } = parseArgs(args, getSubtasksSchema);
408
469
  const api = getApiClient();
409
470
  const response = await api.getSubtasks(parent_task_id, status);
410
471
  if (!response.ok) {
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Tool Documentation
3
3
  *
4
- * This file contains detailed documentation for all MCP tools.
5
- * It is loaded dynamically by get_tool_info to reduce memory footprint
6
- * when tool documentation is not needed.
4
+ * Externalized documentation for all MCP tools.
5
+ * This file is lazy-loaded by get_tool_info to save tokens.
6
+ *
7
+ * Token savings: ~8,000 tokens per schema load when this isn't bundled.
7
8
  */
8
9
  export declare const TOOL_INFO: Record<string, string>;
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Tool Documentation
3
3
  *
4
- * This file contains detailed documentation for all MCP tools.
5
- * It is loaded dynamically by get_tool_info to reduce memory footprint
6
- * when tool documentation is not needed.
4
+ * Externalized documentation for all MCP tools.
5
+ * This file is lazy-loaded by get_tool_info to save tokens.
6
+ *
7
+ * Token savings: ~8,000 tokens per schema load when this isn't bundled.
7
8
  */
8
9
  export const TOOL_INFO = {
9
10
  start_work_session: `# start_work_session
@@ -32,7 +33,8 @@ Get token usage statistics for current session.
32
33
  Send heartbeat to maintain active status. Call every 30-60 seconds.
33
34
 
34
35
  **Parameters:**
35
- - session_id (optional): Uses current session if not provided`,
36
+ - session_id (optional): Uses current session if not provided
37
+ - current_worktree_path (optional): Report your current git worktree path (e.g., "../project-task-abc123")`,
36
38
  end_work_session: `# end_work_session
37
39
  End session and release claimed tasks.
38
40
 
@@ -629,7 +631,252 @@ Get cost breakdown by task for a project.
629
631
  - limit: Max tasks to return (default: 20)
630
632
 
631
633
  **Returns:** Tasks sorted by estimated cost with model breakdown`,
632
- // Knowledge base tools
634
+ // Subtasks
635
+ add_subtask: `# add_subtask
636
+ Add a subtask to break down a larger task.
637
+
638
+ **Parameters:**
639
+ - parent_task_id (required): UUID of the parent task
640
+ - title (required): Subtask title
641
+ - description (optional): Detailed description
642
+ - priority (optional): 1-5 (defaults to parent priority)
643
+ - estimated_minutes (optional): Time estimate
644
+
645
+ **Note:** Max depth is 1 (subtasks cannot have their own subtasks).`,
646
+ get_subtasks: `# get_subtasks
647
+ Get subtasks for a parent task.
648
+
649
+ **Parameters:**
650
+ - parent_task_id (required): UUID of the parent task
651
+ - status (optional): Filter by status
652
+
653
+ **Returns:** Subtasks with aggregate completion stats.`,
654
+ // Bodies of work
655
+ create_body_of_work: `# create_body_of_work
656
+ Create a new body of work to group tasks into phases.
657
+
658
+ **Parameters:**
659
+ - project_id (required): Project UUID
660
+ - title (required): Title for the body of work
661
+ - description (optional): Description
662
+ - auto_deploy_on_completion (optional): Auto-deploy when all tasks complete (default: false)
663
+ - deploy_environment (optional): Target environment (default: production)
664
+ - deploy_version_bump (optional): Version bump (default: minor)
665
+ - deploy_trigger (optional): When to trigger auto-deploy (default: all_completed_validated)`,
666
+ update_body_of_work: `# update_body_of_work
667
+ Update a body of work's settings.
668
+
669
+ **Parameters:**
670
+ - body_of_work_id (required): Body of work UUID
671
+ - title, description (optional)
672
+ - auto_deploy_on_completion, deploy_environment, deploy_version_bump, deploy_trigger (optional)`,
673
+ get_body_of_work: `# get_body_of_work
674
+ Get a body of work with all its tasks organized by phase.
675
+
676
+ **Parameters:**
677
+ - body_of_work_id (required): Body of work UUID
678
+
679
+ **Returns:** Body of work with tasks grouped by pre/core/post phases.`,
680
+ get_bodies_of_work: `# get_bodies_of_work
681
+ List bodies of work for a project.
682
+
683
+ **Parameters:**
684
+ - project_id (required): Project UUID
685
+ - status (optional): Filter by status (draft, active, completed, cancelled)
686
+ - limit (optional): Max items (default 50)`,
687
+ delete_body_of_work: `# delete_body_of_work
688
+ Delete a body of work. Tasks are preserved but no longer grouped.
689
+
690
+ **Parameters:**
691
+ - body_of_work_id (required): Body of work UUID`,
692
+ add_task_to_body_of_work: `# add_task_to_body_of_work
693
+ Add a task to a body of work in a specific phase.
694
+
695
+ **Parameters:**
696
+ - body_of_work_id (required): Body of work UUID
697
+ - task_id (required): Task UUID to add
698
+ - phase (optional): pre, core, or post (default: core)
699
+ - order_index (optional): Order within phase`,
700
+ remove_task_from_body_of_work: `# remove_task_from_body_of_work
701
+ Remove a task from its body of work.
702
+
703
+ **Parameters:**
704
+ - task_id (required): Task UUID to remove
705
+
706
+ **Note:** The task is preserved, just no longer grouped.`,
707
+ activate_body_of_work: `# activate_body_of_work
708
+ Activate a draft body of work to start execution.
709
+
710
+ **Parameters:**
711
+ - body_of_work_id (required): Body of work UUID
712
+
713
+ **Note:** Requires at least one task. Once active, tasks follow phase order.`,
714
+ add_task_dependency: `# add_task_dependency
715
+ Add a dependency between tasks in a body of work.
716
+
717
+ **Parameters:**
718
+ - body_of_work_id (required): Body of work UUID
719
+ - task_id (required): Task that depends on another
720
+ - depends_on_task_id (required): Task that must complete first
721
+
722
+ **Note:** Prevents circular dependencies.`,
723
+ remove_task_dependency: `# remove_task_dependency
724
+ Remove a dependency between tasks.
725
+
726
+ **Parameters:**
727
+ - task_id (required): Task UUID
728
+ - depends_on_task_id (required): Dependency task UUID`,
729
+ get_task_dependencies: `# get_task_dependencies
730
+ Get task dependencies for a body of work or specific task.
731
+
732
+ **Parameters:**
733
+ - body_of_work_id (optional): Body of work UUID
734
+ - task_id (optional): Specific task UUID`,
735
+ get_next_body_of_work_task: `# get_next_body_of_work_task
736
+ Get the next available task from a body of work.
737
+
738
+ **Parameters:**
739
+ - body_of_work_id (required): Body of work UUID
740
+
741
+ **Note:** Considers phase order (pre → core → post) and dependencies.`,
742
+ // Sprints
743
+ create_sprint: `# create_sprint
744
+ Create a new sprint with time bounds and velocity tracking.
745
+
746
+ **Parameters:**
747
+ - project_id (required): Project UUID
748
+ - title (required): Sprint title (e.g., "Sprint 5")
749
+ - start_date (required): Start date (YYYY-MM-DD)
750
+ - end_date (required): End date (YYYY-MM-DD)
751
+ - goal (optional): Sprint goal statement
752
+ - auto_deploy_on_completion, deploy_environment, deploy_version_bump (optional)`,
753
+ update_sprint: `# update_sprint
754
+ Update a sprint's details.
755
+
756
+ **Parameters:**
757
+ - sprint_id (required): Sprint UUID
758
+ - title, goal, start_date, end_date (optional)
759
+ - auto_deploy_on_completion, deploy_environment, deploy_version_bump (optional)`,
760
+ get_sprint: `# get_sprint
761
+ Get a sprint with all its tasks organized by phase.
762
+
763
+ **Parameters:**
764
+ - sprint_id (required): Sprint UUID
765
+
766
+ **Returns:** Sprint with progress percentage, velocity points, committed points.`,
767
+ get_sprints: `# get_sprints
768
+ List sprints for a project with velocity metrics.
769
+
770
+ **Parameters:**
771
+ - project_id (required): Project UUID
772
+ - status (optional): planning, active, in_review, retrospective, completed, cancelled
773
+ - limit (optional): Max sprints (default 20)`,
774
+ delete_sprint: `# delete_sprint
775
+ Delete a sprint. Tasks are preserved but no longer grouped.
776
+
777
+ **Parameters:**
778
+ - sprint_id (required): Sprint UUID`,
779
+ start_sprint: `# start_sprint
780
+ Start a sprint. Transitions from 'planning' to 'active'.
781
+
782
+ **Parameters:**
783
+ - sprint_id (required): Sprint UUID
784
+
785
+ **Note:** Locks committed_points at current total story points.`,
786
+ complete_sprint: `# complete_sprint
787
+ Complete a sprint. Handles retrospective phase and auto-deployment.
788
+
789
+ **Parameters:**
790
+ - sprint_id (required): Sprint UUID
791
+ - retrospective_notes (optional): Sprint retrospective notes
792
+ - skip_retrospective (optional): Skip retrospective phase (default: false)`,
793
+ add_task_to_sprint: `# add_task_to_sprint
794
+ Add a task to a sprint with optional story points.
795
+
796
+ **Parameters:**
797
+ - sprint_id (required): Sprint UUID
798
+ - task_id (required): Task UUID to add
799
+ - story_points (optional): Story point estimate
800
+ - phase (optional): pre, core, or post (default: core)`,
801
+ remove_task_from_sprint: `# remove_task_from_sprint
802
+ Remove a task from a sprint.
803
+
804
+ **Parameters:**
805
+ - sprint_id (required): Sprint UUID
806
+ - task_id (required): Task UUID to remove
807
+
808
+ **Note:** Task returns to backlog.`,
809
+ get_sprint_backlog: `# get_sprint_backlog
810
+ Get tasks that can be added to a sprint.
811
+
812
+ **Parameters:**
813
+ - project_id (required): Project UUID
814
+ - sprint_id (optional): Exclude tasks already in this sprint
815
+
816
+ **Returns:** Tasks not assigned to any body of work or sprint.`,
817
+ get_sprint_velocity: `# get_sprint_velocity
818
+ Get velocity metrics for completed sprints.
819
+
820
+ **Parameters:**
821
+ - project_id (required): Project UUID
822
+ - limit (optional): Number of sprints to analyze (default 10)
823
+
824
+ **Returns:** Committed vs completed points, average velocity.`,
825
+ // Git issues
826
+ add_git_issue: `# add_git_issue
827
+ Record a git-related issue (merge conflict, push failure, etc.).
828
+
829
+ **Parameters:**
830
+ - project_id (required): Project UUID
831
+ - issue_type (required): merge_conflict, push_failed, rebase_needed, branch_diverged, pr_not_mergeable
832
+ - branch (required): Branch where the issue occurred
833
+ - target_branch, conflicting_files, error_message, pr_url, task_id (optional)`,
834
+ resolve_git_issue: `# resolve_git_issue
835
+ Mark a git issue as resolved.
836
+
837
+ **Parameters:**
838
+ - git_issue_id (required): Git issue UUID
839
+ - resolution_note (optional): How the issue was resolved
840
+ - auto_resolved (optional): Whether auto-resolved`,
841
+ get_git_issues: `# get_git_issues
842
+ Get git issues for a project.
843
+
844
+ **Parameters:**
845
+ - project_id (required): Project UUID
846
+ - status (optional): open or resolved (default: open)
847
+ - issue_type (optional): Filter by issue type
848
+ - branch (optional): Filter by branch
849
+ - limit (optional): Max issues (default 50)`,
850
+ delete_git_issue: `# delete_git_issue
851
+ Delete a git issue.
852
+
853
+ **Parameters:**
854
+ - git_issue_id (required): Git issue UUID`,
855
+ // Deployment requirements
856
+ add_deployment_requirement: `# add_deployment_requirement
857
+ Add a pre-deployment requirement.
858
+
859
+ **Parameters:**
860
+ - project_id (required): Project UUID
861
+ - type (required): migration, env_var, config, manual, breaking_change, agent_task
862
+ - title (required): Brief description
863
+ - description (optional): Detailed instructions
864
+ - stage (optional): preparation, deployment, or verification (default: preparation)
865
+ - file_path (optional): File path reference
866
+ - blocking (optional): Whether converted task blocks other work`,
867
+ complete_deployment_requirement: `# complete_deployment_requirement
868
+ Mark a deployment requirement as completed.
869
+
870
+ **Parameters:**
871
+ - requirement_id (required): Requirement UUID`,
872
+ get_deployment_requirements: `# get_deployment_requirements
873
+ Get pending deployment requirements.
874
+
875
+ **Parameters:**
876
+ - project_id (required): Project UUID
877
+ - stage (optional): preparation, deployment, verification, or all
878
+ - status (optional): pending, completed, converted_to_task, or all (default: pending)`,
879
+ // Knowledge base
633
880
  query_knowledge_base: `# query_knowledge_base
634
881
  Query aggregated project knowledge in a single call. Reduces token usage by combining multiple data sources.
635
882