@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
@@ -309,7 +309,7 @@ describe('validateTask', () => {
309
309
 
310
310
  await expect(
311
311
  validateTask({ task_id: VALID_UUID }, ctx)
312
- ).rejects.toThrow('approved is required');
312
+ ).rejects.toThrow('Missing required field: approved');
313
313
  });
314
314
 
315
315
  it('should throw error when task not found', async () => {
@@ -494,4 +494,56 @@ describe('validateTask', () => {
494
494
  validateTask({ task_id: VALID_UUID, approved: false }, ctx)
495
495
  ).rejects.toThrow('Failed to validate task');
496
496
  });
497
+
498
+ describe('PR requirement', () => {
499
+ it('should return error when PR is required but not present', async () => {
500
+ mockApiClient.validateTask.mockResolvedValue({
501
+ ok: false,
502
+ error: 'pr_required',
503
+ data: {
504
+ message: 'This project uses git-flow workflow which requires a Pull Request before validation approval.',
505
+ workflow: 'git-flow',
506
+ },
507
+ });
508
+ const ctx = createMockContext();
509
+
510
+ const result = await validateTask(
511
+ { task_id: VALID_UUID, approved: true },
512
+ ctx
513
+ );
514
+
515
+ expect(result.result).toMatchObject({
516
+ error: 'pr_required',
517
+ workflow: 'git-flow',
518
+ action_required: expect.stringContaining('add_task_reference'),
519
+ });
520
+ });
521
+
522
+ it('should pass skip_pr_check to API', async () => {
523
+ mockApiClient.validateTask.mockResolvedValue({
524
+ ok: true,
525
+ data: {
526
+ success: true,
527
+ validated_task_id: VALID_UUID,
528
+ self_validated: false,
529
+ },
530
+ });
531
+ const ctx = createMockContext({ sessionId: 'validator-session' });
532
+
533
+ await validateTask(
534
+ {
535
+ task_id: VALID_UUID,
536
+ approved: true,
537
+ skip_pr_check: true,
538
+ },
539
+ ctx
540
+ );
541
+
542
+ expect(mockApiClient.validateTask).toHaveBeenCalledWith(
543
+ VALID_UUID,
544
+ { approved: true, skip_pr_check: true },
545
+ 'validator-session'
546
+ );
547
+ });
548
+ });
497
549
  });
@@ -8,14 +8,27 @@
8
8
  */
9
9
 
10
10
  import type { Handler, HandlerRegistry } from './types.js';
11
- import { validateRequired, validateUUID } from '../validators.js';
11
+ import { parseArgs, uuidValidator } from '../validators.js';
12
12
  import { getApiClient } from '../api-client.js';
13
13
 
14
- export const getTasksAwaitingValidation: Handler = async (args, ctx) => {
15
- const { project_id } = args as { project_id: string };
14
+ // Argument schemas for type-safe parsing
15
+ const getTasksAwaitingValidationSchema = {
16
+ project_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
17
+ };
18
+
19
+ const claimValidationSchema = {
20
+ task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
21
+ };
22
+
23
+ const validateTaskSchema = {
24
+ task_id: { type: 'string' as const, required: true as const, validate: uuidValidator },
25
+ approved: { type: 'boolean' as const, required: true as const },
26
+ validation_notes: { type: 'string' as const },
27
+ skip_pr_check: { type: 'boolean' as const },
28
+ };
16
29
 
17
- validateRequired(project_id, 'project_id');
18
- validateUUID(project_id, 'project_id');
30
+ export const getTasksAwaitingValidation: Handler = async (args, _ctx) => {
31
+ const { project_id } = parseArgs(args, getTasksAwaitingValidationSchema);
19
32
 
20
33
  const apiClient = getApiClient();
21
34
  const response = await apiClient.getTasksAwaitingValidation(project_id);
@@ -28,10 +41,7 @@ export const getTasksAwaitingValidation: Handler = async (args, ctx) => {
28
41
  };
29
42
 
30
43
  export const claimValidation: Handler = async (args, ctx) => {
31
- const { task_id } = args as { task_id: string };
32
-
33
- validateRequired(task_id, 'task_id');
34
- validateUUID(task_id, 'task_id');
44
+ const { task_id } = parseArgs(args, claimValidationSchema);
35
45
 
36
46
  const { session } = ctx;
37
47
  const currentSessionId = session.currentSessionId;
@@ -47,18 +57,7 @@ export const claimValidation: Handler = async (args, ctx) => {
47
57
  };
48
58
 
49
59
  export const validateTask: Handler = async (args, ctx) => {
50
- const { task_id, validation_notes, approved } = args as {
51
- task_id: string;
52
- validation_notes?: string;
53
- approved: boolean;
54
- };
55
-
56
- validateRequired(task_id, 'task_id');
57
- validateUUID(task_id, 'task_id');
58
-
59
- if (approved === undefined) {
60
- throw new Error('approved is required');
61
- }
60
+ const { task_id, approved, validation_notes, skip_pr_check } = parseArgs(args, validateTaskSchema);
62
61
 
63
62
  const { session } = ctx;
64
63
  const currentSessionId = session.currentSessionId;
@@ -67,9 +66,21 @@ export const validateTask: Handler = async (args, ctx) => {
67
66
  const response = await apiClient.validateTask(task_id, {
68
67
  approved,
69
68
  validation_notes,
69
+ skip_pr_check,
70
70
  }, currentSessionId || undefined);
71
71
 
72
72
  if (!response.ok) {
73
+ // Handle PR required error specially
74
+ if (response.error === 'pr_required') {
75
+ return {
76
+ result: {
77
+ error: 'pr_required',
78
+ message: response.data?.message || 'A Pull Request is required before validation approval. Create a PR and add it via add_task_reference.',
79
+ workflow: response.data?.workflow,
80
+ action_required: 'Create a PR for this task and add it via add_task_reference(task_id, pr_url, label: "Pull Request")',
81
+ },
82
+ };
83
+ }
73
84
  throw new Error(response.error || 'Failed to validate task');
74
85
  }
75
86
 
package/src/index.ts CHANGED
@@ -1052,8 +1052,8 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
1052
1052
  },
1053
1053
  task_type: {
1054
1054
  type: 'string',
1055
- enum: ['frontend', 'backend', 'database', 'mcp', 'testing', 'docs', 'infra', 'other'],
1056
- description: 'Task category for visual grouping (frontend, backend, database, mcp, testing, docs, infra, other)',
1055
+ enum: ['frontend', 'backend', 'database', 'feature', 'bugfix', 'design', 'mcp', 'testing', 'docs', 'infra', 'other'],
1056
+ description: 'Task category (frontend, backend, database, feature, bugfix, design, mcp, testing, docs, infra, other)',
1057
1057
  },
1058
1058
  },
1059
1059
  required: ['project_id', 'title'],
@@ -1101,8 +1101,8 @@ Returns session info, persona, and next task. Use mode:'full' for complete conte
1101
1101
  },
1102
1102
  task_type: {
1103
1103
  type: 'string',
1104
- enum: ['frontend', 'backend', 'database', 'mcp', 'testing', 'docs', 'infra', 'other'],
1105
- description: 'Task category (frontend, backend, database, mcp, testing, docs, infra, other)',
1104
+ enum: ['frontend', 'backend', 'database', 'feature', 'bugfix', 'design', 'mcp', 'testing', 'docs', 'infra', 'other'],
1105
+ description: 'Task category (frontend, backend, database, feature, bugfix, design, mcp, testing, docs, infra, other)',
1106
1106
  },
1107
1107
  },
1108
1108
  required: ['task_id'],
@@ -1817,6 +1817,10 @@ Returns subtasks with aggregate completion stats.`,
1817
1817
  type: 'string',
1818
1818
  description: 'Session ID from start_work_session (optional, uses current session if not provided)',
1819
1819
  },
1820
+ current_worktree_path: {
1821
+ type: ['string', 'null'],
1822
+ description: 'Report your current git worktree path (e.g., "../project-task-abc123"). Set to null to clear.',
1823
+ },
1820
1824
  },
1821
1825
  },
1822
1826
  },
@@ -1866,7 +1870,7 @@ Returns subtasks with aggregate completion stats.`,
1866
1870
  },
