@vibescope/mcp-server 0.2.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 (65) hide show
  1. package/dist/api-client.d.ts +64 -1
  2. package/dist/api-client.js +34 -3
  3. package/dist/handlers/bodies-of-work.js +82 -49
  4. package/dist/handlers/cost.js +62 -54
  5. package/dist/handlers/decisions.js +29 -16
  6. package/dist/handlers/deployment.js +112 -106
  7. package/dist/handlers/discovery.js +35 -5
  8. package/dist/handlers/fallback.js +24 -19
  9. package/dist/handlers/file-checkouts.d.ts +18 -0
  10. package/dist/handlers/file-checkouts.js +101 -0
  11. package/dist/handlers/findings.d.ts +6 -0
  12. package/dist/handlers/findings.js +85 -30
  13. package/dist/handlers/git-issues.js +36 -32
  14. package/dist/handlers/ideas.js +44 -26
  15. package/dist/handlers/index.d.ts +2 -0
  16. package/dist/handlers/index.js +6 -0
  17. package/dist/handlers/milestones.js +34 -27
  18. package/dist/handlers/organizations.js +86 -78
  19. package/dist/handlers/progress.js +22 -11
  20. package/dist/handlers/project.js +62 -22
  21. package/dist/handlers/requests.js +15 -11
  22. package/dist/handlers/roles.d.ts +18 -0
  23. package/dist/handlers/roles.js +130 -0
  24. package/dist/handlers/session.js +30 -8
  25. package/dist/handlers/sprints.js +76 -64
  26. package/dist/handlers/tasks.js +113 -73
  27. package/dist/handlers/validation.js +18 -14
  28. package/dist/tools.js +387 -0
  29. package/package.json +1 -1
  30. package/src/api-client.ts +89 -6
  31. package/src/handlers/__test-setup__.ts +7 -0
  32. package/src/handlers/bodies-of-work.ts +101 -101
  33. package/src/handlers/cost.test.ts +34 -44
  34. package/src/handlers/cost.ts +77 -92
  35. package/src/handlers/decisions.test.ts +3 -2
  36. package/src/handlers/decisions.ts +32 -27
  37. package/src/handlers/deployment.ts +142 -190
  38. package/src/handlers/discovery.test.ts +4 -5
  39. package/src/handlers/discovery.ts +37 -6
  40. package/src/handlers/fallback.ts +31 -29
  41. package/src/handlers/file-checkouts.test.ts +477 -0
  42. package/src/handlers/file-checkouts.ts +127 -0
  43. package/src/handlers/findings.test.ts +145 -0
  44. package/src/handlers/findings.ts +101 -64
  45. package/src/handlers/git-issues.ts +40 -80
  46. package/src/handlers/ideas.ts +56 -54
  47. package/src/handlers/index.ts +6 -0
  48. package/src/handlers/milestones.test.ts +1 -1
  49. package/src/handlers/milestones.ts +47 -45
  50. package/src/handlers/organizations.ts +104 -129
  51. package/src/handlers/progress.ts +24 -22
  52. package/src/handlers/project.ts +89 -57
  53. package/src/handlers/requests.ts +18 -14
  54. package/src/handlers/roles.test.ts +303 -0
  55. package/src/handlers/roles.ts +208 -0
  56. package/src/handlers/session.ts +39 -17
  57. package/src/handlers/sprints.ts +96 -129
  58. package/src/handlers/tasks.ts +144 -138
  59. package/src/handlers/validation.test.ts +1 -1
  60. package/src/handlers/validation.ts +20 -22
  61. package/src/tools.ts +387 -0
  62. package/dist/config/tool-categories.d.ts +0 -31
  63. package/dist/config/tool-categories.js +0 -253
  64. package/dist/knowledge.d.ts +0 -6
  65. package/dist/knowledge.js +0 -218
@@ -13,21 +13,103 @@
13
13
  * - complete_deployment_requirement
14
14
  * - get_deployment_requirements
15
15
  */
16
- import { ValidationError, validateRequired, validateUUID, validateEnvironment, } from '../validators.js';
16
+ import { ValidationError, parseArgs, uuidValidator, createEnumValidator, } from '../validators.js';
17
17
  import { getApiClient } from '../api-client.js';
18
+ const ENVIRONMENTS = ['development', 'staging', 'production'];
19
+ const VERSION_BUMPS = ['patch', 'minor', 'major'];
20
+ const REQUIREMENT_TYPES = ['migration', 'env_var', 'config', 'manual', 'breaking_change', 'agent_task'];
21
+ const REQUIREMENT_STAGES = ['preparation', 'deployment', 'verification'];
22
+ const REQUIREMENT_STATUSES = ['pending', 'completed', 'converted_to_task', 'all'];
23
+ const SCHEDULE_TYPES = ['once', 'daily', 'weekly', 'monthly'];
24
+ // ============================================================================
25
+ // Argument Schemas
26
+ // ============================================================================
27
+ const requestDeploymentSchema = {
28
+ project_id: { type: 'string', required: true, validate: uuidValidator },
29
+ environment: { type: 'string', default: 'production', validate: createEnumValidator(ENVIRONMENTS) },
30
+ version_bump: { type: 'string', default: 'patch', validate: createEnumValidator(VERSION_BUMPS) },
31
+ notes: { type: 'string' },
32
+ git_ref: { type: 'string' },
33
+ };
34
+ const claimDeploymentValidationSchema = {
35
+ project_id: { type: 'string', required: true, validate: uuidValidator },
36
+ };
37
+ const reportValidationSchema = {
38
+ project_id: { type: 'string', required: true, validate: uuidValidator },
39
+ build_passed: { type: 'boolean', required: true },
40
+ tests_passed: { type: 'boolean' },
41
+ error_message: { type: 'string' },
42
+ };
43
+ const checkDeploymentStatusSchema = {
44
+ project_id: { type: 'string', required: true, validate: uuidValidator },
45
+ };
46
+ const startDeploymentSchema = {
47
+ project_id: { type: 'string', required: true, validate: uuidValidator },
48
+ };
49
+ const completeDeploymentSchema = {
50
+ project_id: { type: 'string', required: true, validate: uuidValidator },
51
+ success: { type: 'boolean', required: true },
52
+ summary: { type: 'string' },
53
+ };
54
+ const cancelDeploymentSchema = {
55
+ project_id: { type: 'string', required: true, validate: uuidValidator },
56
+ reason: { type: 'string' },
57
+ };
58
+ const addDeploymentRequirementSchema = {
59
+ project_id: { type: 'string', required: true, validate: uuidValidator },
60
+ type: { type: 'string', required: true, validate: createEnumValidator(REQUIREMENT_TYPES) },
61
+ title: { type: 'string', required: true },
62
+ description: { type: 'string' },
63
+ file_path: { type: 'string' },
64
+ stage: { type: 'string', default: 'preparation', validate: createEnumValidator(REQUIREMENT_STAGES) },
65
+ blocking: { type: 'boolean', default: false },
66
+ recurring: { type: 'boolean', default: false },
67
+ };
68
+ const completeDeploymentRequirementSchema = {
69
+ requirement_id: { type: 'string', required: true, validate: uuidValidator },
70
+ };
71
+ const getDeploymentRequirementsSchema = {
72
+ project_id: { type: 'string', required: true, validate: uuidValidator },
73
+ status: { type: 'string', default: 'pending', validate: createEnumValidator(REQUIREMENT_STATUSES) },
74
+ stage: { type: 'string', validate: createEnumValidator([...REQUIREMENT_STAGES, 'all']) },
75
+ };
76
+ const scheduleDeploymentSchema = {
77
+ project_id: { type: 'string', required: true, validate: uuidValidator },
78
+ environment: { type: 'string', default: 'production', validate: createEnumValidator(ENVIRONMENTS) },
79
+ version_bump: { type: 'string', default: 'patch', validate: createEnumValidator(VERSION_BUMPS) },
80
+ schedule_type: { type: 'string', default: 'once', validate: createEnumValidator(SCHEDULE_TYPES) },
81
+ scheduled_at: { type: 'string', required: true },
82
+ auto_trigger: { type: 'boolean', default: true },
83
+ notes: { type: 'string' },
84
+ git_ref: { type: 'string' },
85
+ };
86
+ const getScheduledDeploymentsSchema = {
87
+ project_id: { type: 'string', required: true, validate: uuidValidator },
88
+ include_disabled: { type: 'boolean', default: false },
89
+ };
90
+ const updateScheduledDeploymentSchema = {
91
+ schedule_id: { type: 'string', required: true, validate: uuidValidator },
92
+ environment: { type: 'string', validate: createEnumValidator(ENVIRONMENTS) },
93
+ version_bump: { type: 'string', validate: createEnumValidator(VERSION_BUMPS) },
94
+ schedule_type: { type: 'string', validate: createEnumValidator(SCHEDULE_TYPES) },
95
+ scheduled_at: { type: 'string' },
96
+ auto_trigger: { type: 'boolean' },
97
+ enabled: { type: 'boolean' },
98
+ notes: { type: 'string' },
99
+ git_ref: { type: 'string' },
100
+ };
101
+ const deleteScheduledDeploymentSchema = {
102
+ schedule_id: { type: 'string', required: true, validate: uuidValidator },
103
+ };
104
+ const triggerScheduledDeploymentSchema = {
105
+ schedule_id: { type: 'string', required: true, validate: uuidValidator },
106
+ };
107
+ const checkDueDeploymentsSchema = {
108
+ project_id: { type: 'string', required: true, validate: uuidValidator },
109
+ };
18
110
  export const requestDeployment = async (args, ctx) => {
19
- const { project_id, environment = 'production', version_bump = 'patch', notes, git_ref } = args;
111
+ const { project_id, environment, version_bump, notes, git_ref } = parseArgs(args, requestDeploymentSchema);
20
112
  const { session } = ctx;
21
- validateRequired(project_id, 'project_id');
22
- validateUUID(project_id, 'project_id');
23
- validateEnvironment(environment);
24
- if (version_bump && !['patch', 'minor', 'major'].includes(version_bump)) {
25
- throw new ValidationError('Invalid version_bump value', {
26
- field: 'version_bump',
27
- validValues: ['patch', 'minor', 'major'],
28
- hint: 'Must be one of: patch, minor, major',
29
- });
30
- }
31
113
  const apiClient = getApiClient();
32
114
  const response = await apiClient.requestDeployment(project_id, {
33
115
  environment,
@@ -41,10 +123,8 @@ export const requestDeployment = async (args, ctx) => {
41
123
  return { result: response.data };
42
124
  };
43
125
  export const claimDeploymentValidation = async (args, ctx) => {
44
- const { project_id } = args;
126
+ const { project_id } = parseArgs(args, claimDeploymentValidationSchema);
45
127
  const { session } = ctx;
46
- validateRequired(project_id, 'project_id');
47
- validateUUID(project_id, 'project_id');
48
128
  const apiClient = getApiClient();
49
129
  const response = await apiClient.claimDeploymentValidation(project_id, session.currentSessionId || undefined);
50
130
  if (!response.ok) {
@@ -53,16 +133,8 @@ export const claimDeploymentValidation = async (args, ctx) => {
53
133
  return { result: response.data };
54
134
  };
55
135
  export const reportValidation = async (args, ctx) => {
56
- const { project_id, build_passed, tests_passed, error_message } = args;
136
+ const { project_id, build_passed, tests_passed, error_message } = parseArgs(args, reportValidationSchema);
57
137
  const { session } = ctx;
58
- validateRequired(project_id, 'project_id');
59
- validateUUID(project_id, 'project_id');
60
- if (build_passed === undefined) {
61
- throw new ValidationError('build_passed is required', {
62
- field: 'build_passed',
63
- hint: 'Set to true if the build succeeded, false otherwise',
64
- });
65
- }
66
138
  const apiClient = getApiClient();
67
139
  const response = await apiClient.reportValidation(project_id, {
68
140
  build_passed,
@@ -75,9 +147,7 @@ export const reportValidation = async (args, ctx) => {
75
147
  return { result: response.data };
76
148
  };
77
149
  export const checkDeploymentStatus = async (args, ctx) => {
78
- const { project_id } = args;
79
- validateRequired(project_id, 'project_id');
80
- validateUUID(project_id, 'project_id');
150
+ const { project_id } = parseArgs(args, checkDeploymentStatusSchema);
81
151
  const apiClient = getApiClient();
82
152
  const response = await apiClient.checkDeploymentStatus(project_id);
83
153
  if (!response.ok) {
@@ -86,10 +156,8 @@ export const checkDeploymentStatus = async (args, ctx) => {
86
156
  return { result: response.data };
87
157
  };
88
158
  export const startDeployment = async (args, ctx) => {
89
- const { project_id } = args;
159
+ const { project_id } = parseArgs(args, startDeploymentSchema);
90
160
  const { session } = ctx;
91
- validateRequired(project_id, 'project_id');
92
- validateUUID(project_id, 'project_id');
93
161
  const apiClient = getApiClient();
94
162
  const response = await apiClient.startDeployment(project_id, session.currentSessionId || undefined);
95
163
  if (!response.ok) {
@@ -98,16 +166,8 @@ export const startDeployment = async (args, ctx) => {
98
166
  return { result: response.data };
99
167
  };
100
168
  export const completeDeployment = async (args, ctx) => {
101
- const { project_id, success, summary } = args;
169
+ const { project_id, success, summary } = parseArgs(args, completeDeploymentSchema);
102
170
  const { session } = ctx;
103
- validateRequired(project_id, 'project_id');
104
- validateUUID(project_id, 'project_id');
105
- if (success === undefined) {
106
- throw new ValidationError('success is required', {
107
- field: 'success',
108
- hint: 'Set to true if deployment succeeded, false otherwise',
109
- });
110
- }
111
171
  const apiClient = getApiClient();
112
172
  const response = await apiClient.completeDeployment(project_id, {
113
173
  success,
@@ -119,9 +179,7 @@ export const completeDeployment = async (args, ctx) => {
119
179
  return { result: response.data };
120
180
  };
121
181
  export const cancelDeployment = async (args, ctx) => {
122
- const { project_id, reason } = args;
123
- validateRequired(project_id, 'project_id');
124
- validateUUID(project_id, 'project_id');
182
+ const { project_id, reason } = parseArgs(args, cancelDeploymentSchema);
125
183
  const apiClient = getApiClient();
126
184
  const response = await apiClient.cancelDeployment(project_id, reason);
127
185
  if (!response.ok) {
@@ -130,19 +188,7 @@ export const cancelDeployment = async (args, ctx) => {
130
188
  return { result: response.data };
131
189
  };
132
190
  export const addDeploymentRequirement = async (args, ctx) => {
133
- const { project_id, type, title, description, file_path, stage = 'preparation', blocking = false, recurring = false } = args;
134
- validateRequired(project_id, 'project_id');
135
- validateUUID(project_id, 'project_id');
136
- validateRequired(type, 'type');
137
- validateRequired(title, 'title');
138
- const validTypes = ['migration', 'env_var', 'config', 'manual', 'breaking_change', 'agent_task'];
139
- if (!validTypes.includes(type)) {
140
- throw new ValidationError(`type must be one of: ${validTypes.join(', ')}`);
141
- }
142
- const validStages = ['preparation', 'deployment', 'verification'];
143
- if (!validStages.includes(stage)) {
144
- throw new ValidationError(`stage must be one of: ${validStages.join(', ')}`);
145
- }
191
+ const { project_id, type, title, description, file_path, stage, blocking, recurring } = parseArgs(args, addDeploymentRequirementSchema);
146
192
  const apiClient = getApiClient();
147
193
  const response = await apiClient.addDeploymentRequirement(project_id, {
148
194
  type: type,
@@ -159,9 +205,7 @@ export const addDeploymentRequirement = async (args, ctx) => {
159
205
  return { result: response.data };
160
206
  };
161
207
  export const completeDeploymentRequirement = async (args, ctx) => {
162
- const { requirement_id } = args;
163
- validateRequired(requirement_id, 'requirement_id');
164
- validateUUID(requirement_id, 'requirement_id');
208
+ const { requirement_id } = parseArgs(args, completeDeploymentRequirementSchema);
165
209
  const apiClient = getApiClient();
166
210
  const response = await apiClient.completeDeploymentRequirement(requirement_id);
167
211
  if (!response.ok) {
@@ -170,9 +214,7 @@ export const completeDeploymentRequirement = async (args, ctx) => {
170
214
  return { result: response.data };
171
215
  };
172
216
  export const getDeploymentRequirements = async (args, ctx) => {
173
- const { project_id, status = 'pending', stage } = args;
174
- validateRequired(project_id, 'project_id');
175
- validateUUID(project_id, 'project_id');
217
+ const { project_id, status, stage } = parseArgs(args, getDeploymentRequirementsSchema);
176
218
  const apiClient = getApiClient();
177
219
  const response = await apiClient.getDeploymentRequirements(project_id, {
178
220
  status: status,
@@ -187,23 +229,7 @@ export const getDeploymentRequirements = async (args, ctx) => {
187
229
  // Scheduled Deployments
188
230
  // ============================================================================
189
231
  export const scheduleDeployment = async (args, ctx) => {
190
- const { project_id, environment = 'production', version_bump = 'patch', schedule_type = 'once', scheduled_at, auto_trigger = true, notes, git_ref, } = args;
191
- validateRequired(project_id, 'project_id');
192
- validateUUID(project_id, 'project_id');
193
- validateRequired(scheduled_at, 'scheduled_at');
194
- validateEnvironment(environment);
195
- if (!['patch', 'minor', 'major'].includes(version_bump)) {
196
- throw new ValidationError('Invalid version_bump value', {
197
- field: 'version_bump',
198
- validValues: ['patch', 'minor', 'major'],
199
- });
200
- }
201
- if (!['once', 'daily', 'weekly', 'monthly'].includes(schedule_type)) {
202
- throw new ValidationError('Invalid schedule_type value', {
203
- field: 'schedule_type',
204
- validValues: ['once', 'daily', 'weekly', 'monthly'],
205
- });
206
- }
232
+ const { project_id, environment, version_bump, schedule_type, scheduled_at, auto_trigger, notes, git_ref, } = parseArgs(args, scheduleDeploymentSchema);
207
233
  // Parse and validate scheduled_at
208
234
  const scheduledDate = new Date(scheduled_at);
209
235
  if (isNaN(scheduledDate.getTime())) {
@@ -233,9 +259,7 @@ export const scheduleDeployment = async (args, ctx) => {
233
259
  return { result: response.data };
234
260
  };
235
261
  export const getScheduledDeployments = async (args, ctx) => {
236
- const { project_id, include_disabled = false } = args;
237
- validateRequired(project_id, 'project_id');
238
- validateUUID(project_id, 'project_id');
262
+ const { project_id, include_disabled } = parseArgs(args, getScheduledDeploymentsSchema);
239
263
  const apiClient = getApiClient();
240
264
  const response = await apiClient.getScheduledDeployments(project_id, include_disabled);
241
265
  if (!response.ok) {
@@ -244,26 +268,14 @@ export const getScheduledDeployments = async (args, ctx) => {
244
268
  return { result: response.data };
245
269
  };
246
270
  export const updateScheduledDeployment = async (args, ctx) => {
247
- const { schedule_id, environment, version_bump, schedule_type, scheduled_at, auto_trigger, enabled, notes, git_ref, } = args;
248
- validateRequired(schedule_id, 'schedule_id');
249
- validateUUID(schedule_id, 'schedule_id');
271
+ const { schedule_id, environment, version_bump, schedule_type, scheduled_at, auto_trigger, enabled, notes, git_ref, } = parseArgs(args, updateScheduledDeploymentSchema);
250
272
  const updates = {};
251
- if (environment !== undefined) {
252
- validateEnvironment(environment);
273
+ if (environment !== undefined)
253
274
  updates.environment = environment;
254
- }
255
- if (version_bump !== undefined) {
256
- if (!['patch', 'minor', 'major'].includes(version_bump)) {
257
- throw new ValidationError('Invalid version_bump value');
258
- }
275
+ if (version_bump !== undefined)
259
276
  updates.version_bump = version_bump;
260
- }
261
- if (schedule_type !== undefined) {
262
- if (!['once', 'daily', 'weekly', 'monthly'].includes(schedule_type)) {
263
- throw new ValidationError('Invalid schedule_type value');
264
- }
277
+ if (schedule_type !== undefined)
265
278
  updates.schedule_type = schedule_type;
266
- }
267
279
  if (scheduled_at !== undefined) {
268
280
  const scheduledDate = new Date(scheduled_at);
269
281
  if (isNaN(scheduledDate.getTime())) {
@@ -290,9 +302,7 @@ export const updateScheduledDeployment = async (args, ctx) => {
290
302
  return { result: response.data };
291
303
  };
292
304
  export const deleteScheduledDeployment = async (args, ctx) => {
293
- const { schedule_id } = args;
294
- validateRequired(schedule_id, 'schedule_id');
295
- validateUUID(schedule_id, 'schedule_id');
305
+ const { schedule_id } = parseArgs(args, deleteScheduledDeploymentSchema);
296
306
  const apiClient = getApiClient();
297
307
  const response = await apiClient.deleteScheduledDeployment(schedule_id);
298
308
  if (!response.ok) {
@@ -301,10 +311,8 @@ export const deleteScheduledDeployment = async (args, ctx) => {
301
311
  return { result: response.data };
302
312
  };
303
313
  export const triggerScheduledDeployment = async (args, ctx) => {
304
- const { schedule_id } = args;
314
+ const { schedule_id } = parseArgs(args, triggerScheduledDeploymentSchema);
305
315
  const { session } = ctx;
306
- validateRequired(schedule_id, 'schedule_id');
307
- validateUUID(schedule_id, 'schedule_id');
308
316
  const apiClient = getApiClient();
309
317
  const response = await apiClient.triggerScheduledDeployment(schedule_id, session.currentSessionId || undefined);
310
318
  if (!response.ok) {
@@ -313,9 +321,7 @@ export const triggerScheduledDeployment = async (args, ctx) => {
313
321
  return { result: response.data };
314
322
  };
315
323
  export const checkDueDeployments = async (args, ctx) => {
316
- const { project_id } = args;
317
- validateRequired(project_id, 'project_id');
318
- validateUUID(project_id, 'project_id');
324
+ const { project_id } = parseArgs(args, checkDueDeploymentsSchema);
319
325
  const apiClient = getApiClient();
320
326
  const response = await apiClient.checkDueDeployments(project_id);
321
327
  if (!response.ok) {
@@ -8,6 +8,14 @@
8
8
  * Note: Tool documentation is lazy-loaded from tool-docs.ts to save tokens.
9
9
  * This saves ~8,000 tokens per schema load.
10
10
  */
11
+ import { parseArgs } from '../validators.js';
12
+ // Argument schemas for type-safe parsing
13
+ const discoverToolsSchema = {
14
+ category: { type: 'string' },
15
+ };
16
+ const getToolInfoSchema = {
17
+ tool_name: { type: 'string', required: true },
18
+ };
11
19
  // Lazy-loaded tool documentation cache
12
20
  let toolInfoCache = null;
13
21
  /**
@@ -163,6 +171,22 @@ const TOOL_CATEGORIES = {
163
171
  { name: 'activate_body_of_work', brief: 'Activate for work' },
164
172
  ],
165
173
  },
174
+ sprints: {
175
+ description: 'Time-bounded sprints with velocity tracking',
176
+ tools: [
177
+ { name: 'create_sprint', brief: 'Create new sprint' },
178
+ { name: 'update_sprint', brief: 'Update sprint details' },
179
+ { name: 'get_sprint', brief: 'Get sprint with tasks' },
180
+ { name: 'get_sprints', brief: 'List project sprints' },
181
+ { name: 'delete_sprint', brief: 'Delete sprint' },
182
+ { name: 'start_sprint', brief: 'Start sprint' },
183
+ { name: 'complete_sprint', brief: 'Complete sprint' },
184
+ { name: 'add_task_to_sprint', brief: 'Add task to sprint' },
185
+ { name: 'remove_task_from_sprint', brief: 'Remove from sprint' },
186
+ { name: 'get_sprint_backlog', brief: 'Get available tasks' },
187
+ { name: 'get_sprint_velocity', brief: 'Velocity metrics' },
188
+ ],
189
+ },
166
190
  requests: {
167
191
  description: 'User request handling',
168
192
  tools: [
@@ -200,6 +224,15 @@ const TOOL_CATEGORIES = {
200
224
  { name: 'get_task_costs', brief: 'Cost per task' },
201
225
  ],
202
226
  },
227
+ git_issues: {
228
+ description: 'Git conflict and issue tracking',
229
+ tools: [
230
+ { name: 'add_git_issue', brief: 'Record git issue' },
231
+ { name: 'resolve_git_issue', brief: 'Mark resolved' },
232
+ { name: 'get_git_issues', brief: 'List git issues' },
233
+ { name: 'delete_git_issue', brief: 'Delete git issue' },
234
+ ],
235
+ },
203
236
  knowledge: {
204
237
  description: 'Queryable knowledge base from project data',
205
238
  tools: [
@@ -208,7 +241,7 @@ const TOOL_CATEGORIES = {
208
241
  },
209
242
  };
210
243
  export const discoverTools = async (args) => {
211
- const { category } = args;
244
+ const { category } = parseArgs(args, discoverToolsSchema);
212
245
  if (category) {
213
246
  // Return tools in specific category
214
247
  const cat = TOOL_CATEGORIES[category];
@@ -243,10 +276,7 @@ export const discoverTools = async (args) => {
243
276
  };
244
277
  };
245
278
  export const getToolInfo = async (args) => {
246
- const { tool_name } = args;
247
- if (!tool_name) {
248
- return { result: { error: 'tool_name is required' } };
249
- }
279
+ const { tool_name } = parseArgs(args, getToolInfoSchema);
250
280
  // Lazy-load tool documentation
251
281
  const toolDocs = await getToolDocs();
252
282
  const info = toolDocs[tool_name];
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * MIGRATED: Uses Vibescope API client instead of direct Supabase
11
11
  */
12
- import { validateRequired, validateUUID } from '../validators.js';
12
+ import { parseArgs, uuidValidator, createEnumValidator } from '../validators.js';
13
13
  import { FALLBACK_ACTIVITIES } from '../utils.js';
14
14
  import { getApiClient } from '../api-client.js';
15
15
  const VALID_ACTIVITIES = [
@@ -24,14 +24,25 @@ const VALID_ACTIVITIES = [
24
24
  'dependency_audit',
25
25
  'validate_completed_tasks',
26
26
  ];
27
+ // Argument schemas for type-safe parsing
28
+ const startFallbackActivitySchema = {
29
+ project_id: { type: 'string', required: true, validate: uuidValidator },
30
+ activity: { type: 'string', required: true, validate: createEnumValidator(VALID_ACTIVITIES) },
31
+ };
32
+ const stopFallbackActivitySchema = {
33
+ project_id: { type: 'string', required: true, validate: uuidValidator },
34
+ summary: { type: 'string' },
35
+ };
36
+ const getActivityHistorySchema = {
37
+ project_id: { type: 'string', required: true, validate: uuidValidator },
38
+ activity_type: { type: 'string' },
39
+ limit: { type: 'number', default: 50 },
40
+ };
41
+ const getActivitySchedulesSchema = {
42
+ project_id: { type: 'string', required: true, validate: uuidValidator },
43
+ };
27
44
  export const startFallbackActivity = async (args, ctx) => {
28
- const { project_id, activity } = args;
29
- validateRequired(project_id, 'project_id');
30
- validateUUID(project_id, 'project_id');
31
- validateRequired(activity, 'activity');
32
- if (!VALID_ACTIVITIES.includes(activity)) {
33
- throw new Error(`Invalid activity. Must be one of: ${VALID_ACTIVITIES.join(', ')}`);
34
- }
45
+ const { project_id, activity } = parseArgs(args, startFallbackActivitySchema);
35
46
  const { session } = ctx;
36
47
  const apiClient = getApiClient();
37
48
  const response = await apiClient.startFallbackActivity(project_id, activity, session.currentSessionId || undefined);
@@ -61,9 +72,7 @@ export const startFallbackActivity = async (args, ctx) => {
61
72
  return { result };
62
73
  };
63
74
  export const stopFallbackActivity = async (args, ctx) => {
64
- const { project_id, summary } = args;
65
- validateRequired(project_id, 'project_id');
66
- validateUUID(project_id, 'project_id');
75
+ const { project_id, summary } = parseArgs(args, stopFallbackActivitySchema);
67
76
  const { session } = ctx;
68
77
  const apiClient = getApiClient();
69
78
  const response = await apiClient.stopFallbackActivity(project_id, summary, session.currentSessionId || undefined);
@@ -77,10 +86,8 @@ export const stopFallbackActivity = async (args, ctx) => {
77
86
  },
78
87
  };
79
88
  };
80
- export const getActivityHistory = async (args, ctx) => {
81
- const { project_id, activity_type, limit = 50 } = args;
82
- validateRequired(project_id, 'project_id');
83
- validateUUID(project_id, 'project_id');
89
+ export const getActivityHistory = async (args, _ctx) => {
90
+ const { project_id, activity_type, limit } = parseArgs(args, getActivityHistorySchema);
84
91
  const apiClient = getApiClient();
85
92
  // Use proxy for get_activity_history operation
86
93
  const response = await apiClient.proxy('get_activity_history', {
@@ -99,10 +106,8 @@ export const getActivityHistory = async (args, ctx) => {
99
106
  },
100
107
  };
101
108
  };
102
- export const getActivitySchedules = async (args, ctx) => {
103
- const { project_id } = args;
104
- validateRequired(project_id, 'project_id');
105
- validateUUID(project_id, 'project_id');
109
+ export const getActivitySchedules = async (args, _ctx) => {
110
+ const { project_id } = parseArgs(args, getActivitySchedulesSchema);
106
111
  const apiClient = getApiClient();
107
112
  // Use proxy for get_activity_schedules operation
108
113
  const response = await apiClient.proxy('get_activity_schedules', {
@@ -0,0 +1,18 @@
1
+ /**
2
+ * File Checkouts Handlers
3
+ *
4
+ * Handles file checkout/checkin for multi-agent coordination:
5
+ * - checkout_file: Check out a file before editing
6
+ * - checkin_file: Check in a file after editing
7
+ * - get_file_checkouts: Get active checkouts for a project
8
+ * - abandon_checkout: Force release a checkout
9
+ */
10
+ import type { Handler, HandlerRegistry } from './types.js';
11
+ export declare const checkoutFile: Handler;
12
+ export declare const checkinFile: Handler;
13
+ export declare const getFileCheckouts: Handler;
14
+ export declare const abandonCheckout: Handler;
15
+ /**
16
+ * File Checkouts handlers registry
17
+ */
18
+ export declare const fileCheckoutHandlers: HandlerRegistry;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * File Checkouts Handlers
3
+ *
4
+ * Handles file checkout/checkin for multi-agent coordination:
5
+ * - checkout_file: Check out a file before editing
6
+ * - checkin_file: Check in a file after editing
7
+ * - get_file_checkouts: Get active checkouts for a project
8
+ * - abandon_checkout: Force release a checkout
9
+ */
10
+ import { parseArgs, uuidValidator, createEnumValidator } from '../validators.js';
11
+ import { getApiClient } from '../api-client.js';
12
+ const VALID_CHECKOUT_STATUSES = ['checked_out', 'checked_in', 'abandoned'];
13
+ // Argument schemas for type-safe parsing
14
+ const checkoutFileSchema = {
15
+ project_id: { type: 'string', required: true, validate: uuidValidator },
16
+ file_path: { type: 'string', required: true },
17
+ reason: { type: 'string' },
18
+ };
19
+ const checkinFileSchema = {
20
+ checkout_id: { type: 'string', validate: uuidValidator },
21
+ project_id: { type: 'string', validate: uuidValidator },
22
+ file_path: { type: 'string' },
23
+ summary: { type: 'string' },
24
+ };
25
+ const getFileCheckoutsSchema = {
26
+ project_id: { type: 'string', required: true, validate: uuidValidator },
27
+ status: { type: 'string', validate: createEnumValidator(VALID_CHECKOUT_STATUSES) },
28
+ file_path: { type: 'string' },
29
+ limit: { type: 'number', default: 50 },
30
+ };
31
+ const abandonCheckoutSchema = {
32
+ checkout_id: { type: 'string', validate: uuidValidator },
33
+ project_id: { type: 'string', validate: uuidValidator },
34
+ file_path: { type: 'string' },
35
+ };
36
+ export const checkoutFile = async (args, ctx) => {
37
+ const { project_id, file_path, reason } = parseArgs(args, checkoutFileSchema);
38
+ const apiClient = getApiClient();
39
+ const response = await apiClient.checkoutFile(project_id, file_path, reason, ctx.session.currentSessionId || undefined);
40
+ if (!response.ok) {
41
+ throw new Error(response.error || 'Failed to checkout file');
42
+ }
43
+ return { result: response.data };
44
+ };
45
+ export const checkinFile = async (args, ctx) => {
46
+ const { checkout_id, project_id, file_path, summary } = parseArgs(args, checkinFileSchema);
47
+ // Validate that either checkout_id or both project_id and file_path are provided
48
+ if (!checkout_id && (!project_id || !file_path)) {
49
+ throw new Error('Either checkout_id or both project_id and file_path are required');
50
+ }
51
+ const apiClient = getApiClient();
52
+ const response = await apiClient.checkinFile({
53
+ checkout_id,
54
+ project_id,
55
+ file_path,
56
+ summary
57
+ }, ctx.session.currentSessionId || undefined);
58
+ if (!response.ok) {
59
+ throw new Error(response.error || 'Failed to checkin file');
60
+ }
61
+ return { result: response.data };
62
+ };
63
+ export const getFileCheckouts = async (args, _ctx) => {
64
+ const { project_id, status, file_path, limit } = parseArgs(args, getFileCheckoutsSchema);
65
+ const apiClient = getApiClient();
66
+ const response = await apiClient.getFileCheckouts(project_id, {
67
+ status,
68
+ file_path,
69
+ limit
70
+ });
71
+ if (!response.ok) {
72
+ throw new Error(response.error || 'Failed to get file checkouts');
73
+ }
74
+ return { result: response.data };
75
+ };
76
+ export const abandonCheckout = async (args, _ctx) => {
77
+ const { checkout_id, project_id, file_path } = parseArgs(args, abandonCheckoutSchema);
78
+ // Validate that either checkout_id or both project_id and file_path are provided
79
+ if (!checkout_id && (!project_id || !file_path)) {
80
+ throw new Error('Either checkout_id or both project_id and file_path are required');
81
+ }
82
+ const apiClient = getApiClient();
83
+ const response = await apiClient.abandonCheckout({
84
+ checkout_id,
85
+ project_id,
86
+ file_path
87
+ });
88
+ if (!response.ok) {
89
+ throw new Error(response.error || 'Failed to abandon checkout');
90
+ }
91
+ return { result: response.data };
92
+ };
93
+ /**
94
+ * File Checkouts handlers registry
95
+ */
96
+ export const fileCheckoutHandlers = {
97
+ checkout_file: checkoutFile,
98
+ checkin_file: checkinFile,
99
+ get_file_checkouts: getFileCheckouts,
100
+ abandon_checkout: abandonCheckout,
101
+ };
@@ -19,6 +19,12 @@ export declare const getFindings: Handler;
19
19
  export declare const getFindingsStats: Handler;
20
20
  export declare const updateFinding: Handler;
21
21
  export declare const deleteFinding: Handler;
22
+ /**
23
+ * Query aggregated project knowledge in a single call.
24
+ * Returns findings, Q&A, decisions, completed tasks, and resolved blockers.
25
+ * Use this instead of multiple separate tool calls to reduce token usage.
26
+ */
27
+ export declare const queryKnowledgeBase: Handler;
22
28
  /**
23
29
  * Findings handlers registry
24
30
  */