1867
1871
  {
1868
1872
  name: 'validate_task',
1869
- description: 'Validate a completed task. Include test results in validation_notes.',
1873
+ description: 'Validate a completed task. Include test results in validation_notes. For github-flow/git-flow projects, a PR must exist before approval (add via add_task_reference).',
1870
1874
  inputSchema: {
1871
1875
  type: 'object',
1872
1876
  properties: {
@@ -1882,6 +1886,10 @@ Returns subtasks with aggregate completion stats.`,
1882
1886
  type: 'boolean',
1883
1887
  description: 'Whether the task passes validation (true = approved, false = needs more work)',
1884
1888
  },
1889
+ skip_pr_check: {
1890
+ type: 'boolean',
1891
+ description: 'Skip PR existence check (use only for tasks that legitimately do not need a PR)',
1892
+ },
1885
1893
  },
1886
1894
  required: ['task_id', 'approved'],
1887
1895
  },
@@ -2589,7 +2597,8 @@ Bodies of work allow organizing related tasks with optional auto-deployment on c
2589
2597
  },
2590
2598
  {
2591
2599
  name: 'get_body_of_work',
2592
- description: `Get a body of work with all its tasks organized by phase.`,
2600
+ description: `Get a body of work with all its tasks organized by phase.
2601
+ Use summary_only: true to get task counts and next task instead of full task arrays (saves tokens).`,
2593
2602
  inputSchema: {
2594
2603
  type: 'object',
2595
2604
  properties: {
@@ -2597,6 +2606,10 @@ Bodies of work allow organizing related tasks with optional auto-deployment on c
2597
2606
  type: 'string',
2598
2607
  description: 'Body of work UUID',
2599
2608
  },
2609
+ summary_only: {
2610
+ type: 'boolean',
2611
+ description: 'Return task counts and next task instead of full task arrays (default: false)',
2612
+ },
2600
2613
  },
2601
2614
  required: ['body_of_work_id'],
2602
2615
  },
@@ -2872,7 +2885,8 @@ Sprints start in 'planning' status where tasks can be added with story points.`,
2872
2885
  {
2873
2886
  name: 'get_sprint',
2874
2887
  description: `Get a sprint with all its tasks organized by phase (pre/core/post).
2875
- Includes progress percentage, velocity points, and committed points.`,
2888
+ Includes progress percentage, velocity points, and committed points.
2889
+ Use summary_only: true to get task counts and next task instead of full task arrays (saves tokens).`,
2876
2890
  inputSchema: {
2877
2891
  type: 'object',
2878
2892
  properties: {
@@ -2880,6 +2894,10 @@ Includes progress percentage, velocity points, and committed points.`,
2880
2894
  type: 'string',
2881
2895
  description: 'Sprint UUID',
2882
2896
  },
2897
+ summary_only: {
2898
+ type: 'boolean',
2899
+ description: 'Return task counts and next task instead of full task arrays (default: false)',
2900
+ },
2883
2901
  },
2884
2902
  required: ['sprint_id'],
2885
2903
  },