@vibescope/mcp-server 0.0.1 → 0.2.0

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 (173) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1169 -0
  3. package/dist/api-client.js +713 -0
  4. package/dist/cli.d.ts +1 -6
  5. package/dist/cli.js +39 -240
  6. package/dist/config/tool-categories.d.ts +31 -0
  7. package/dist/config/tool-categories.js +253 -0
  8. package/dist/handlers/blockers.js +57 -58
  9. package/dist/handlers/bodies-of-work.d.ts +2 -0
  10. package/dist/handlers/bodies-of-work.js +108 -477
  11. package/dist/handlers/cost.d.ts +1 -0
  12. package/dist/handlers/cost.js +35 -113
  13. package/dist/handlers/decisions.d.ts +2 -0
  14. package/dist/handlers/decisions.js +28 -27
  15. package/dist/handlers/deployment.js +113 -828
  16. package/dist/handlers/discovery.d.ts +3 -0
  17. package/dist/handlers/discovery.js +26 -627
  18. package/dist/handlers/fallback.d.ts +2 -0
  19. package/dist/handlers/fallback.js +56 -142
  20. package/dist/handlers/findings.d.ts +8 -1
  21. package/dist/handlers/findings.js +65 -68
  22. package/dist/handlers/git-issues.d.ts +9 -13
  23. package/dist/handlers/git-issues.js +80 -225
  24. package/dist/handlers/ideas.d.ts +3 -0
  25. package/dist/handlers/ideas.js +53 -134
  26. package/dist/handlers/index.d.ts +2 -0
  27. package/dist/handlers/index.js +6 -0
  28. package/dist/handlers/milestones.d.ts +2 -0
  29. package/dist/handlers/milestones.js +51 -98
  30. package/dist/handlers/organizations.js +79 -275
  31. package/dist/handlers/progress.d.ts +2 -0
  32. package/dist/handlers/progress.js +25 -123
  33. package/dist/handlers/project.js +42 -221
  34. package/dist/handlers/requests.d.ts +2 -0
  35. package/dist/handlers/requests.js +23 -83
  36. package/dist/handlers/session.js +119 -590
  37. package/dist/handlers/sprints.d.ts +32 -0
  38. package/dist/handlers/sprints.js +275 -0
  39. package/dist/handlers/tasks.d.ts +7 -10
  40. package/dist/handlers/tasks.js +245 -894
  41. package/dist/handlers/tool-docs.d.ts +9 -0
  42. package/dist/handlers/tool-docs.js +904 -0
  43. package/dist/handlers/types.d.ts +11 -3
  44. package/dist/handlers/validation.d.ts +1 -1
  45. package/dist/handlers/validation.js +38 -153
  46. package/dist/index.js +493 -162
  47. package/dist/knowledge.js +106 -9
  48. package/dist/tools.js +34 -4
  49. package/dist/validators.d.ts +21 -0
  50. package/dist/validators.js +91 -0
  51. package/package.json +2 -3
  52. package/src/api-client.ts +1822 -0
  53. package/src/cli.test.ts +128 -302
  54. package/src/cli.ts +41 -285
  55. package/src/handlers/__test-setup__.ts +215 -0
  56. package/src/handlers/__test-utils__.ts +4 -134
  57. package/src/handlers/blockers.test.ts +114 -124
  58. package/src/handlers/blockers.ts +68 -70
  59. package/src/handlers/bodies-of-work.test.ts +236 -831
  60. package/src/handlers/bodies-of-work.ts +210 -525
  61. package/src/handlers/cost.test.ts +149 -113
  62. package/src/handlers/cost.ts +44 -132
  63. package/src/handlers/decisions.test.ts +111 -209
  64. package/src/handlers/decisions.ts +35 -27
  65. package/src/handlers/deployment.test.ts +193 -239
  66. package/src/handlers/deployment.ts +143 -896
  67. package/src/handlers/discovery.test.ts +20 -67
  68. package/src/handlers/discovery.ts +29 -714
  69. package/src/handlers/fallback.test.ts +206 -361
  70. package/src/handlers/fallback.ts +81 -156
  71. package/src/handlers/findings.test.ts +229 -320
  72. package/src/handlers/findings.ts +76 -64
  73. package/src/handlers/git-issues.test.ts +623 -0
  74. package/src/handlers/git-issues.ts +174 -0
  75. package/src/handlers/ideas.test.ts +229 -343
  76. package/src/handlers/ideas.ts +69 -143
  77. package/src/handlers/index.ts +6 -0
  78. package/src/handlers/milestones.test.ts +167 -281
  79. package/src/handlers/milestones.ts +54 -93
  80. package/src/handlers/organizations.test.ts +275 -467
  81. package/src/handlers/organizations.ts +84 -294
  82. package/src/handlers/progress.test.ts +112 -218
  83. package/src/handlers/progress.ts +29 -142
  84. package/src/handlers/project.test.ts +203 -226
  85. package/src/handlers/project.ts +48 -238
  86. package/src/handlers/requests.test.ts +74 -342
  87. package/src/handlers/requests.ts +25 -83
  88. package/src/handlers/session.test.ts +276 -206
  89. package/src/handlers/session.ts +136 -662
  90. package/src/handlers/sprints.test.ts +711 -0
  91. package/src/handlers/sprints.ts +510 -0
  92. package/src/handlers/tasks.test.ts +669 -353
  93. package/src/handlers/tasks.ts +263 -1015
  94. package/src/handlers/tool-docs.ts +1024 -0
  95. package/src/handlers/types.ts +12 -4
  96. package/src/handlers/validation.test.ts +237 -568
  97. package/src/handlers/validation.ts +43 -167
  98. package/src/index.ts +493 -186
  99. package/src/tools.ts +2532 -0
  100. package/src/validators.test.ts +223 -223
  101. package/src/validators.ts +127 -0
  102. package/tsconfig.json +1 -1
  103. package/vitest.config.ts +14 -13
  104. package/dist/cli.test.d.ts +0 -1
  105. package/dist/cli.test.js +0 -367
  106. package/dist/handlers/__test-utils__.d.ts +0 -72
  107. package/dist/handlers/__test-utils__.js +0 -176
  108. package/dist/handlers/checkouts.d.ts +0 -37
  109. package/dist/handlers/checkouts.js +0 -377
  110. package/dist/handlers/knowledge-query.d.ts +0 -22
  111. package/dist/handlers/knowledge-query.js +0 -253
  112. package/dist/handlers/knowledge.d.ts +0 -12
  113. package/dist/handlers/knowledge.js +0 -108
  114. package/dist/handlers/roles.d.ts +0 -30
  115. package/dist/handlers/roles.js +0 -281
  116. package/dist/handlers/tasks.test.d.ts +0 -1
  117. package/dist/handlers/tasks.test.js +0 -431
  118. package/dist/utils.test.d.ts +0 -1
  119. package/dist/utils.test.js +0 -532
  120. package/dist/validators.test.d.ts +0 -1
  121. package/dist/validators.test.js +0 -176
  122. package/src/knowledge.ts +0 -132
  123. package/src/tmpclaude-0078-cwd +0 -1
  124. package/src/tmpclaude-0ee1-cwd +0 -1
  125. package/src/tmpclaude-2dd5-cwd +0 -1
  126. package/src/tmpclaude-344c-cwd +0 -1
  127. package/src/tmpclaude-3860-cwd +0 -1
  128. package/src/tmpclaude-4b63-cwd +0 -1
  129. package/src/tmpclaude-5c73-cwd +0 -1
  130. package/src/tmpclaude-5ee3-cwd +0 -1
  131. package/src/tmpclaude-6795-cwd +0 -1
  132. package/src/tmpclaude-709e-cwd +0 -1
  133. package/src/tmpclaude-9839-cwd +0 -1
  134. package/src/tmpclaude-d829-cwd +0 -1
  135. package/src/tmpclaude-e072-cwd +0 -1
  136. package/src/tmpclaude-f6ee-cwd +0 -1
  137. package/tmpclaude-0439-cwd +0 -1
  138. package/tmpclaude-132f-cwd +0 -1
  139. package/tmpclaude-15bb-cwd +0 -1
  140. package/tmpclaude-165a-cwd +0 -1
  141. package/tmpclaude-1ba9-cwd +0 -1
  142. package/tmpclaude-21a3-cwd +0 -1
  143. package/tmpclaude-2a38-cwd +0 -1
  144. package/tmpclaude-2adf-cwd +0 -1
  145. package/tmpclaude-2f56-cwd +0 -1
  146. package/tmpclaude-3626-cwd +0 -1
  147. package/tmpclaude-3727-cwd +0 -1
  148. package/tmpclaude-40bc-cwd +0 -1
  149. package/tmpclaude-436f-cwd +0 -1
  150. package/tmpclaude-4783-cwd +0 -1
  151. package/tmpclaude-4b6d-cwd +0 -1
  152. package/tmpclaude-4ba4-cwd +0 -1
  153. package/tmpclaude-51e6-cwd +0 -1
  154. package/tmpclaude-5ecf-cwd +0 -1
  155. package/tmpclaude-6f97-cwd +0 -1
  156. package/tmpclaude-7fb2-cwd +0 -1
  157. package/tmpclaude-825c-cwd +0 -1
  158. package/tmpclaude-8baf-cwd +0 -1
  159. package/tmpclaude-8d9f-cwd +0 -1
  160. package/tmpclaude-975c-cwd +0 -1
  161. package/tmpclaude-9983-cwd +0 -1
  162. package/tmpclaude-a045-cwd +0 -1
  163. package/tmpclaude-ac4a-cwd +0 -1
  164. package/tmpclaude-b593-cwd +0 -1
  165. package/tmpclaude-b891-cwd +0 -1
  166. package/tmpclaude-c032-cwd +0 -1
  167. package/tmpclaude-cf43-cwd +0 -1
  168. package/tmpclaude-d040-cwd +0 -1
  169. package/tmpclaude-dcdd-cwd +0 -1
  170. package/tmpclaude-dcee-cwd +0 -1
  171. package/tmpclaude-e16b-cwd +0 -1
  172. package/tmpclaude-ecd2-cwd +0 -1
  173. package/tmpclaude-f48d-cwd +0 -1
@@ -0,0 +1,1822 @@
1
+ /**
2
+ * Vibescope API Client
3
+ *
4
+ * HTTP client for communicating with the Vibescope API.
5
+ * All database operations are handled server-side through these endpoints.
6
+ */
7
+
8
+ const DEFAULT_API_URL = 'https://vibescope.dev';
9
+
10
+ interface ApiClientConfig {
11
+ apiKey: string;
12
+ baseUrl?: string;
13
+ }
14
+
15
+ interface ApiResponse<T> {
16
+ ok: boolean;
17
+ status: number;
18
+ data?: T;
19
+ error?: string;
20
+ }
21
+
22
+ export class VibescopeApiClient {
23
+ private apiKey: string;
24
+ private baseUrl: string;
25
+
26
+ constructor(config: ApiClientConfig) {
27
+ this.apiKey = config.apiKey;
28
+ this.baseUrl = config.baseUrl || process.env.VIBESCOPE_API_URL || DEFAULT_API_URL;
29
+ }
30
+
31
+ private async request<T>(method: string, path: string, body?: unknown): Promise<ApiResponse<T>> {
32
+ const url = `${this.baseUrl}${path}`;
33
+
34
+ try {
35
+ const response = await fetch(url, {
36
+ method,
37
+ headers: {
38
+ 'Content-Type': 'application/json',
39
+ 'X-API-Key': this.apiKey
40
+ },
41
+ body: body ? JSON.stringify(body) : undefined
42
+ });
43
+
44
+ const data = await response.json();
45
+
46
+ if (!response.ok) {
47
+ return {
48
+ ok: false,
49
+ status: response.status,
50
+ error: data.error || `HTTP ${response.status}`
51
+ };
52
+ }
53
+
54
+ return {
55
+ ok: true,
56
+ status: response.status,
57
+ data
58
+ };
59
+ } catch (err) {
60
+ return {
61
+ ok: false,
62
+ status: 0,
63
+ error: err instanceof Error ? err.message : 'Network error'
64
+ };
65
+ }
66
+ }
67
+
68
+ // Auth endpoints
69
+ async validateAuth(): Promise<ApiResponse<{
70
+ valid: boolean;
71
+ user_id: string;
72
+ api_key_id: string;
73
+ key_name: string;
74
+ }>> {
75
+ return this.request('POST', '/api/mcp/auth/validate', {
76
+ api_key: this.apiKey
77
+ });
78
+ }
79
+
80
+ // Session endpoints
81
+ async startSession(params: {
82
+ project_id?: string;
83
+ git_url?: string;
84
+ mode?: 'lite' | 'full';
85
+ model?: 'opus' | 'sonnet' | 'haiku';
86
+ role?: 'developer' | 'validator' | 'deployer' | 'reviewer' | 'maintainer';
87
+ }): Promise<ApiResponse<{
88
+ session_started: boolean;
89
+ session_id?: string;
90
+ persona?: string;
91
+ role?: string;
92
+ project?: {
93
+ id: string;
94
+ name: string;
95
+ description?: string;
96
+ goal?: string;
97
+ status?: string;
98
+ git_url?: string;
99
+ agent_instructions?: string;
100
+ tech_stack?: string[];
101
+ git_workflow?: string;
102
+ git_main_branch?: string;
103
+ git_develop_branch?: string;
104
+ git_auto_branch?: boolean;
105
+ };
106
+ active_tasks?: Array<{
107
+ id: string;
108
+ title: string;
109
+ status: string;
110
+ priority: number;
111
+ progress_percentage?: number;
112
+ estimated_minutes?: number;
113
+ }>;
114
+ blockers?: Array<{
115
+ id: string;
116
+ description: string;
117
+ status: string;
118
+ }>;
119
+ next_task?: {
120
+ id: string;
121
+ title: string;
122
+ priority: number;
123
+ estimated_minutes?: number;
124
+ } | null;
125
+ directive?: string;
126
+ blockers_count?: number;
127
+ validation_count?: number;
128
+ project_not_found?: boolean;
129
+ message?: string;
130
+ suggestion?: {
131
+ action: string;
132
+ example: string;
133
+ note: string;
134
+ };
135
+ error?: string;
136
+ }>> {
137
+ return this.request('POST', '/api/mcp/sessions/start', params);
138
+ }
139
+
140
+ async heartbeat(sessionId: string, options?: {
141
+ current_worktree_path?: string | null;
142
+ }): Promise<ApiResponse<{
143
+ success: boolean;
144
+ session_id: string;
145
+ timestamp: string;
146
+ }>> {
147
+ return this.request('POST', '/api/mcp/sessions/heartbeat', {
148
+ session_id: sessionId,
149
+ ...options
150
+ });
151
+ }
152
+
153
+ async endSession(sessionId: string): Promise<ApiResponse<{
154
+ success: boolean;
155
+ ended_session_id?: string;
156
+ session_summary?: {
157
+ agent_name: string;
158
+ tasks_completed_this_session: number;
159
+ tasks_awaiting_validation: number;
160
+ tasks_released: number;
161
+ };
162
+ reminders?: string[];
163
+ }>> {
164
+ return this.request('POST', '/api/mcp/sessions/end', {
165
+ session_id: sessionId
166
+ });
167
+ }
168
+
169
+ // Project endpoints
170
+ async listProjects(): Promise<ApiResponse<{
171
+ projects: Array<{
172
+ id: string;
173
+ name: string;
174
+ description?: string;
175
+ status: string;
176
+ git_url?: string;
177
+ goal?: string;
178
+ tech_stack?: string[];
179
+ }>;
180
+ }>> {
181
+ return this.request('GET', '/api/mcp/projects');
182
+ }
183
+
184
+ async createProject(params: {
185
+ name: string;
186
+ description?: string;
187
+ goal?: string;
188
+ git_url?: string;
189
+ tech_stack?: string[];
190
+ }): Promise<ApiResponse<{
191
+ success: boolean;
192
+ project: {
193
+ id: string;
194
+ name: string;
195
+ };
196
+ }>> {
197
+ return this.request('POST', '/api/mcp/projects', params);
198
+ }
199
+
200
+ async getProject(projectId: string, gitUrl?: string): Promise<ApiResponse<{
201
+ found: boolean;
202
+ project?: {
203
+ id: string;
204
+ name: string;
205
+ description?: string;
206
+ goal?: string;
207
+ status: string;
208
+ git_url?: string;
209
+ agent_instructions?: string;
210
+ tech_stack?: string[];
211
+ git_workflow?: string;
212
+ git_main_branch?: string;
213
+ git_develop_branch?: string;
214
+ git_auto_branch?: boolean;
215
+ git_auto_tag?: boolean;
216
+ deployment_instructions?: string;
217
+ };
218
+ active_tasks?: Array<{
219
+ id: string;
220
+ title: string;
221
+ description?: string;
222
+ priority: number;
223
+ status: string;
224
+ progress_percentage?: number;
225
+ estimated_minutes?: number;
226
+ }>;
227
+ open_blockers?: Array<{
228
+ id: string;
229
+ description: string;
230
+ }>;
231
+ recent_decisions?: Array<{
232
+ id: string;
233
+ title: string;
234
+ description?: string;
235
+ }>;
236
+ message?: string;
237
+ }>> {
238
+ const url = gitUrl
239
+ ? `/api/mcp/projects/${projectId}?git_url=${encodeURIComponent(gitUrl)}`
240
+ : `/api/mcp/projects/${projectId}`;
241
+ return this.request('GET', url);
242
+ }
243
+
244
+ async updateProject(projectId: string, updates: {
245
+ name?: string;
246
+ description?: string;
247
+ goal?: string;
248
+ git_url?: string;
249
+ tech_stack?: string[];
250
+ status?: string;
251
+ git_workflow?: string;
252
+ git_main_branch?: string;
253
+ git_develop_branch?: string;
254
+ git_auto_branch?: boolean;
255
+ git_auto_tag?: boolean;
256
+ deployment_instructions?: string;
257
+ agent_instructions?: string;
258
+ }): Promise<ApiResponse<{
259
+ success: boolean;
260
+ project_id: string;
261
+ }>> {
262
+ return this.request('PATCH', `/api/mcp/projects/${projectId}`, updates);
263
+ }
264
+
265
+ // Task endpoints
266
+ async getTasks(projectId: string, params?: {
267
+ status?: string;
268
+ limit?: number;
269
+ offset?: number;
270
+ include_subtasks?: boolean;
271
+ search_query?: string;
272
+ include_metadata?: boolean; // When true, returns all task fields; when false (default), only id/title/priority/status
273
+ }): Promise<ApiResponse<{
274
+ tasks: Array<{
275
+ id: string;
276
+ title: string;
277
+ description?: string;
278
+ priority: number;
279
+ status: string;
280
+ progress_percentage?: number;
281
+ estimated_minutes?: number;
282
+ started_at?: string;
283
+ completed_at?: string;
284
+ parent_task_id?: string;
285
+ }>;
286
+ total_count: number;
287
+ has_more: boolean;
288
+ }>> {
289
+ const queryParams = new URLSearchParams();
290
+ if (params?.status) queryParams.set('status', params.status);
291
+ if (params?.limit) queryParams.set('limit', params.limit.toString());
292
+ if (params?.offset) queryParams.set('offset', params.offset.toString());
293
+ if (params?.include_subtasks) queryParams.set('include_subtasks', 'true');
294
+ if (params?.search_query) queryParams.set('search_query', params.search_query);
295
+ if (params?.include_metadata) queryParams.set('include_metadata', 'true');
296
+
297
+ const query = queryParams.toString();
298
+ const url = `/api/mcp/projects/${projectId}/tasks${query ? `?${query}` : ''}`;
299
+ return this.request('GET', url);
300
+ }
301
+
302
+ async createTask(projectId: string, params: {
303
+ title: string;
304
+ description?: string;
305
+ priority?: number;
306
+ estimated_minutes?: number;
307
+ blocking?: boolean;
308
+ session_id?: string;
309
+ }): Promise<ApiResponse<{
310
+ success: boolean;
311
+ task_id: string;
312
+ title: string;
313
+ blocking?: boolean;
314
+ message?: string;
315
+ }>> {
316
+ return this.request('POST', `/api/mcp/projects/${projectId}/tasks`, params);
317
+ }
318
+
319
+ async getNextTask(projectId: string, sessionId?: string): Promise<ApiResponse<{
320
+ task?: {
321
+ id: string;
322
+ title: string;
323
+ description?: string;
324
+ priority: number;
325
+ estimated_minutes?: number;
326
+ blocking?: boolean;
327
+ } | null;
328
+ blocking_task?: boolean;
329
+ deployment_blocks_tasks?: boolean;
330
+ deployment?: {
331
+ id: string;
332
+ status: string;
333
+ env: string;
334
+ };
335
+ awaiting_validation?: Array<{
336
+ id: string;
337
+ title: string;
338
+ }>;
339
+ validation_priority?: string;
340
+ all_claimed?: boolean;
341
+ is_subtask?: boolean;
342
+ suggested_activity?: string;
343
+ directive?: string;
344
+ message?: string;
345
+ action?: string;
346
+ }>> {
347
+ const url = sessionId
348
+ ? `/api/mcp/projects/${projectId}/next-task?session_id=${sessionId}`
349
+ : `/api/mcp/projects/${projectId}/next-task`;
350
+ return this.request('GET', url);
351
+ }
352
+
353
+ async getTask(taskId: string): Promise<ApiResponse<{
354
+ task: {
355
+ id: string;
356
+ title: string;
357
+ description?: string;
358
+ priority: number;
359
+ status: string;
360
+ progress_percentage?: number;
361
+ estimated_minutes?: number;
362
+ started_at?: string;
363
+ completed_at?: string;
364
+ git_branch?: string;
365
+ blocking?: boolean;
366
+ references?: Array<{ url: string; label?: string }>;
367
+ parent_task_id?: string;
368
+ working_agent_session_id?: string;
369
+ };
370
+ }>> {
371
+ return this.request('GET', `/api/mcp/tasks/${taskId}`);
372
+ }
373
+
374
+ async updateTask(taskId: string, updates: {
375
+ title?: string;
376
+ description?: string;
377
+ priority?: number;
378
+ status?: string;
379
+ progress_percentage?: number;
380
+ progress_note?: string;
381
+ estimated_minutes?: number;
382
+ git_branch?: string;
383
+ session_id?: string;
384
+ }): Promise<ApiResponse<{
385
+ success: boolean;
386
+ task_id: string;
387
+ git_workflow?: {
388
+ workflow: string;
389
+ base_branch: string;
390
+ suggested_branch: string;
391
+ worktree_required: boolean;
392
+ };
393
+ worktree_setup?: {
394
+ message: string;
395
+ commands: string[];
396
+ worktree_path: string;
397
+ branch_name: string;
398
+ cleanup_command: string;
399
+ };
400
+ next_step?: string;
401
+ }>> {
402
+ return this.request('PATCH', `/api/mcp/tasks/${taskId}`, updates);
403
+ }
404
+
405
+ async completeTask(taskId: string, params: {
406
+ summary?: string;
407
+ session_id?: string;
408
+ }): Promise<ApiResponse<{
409
+ success: boolean;
410
+ directive: string;
411
+ auto_continue: boolean;
412
+ completed_task_id: string;
413
+ next_task?: {
414
+ id: string;
415
+ title: string;
416
+ priority: number;
417
+ estimated_minutes?: number;
418
+ } | null;
419
+ context?: {
420
+ validation?: number;
421
+ blockers?: number;
422
+ deployment?: string;
423
+ };
424
+ next_action: string;
425
+ warnings?: string[];
426
+ }>> {
427
+ return this.request('POST', `/api/mcp/tasks/${taskId}/complete`, params);
428
+ }
429
+
430
+ async deleteTask(taskId: string): Promise<ApiResponse<{
431
+ success: boolean;
432
+ deleted_id: string;
433
+ }>> {
434
+ return this.request('DELETE', `/api/mcp/tasks/${taskId}`);
435
+ }
436
+
437
+ // Progress endpoints
438
+ async logProgress(projectId: string, params: {
439
+ summary: string;
440
+ details?: string;
441
+ task_id?: string;
442
+ session_id?: string;
443
+ }): Promise<ApiResponse<{
444
+ success: boolean;
445
+ progress_id: string;
446
+ }>> {
447
+ return this.request('POST', `/api/mcp/projects/${projectId}/progress`, params);
448
+ }
449
+
450
+ // Git workflow endpoint
451
+ async getGitWorkflow(projectId: string, taskId?: string): Promise<ApiResponse<{
452
+ workflow: string;
453
+ main_branch: string;
454
+ develop_branch?: string | null;
455
+ auto_branch?: boolean;
456
+ auto_tag?: boolean;
457
+ instructions: string[];
458
+ task?: {
459
+ id: string;
460
+ title: string;
461
+ current_branch?: string;
462
+ suggested_branch?: string | null;
463
+ };
464
+ }>> {
465
+ const url = taskId
466
+ ? `/api/mcp/projects/${projectId}/git-workflow?task_id=${taskId}`
467
+ : `/api/mcp/projects/${projectId}/git-workflow`;
468
+ return this.request('GET', url);
469
+ }
470
+
471
+ // ============================================================================
472
+ // Proxy endpoint - Generic method for all operations
473
+ // ============================================================================
474
+ async proxy<T>(operation: string, args: Record<string, unknown>, sessionContext?: {
475
+ session_id: string | null;
476
+ persona: string | null;
477
+ instance_id: string;
478
+ }): Promise<ApiResponse<T>> {
479
+ return this.request('POST', '/api/mcp/proxy', {
480
+ operation,
481
+ args,
482
+ session_context: sessionContext
483
+ });
484
+ }
485
+
486
+ // ============================================================================
487
+ // Blocker endpoints
488
+ // ============================================================================
489
+ async getBlockers(projectId: string, params?: {
490
+ status?: string;
491
+ limit?: number;
492
+ offset?: number;
493
+ search_query?: string;
494
+ }): Promise<ApiResponse<{
495
+ blockers: Array<{
496
+ id: string;
497
+ description: string;
498
+ status: string;
499
+ resolution_note?: string;
500
+ created_at: string;
501
+ resolved_at?: string;
502
+ }>;
503
+ total_count?: number;
504
+ has_more?: boolean;
505
+ }>> {
506
+ return this.proxy('get_blockers', {
507
+ project_id: projectId,
508
+ ...params
509
+ });
510
+ }
511
+
512
+ async addBlocker(projectId: string, description: string, sessionId?: string): Promise<ApiResponse<{
513
+ success: boolean;
514
+ blocker_id: string;
515
+ }>> {
516
+ return this.proxy('add_blocker', { project_id: projectId, description }, sessionId ? {
517
+ session_id: sessionId,
518
+ persona: null,
519
+ instance_id: ''
520
+ } : undefined);
521
+ }
522
+
523
+ async resolveBlocker(blockerId: string, resolutionNote?: string): Promise<ApiResponse<{
524
+ success: boolean;
525
+ blocker_id: string;
526
+ }>> {
527
+ return this.proxy('resolve_blocker', {
528
+ blocker_id: blockerId,
529
+ resolution_note: resolutionNote
530
+ });
531
+ }
532
+
533
+ async deleteBlocker(blockerId: string): Promise<ApiResponse<{
534
+ success: boolean;
535
+ }>> {
536
+ return this.proxy('delete_blocker', { blocker_id: blockerId });
537
+ }
538
+
539
+ // ============================================================================
540
+ // Decision endpoints
541
+ // ============================================================================
542
+ async getDecisions(projectId: string): Promise<ApiResponse<{
543
+ decisions: Array<{
544
+ id: string;
545
+ title: string;
546
+ description: string;
547
+ rationale?: string;
548
+ alternatives_considered?: string[];
549
+ created_at: string;
550
+ }>;
551
+ }>> {
552
+ return this.proxy('get_decisions', { project_id: projectId });
553
+ }
554
+
555
+ async logDecision(projectId: string, params: {
556
+ title: string;
557
+ description: string;
558
+ rationale?: string;
559
+ alternatives_considered?: string[];
560
+ }, sessionId?: string): Promise<ApiResponse<{
561
+ success: boolean;
562
+ decision_id: string;
563
+ }>> {
564
+ return this.proxy('log_decision', {
565
+ project_id: projectId,
566
+ ...params
567
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
568
+ }
569
+
570
+ async deleteDecision(decisionId: string): Promise<ApiResponse<{
571
+ success: boolean;
572
+ }>> {
573
+ return this.proxy('delete_decision', { decision_id: decisionId });
574
+ }
575
+
576
+ // ============================================================================
577
+ // Idea endpoints
578
+ // ============================================================================
579
+ async getIdeas(projectId: string, params?: {
580
+ status?: string;
581
+ limit?: number;
582
+ offset?: number;
583
+ search_query?: string;
584
+ }): Promise<ApiResponse<{
585
+ ideas: Array<{
586
+ id: string;
587
+ title: string;
588
+ description?: string;
589
+ status: string;
590
+ doc_url?: string;
591
+ created_at: string;
592
+ }>;
593
+ }>> {
594
+ return this.proxy('get_ideas', {
595
+ project_id: projectId,
596
+ ...params
597
+ });
598
+ }
599
+
600
+ async addIdea(projectId: string, params: {
601
+ title: string;
602
+ description?: string;
603
+ status?: string;
604
+ }, sessionId?: string): Promise<ApiResponse<{
605
+ success: boolean;
606
+ idea_id: string;
607
+ }>> {
608
+ return this.proxy('add_idea', {
609
+ project_id: projectId,
610
+ ...params
611
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
612
+ }
613
+
614
+ async updateIdea(ideaId: string, updates: {
615
+ title?: string;
616
+ description?: string;
617
+ status?: string;
618
+ doc_url?: string;
619
+ }): Promise<ApiResponse<{
620
+ success: boolean;
621
+ idea_id: string;
622
+ }>> {
623
+ return this.proxy('update_idea', {
624
+ idea_id: ideaId,
625
+ ...updates
626
+ });
627
+ }
628
+
629
+ async deleteIdea(ideaId: string): Promise<ApiResponse<{
630
+ success: boolean;
631
+ }>> {
632
+ return this.proxy('delete_idea', { idea_id: ideaId });
633
+ }
634
+
635
+ async convertIdeaToTask(ideaId: string, params?: {
636
+ priority?: number;
637
+ estimated_minutes?: number;
638
+ update_status?: boolean;
639
+ }): Promise<ApiResponse<{
640
+ success: boolean;
641
+ task_id?: string;
642
+ task_title?: string;
643
+ idea_id?: string;
644
+ idea_status?: string;
645
+ message?: string;
646
+ error?: string;
647
+ existing_task_id?: string;
648
+ }>> {
649
+ return this.proxy('convert_idea_to_task', {
650
+ idea_id: ideaId,
651
+ ...params
652
+ });
653
+ }
654
+
655
+ // ============================================================================
656
+ // Finding endpoints
657
+ // ============================================================================
658
+ async getFindings(projectId: string, params?: {
659
+ category?: string;
660
+ severity?: string;
661
+ status?: string;
662
+ limit?: number;
663
+ offset?: number;
664
+ search_query?: string;
665
+ summary_only?: boolean;
666
+ }): Promise<ApiResponse<{
667
+ findings: Array<{
668
+ id: string;
669
+ title: string;
670
+ description?: string;
671
+ category: string;
672
+ severity: string;
673
+ status: string;
674
+ file_path?: string;
675
+ line_number?: number;
676
+ resolution_note?: string;
677
+ created_at: string;
678
+ }>;
679
+ total_count?: number;
680
+ has_more?: boolean;
681
+ }>> {
682
+ return this.proxy('get_findings', {
683
+ project_id: projectId,
684
+ ...params
685
+ });
686
+ }
687
+
688
+ async getFindingsStats(projectId: string): Promise<ApiResponse<{
689
+ total: number;
690
+ by_status: Record<string, number>;
691
+ by_severity: Record<string, number>;
692
+ by_category: Record<string, number>;
693
+ }>> {
694
+ return this.proxy('get_findings_stats', {
695
+ project_id: projectId
696
+ });
697
+ }
698
+
699
+ async addFinding(projectId: string, params: {
700
+ title: string;
701
+ description?: string;
702
+ category?: string;
703
+ severity?: string;
704
+ file_path?: string;
705
+ line_number?: number;
706
+ related_task_id?: string;
707
+ }, sessionId?: string): Promise<ApiResponse<{
708
+ success: boolean;
709
+ finding_id: string;
710
+ }>> {
711
+ return this.proxy('add_finding', {
712
+ project_id: projectId,
713
+ ...params
714
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
715
+ }
716
+
717
+ async updateFinding(findingId: string, updates: {
718
+ title?: string;
719
+ description?: string;
720
+ severity?: string;
721
+ status?: string;
722
+ resolution_note?: string;
723
+ }): Promise<ApiResponse<{
724
+ success: boolean;
725
+ finding_id: string;
726
+ }>> {
727
+ return this.proxy('update_finding', {
728
+ finding_id: findingId,
729
+ ...updates
730
+ });
731
+ }
732
+
733
+ async deleteFinding(findingId: string): Promise<ApiResponse<{
734
+ success: boolean;
735
+ }>> {
736
+ return this.proxy('delete_finding', { finding_id: findingId });
737
+ }
738
+
739
+ // ============================================================================
740
+ // Milestone endpoints
741
+ // ============================================================================
742
+ async getMilestones(taskId: string): Promise<ApiResponse<{
743
+ milestones: Array<{
744
+ id: string;
745
+ title: string;
746
+ description?: string;
747
+ status: string;
748
+ order_index: number;
749
+ created_at: string;
750
+ completed_at?: string;
751
+ }>;
752
+ stats: {
753
+ total: number;
754
+ completed: number;
755
+ progress_percentage: number;
756
+ };
757
+ }>> {
758
+ return this.proxy('get_milestones', { task_id: taskId });
759
+ }
760
+
761
+ async addMilestone(taskId: string, params: {
762
+ title: string;
763
+ description?: string;
764
+ order_index?: number;
765
+ }, sessionId?: string): Promise<ApiResponse<{
766
+ success: boolean;
767
+ milestone_id: string;
768
+ }>> {
769
+ return this.proxy('add_milestone', {
770
+ task_id: taskId,
771
+ ...params
772
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
773
+ }
774
+
775
+ async updateMilestone(milestoneId: string, updates: {
776
+ title?: string;
777
+ description?: string;
778
+ status?: string;
779
+ order_index?: number;
780
+ }): Promise<ApiResponse<{
781
+ success: boolean;
782
+ milestone: {
783
+ id: string;
784
+ title: string;
785
+ status: string;
786
+ };
787
+ }>> {
788
+ return this.proxy('update_milestone', {
789
+ milestone_id: milestoneId,
790
+ ...updates
791
+ });
792
+ }
793
+
794
+ async completeMilestone(milestoneId: string): Promise<ApiResponse<{
795
+ success: boolean;
796
+ milestone: {
797
+ id: string;
798
+ title: string;
799
+ status: string;
800
+ };
801
+ }>> {
802
+ return this.proxy('complete_milestone', { milestone_id: milestoneId });
803
+ }
804
+
805
+ async deleteMilestone(milestoneId: string): Promise<ApiResponse<{
806
+ success: boolean;
807
+ }>> {
808
+ return this.proxy('delete_milestone', { milestone_id: milestoneId });
809
+ }
810
+
811
+ // ============================================================================
812
+ // Request endpoints
813
+ // ============================================================================
814
+ async getPendingRequests(projectId: string, sessionId?: string): Promise<ApiResponse<{
815
+ requests: Array<{
816
+ id: string;
817
+ request_type: string;
818
+ message: string;
819
+ created_at: string;
820
+ }>;
821
+ }>> {
822
+ return this.proxy('get_pending_requests', { project_id: projectId }, sessionId ? {
823
+ session_id: sessionId,
824
+ persona: null,
825
+ instance_id: ''
826
+ } : undefined);
827
+ }
828
+
829
+ async acknowledgeRequest(requestId: string, sessionId?: string): Promise<ApiResponse<{
830
+ success: boolean;
831
+ }>> {
832
+ return this.proxy('acknowledge_request', { request_id: requestId }, sessionId ? {
833
+ session_id: sessionId,
834
+ persona: null,
835
+ instance_id: ''
836
+ } : undefined);
837
+ }
838
+
839
+ async answerQuestion(requestId: string, answer: string, sessionId?: string): Promise<ApiResponse<{
840
+ success: boolean;
841
+ }>> {
842
+ return this.proxy('answer_question', {
843
+ request_id: requestId,
844
+ answer
845
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
846
+ }
847
+
848
+ // ============================================================================
849
+ // Validation endpoints
850
+ // ============================================================================
851
+ async getTasksAwaitingValidation(projectId: string): Promise<ApiResponse<{
852
+ tasks: Array<{
853
+ id: string;
854
+ title: string;
855
+ completed_at?: string;
856
+ completed_by_session_id?: string;
857
+ }>;
858
+ }>> {
859
+ return this.proxy('get_tasks_awaiting_validation', { project_id: projectId });
860
+ }
861
+
862
+ async claimValidation(taskId: string, sessionId?: string): Promise<ApiResponse<{
863
+ success: boolean;
864
+ task_id: string;
865
+ }>> {
866
+ return this.proxy('claim_validation', { task_id: taskId }, sessionId ? {
867
+ session_id: sessionId,
868
+ persona: null,
869
+ instance_id: ''
870
+ } : undefined);
871
+ }
872
+
873
+ async validateTask(taskId: string, params: {
874
+ approved: boolean;
875
+ validation_notes?: string;
876
+ skip_pr_check?: boolean;
877
+ }, sessionId?: string): Promise<ApiResponse<{
878
+ success: boolean;
879
+ approved: boolean;
880
+ task_id: string;
881
+ message?: string;
882
+ workflow?: string;
883
+ }>> {
884
+ return this.proxy('validate_task', {
885
+ task_id: taskId,
886
+ ...params
887
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
888
+ }
889
+
890
+ // ============================================================================
891
+ // Fallback activity endpoints
892
+ // ============================================================================
893
+ async startFallbackActivity(projectId: string, activity: string, sessionId?: string): Promise<ApiResponse<{
894
+ success: boolean;
895
+ activity: string;
896
+ message: string;
897
+ git_workflow?: {
898
+ workflow: string;
899
+ base_branch: string;
900
+ worktree_recommended: boolean;
901
+ note: string;
902
+ };
903
+ worktree_setup?: {
904
+ message: string;
905
+ commands: string[];
906
+ worktree_path: string;
907
+ branch_name: string;
908
+ cleanup_command: string;
909
+ report_worktree: string;
910
+ };
911
+ next_step?: string;
912
+ }>> {
913
+ return this.proxy('start_fallback_activity', {
914
+ project_id: projectId,
915
+ activity
916
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
917
+ }
918
+
919
+ async stopFallbackActivity(projectId: string, summary?: string, sessionId?: string): Promise<ApiResponse<{
920
+ success: boolean;
921
+ }>> {
922
+ return this.proxy('stop_fallback_activity', {
923
+ project_id: projectId,
924
+ summary
925
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
926
+ }
927
+
928
+ async getActivityHistory(projectId: string, params?: {
929
+ activity_type?: string;
930
+ limit?: number;
931
+ }): Promise<ApiResponse<{
932
+ history: Array<{
933
+ id: string;
934
+ activity_type: string;
935
+ completed_at: string;
936
+ summary?: string;
937
+ }>;
938
+ latest_by_type: Record<string, unknown>;
939
+ count: number;
940
+ }>> {
941
+ return this.proxy('get_activity_history', {
942
+ project_id: projectId,
943
+ ...params
944
+ });
945
+ }
946
+
947
+ async getActivitySchedules(projectId: string): Promise<ApiResponse<{
948
+ schedules: Array<{
949
+ id: string;
950
+ activity_type: string;
951
+ schedule_type: string;
952
+ next_run_at?: string;
953
+ enabled: boolean;
954
+ }>;
955
+ due_activities: string[];
956
+ count: number;
957
+ }>> {
958
+ return this.proxy('get_activity_schedules', { project_id: projectId });
959
+ }
960
+
961
+ // ============================================================================
962
+ // Subtask endpoints
963
+ // ============================================================================
964
+ async addSubtask(parentTaskId: string, params: {
965
+ title: string;
966
+ description?: string;
967
+ priority?: number;
968
+ estimated_minutes?: number;
969
+ }, sessionId?: string): Promise<ApiResponse<{
970
+ success: boolean;
971
+ subtask_id: string;
972
+ parent_task_id: string;
973
+ }>> {
974
+ return this.proxy('add_subtask', {
975
+ parent_task_id: parentTaskId,
976
+ ...params
977
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
978
+ }
979
+
980
+ async getSubtasks(parentTaskId: string, status?: string): Promise<ApiResponse<{
981
+ subtasks: Array<{
982
+ id: string;
983
+ title: string;
984
+ description?: string;
985
+ priority: number;
986
+ status: string;
987
+ progress_percentage?: number;
988
+ estimated_minutes?: number;
989
+ }>;
990
+ stats: {
991
+ total: number;
992
+ completed: number;
993
+ progress_percentage: number;
994
+ };
995
+ }>> {
996
+ return this.proxy('get_subtasks', {
997
+ parent_task_id: parentTaskId,
998
+ status
999
+ });
1000
+ }
1001
+
1002
+ // ============================================================================
1003
+ // Activity feed endpoint
1004
+ // ============================================================================
1005
+ async getActivityFeed(projectId: string, params?: {
1006
+ limit?: number;
1007
+ since?: string;
1008
+ }): Promise<ApiResponse<{
1009
+ activities: Array<{
1010
+ type: string;
1011
+ data: unknown;
1012
+ timestamp: string;
1013
+ }>;
1014
+ }>> {
1015
+ return this.proxy('get_activity_feed', {
1016
+ project_id: projectId,
1017
+ ...params
1018
+ });
1019
+ }
1020
+
1021
+ // ============================================================================
1022
+ // Deployment endpoints
1023
+ // ============================================================================
1024
+ async requestDeployment(projectId: string, params?: {
1025
+ environment?: string;
1026
+ version_bump?: string;
1027
+ git_ref?: string;
1028
+ notes?: string;
1029
+ }, sessionId?: string): Promise<ApiResponse<{
1030
+ success: boolean;
1031
+ deployment_id: string;
1032
+ status: string;
1033
+ }>> {
1034
+ return this.proxy('request_deployment', {
1035
+ project_id: projectId,
1036
+ ...params
1037
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
1038
+ }
1039
+
1040
+ async checkDeploymentStatus(projectId: string): Promise<ApiResponse<{
1041
+ active_deployment: boolean;
1042
+ deployment?: {
1043
+ id: string;
1044
+ status: string;
1045
+ environment: string;
1046
+ git_ref?: string;
1047
+ created_at: string;
1048
+ };
1049
+ }>> {
1050
+ return this.proxy('check_deployment_status', { project_id: projectId });
1051
+ }
1052
+
1053
+ async claimDeploymentValidation(projectId: string, sessionId?: string): Promise<ApiResponse<{
1054
+ success: boolean;
1055
+ deployment_id: string;
1056
+ message: string;
1057
+ }>> {
1058
+ return this.proxy('claim_deployment_validation', { project_id: projectId }, sessionId ? {
1059
+ session_id: sessionId,
1060
+ persona: null,
1061
+ instance_id: ''
1062
+ } : undefined);
1063
+ }
1064
+
1065
+ async reportValidation(projectId: string, params: {
1066
+ build_passed: boolean;
1067
+ tests_passed: boolean;
1068
+ error_message?: string;
1069
+ }): Promise<ApiResponse<{
1070
+ success: boolean;
1071
+ deployment_id: string;
1072
+ status: string;
1073
+ }>> {
1074
+ return this.proxy('report_validation', {
1075
+ project_id: projectId,
1076
+ ...params
1077
+ });
1078
+ }
1079
+
1080
+ async startDeployment(projectId: string, sessionId?: string): Promise<ApiResponse<{
1081
+ success: boolean;
1082
+ deployment_id: string;
1083
+ instructions: string;
1084
+ }>> {
1085
+ return this.proxy('start_deployment', { project_id: projectId }, sessionId ? {
1086
+ session_id: sessionId,
1087
+ persona: null,
1088
+ instance_id: ''
1089
+ } : undefined);
1090
+ }
1091
+
1092
+ async completeDeployment(projectId: string, params: {
1093
+ success: boolean;
1094
+ summary?: string;
1095
+ }): Promise<ApiResponse<{
1096
+ success: boolean;
1097
+ deployment_id: string;
1098
+ status: string;
1099
+ }>> {
1100
+ return this.proxy('complete_deployment', {
1101
+ project_id: projectId,
1102
+ ...params
1103
+ });
1104
+ }
1105
+
1106
+ async cancelDeployment(projectId: string, reason?: string): Promise<ApiResponse<{
1107
+ success: boolean;
1108
+ }>> {
1109
+ return this.proxy('cancel_deployment', {
1110
+ project_id: projectId,
1111
+ reason
1112
+ });
1113
+ }
1114
+
1115
+ // ============================================================================
1116
+ // Task reference endpoints
1117
+ // ============================================================================
1118
+ async addTaskReference(taskId: string, url: string, label?: string): Promise<ApiResponse<{
1119
+ success: boolean;
1120
+ reference: { url: string; label?: string };
1121
+ }>> {
1122
+ return this.proxy('add_task_reference', {
1123
+ task_id: taskId,
1124
+ url,
1125
+ label
1126
+ });
1127
+ }
1128
+
1129
+ async removeTaskReference(taskId: string, url: string): Promise<ApiResponse<{
1130
+ success: boolean;
1131
+ }>> {
1132
+ return this.proxy('remove_task_reference', {
1133
+ task_id: taskId,
1134
+ url
1135
+ });
1136
+ }
1137
+
1138
+ // ============================================================================
1139
+ // Knowledge base endpoint
1140
+ // ============================================================================
1141
+ async queryKnowledgeBase(projectId: string, params?: {
1142
+ categories?: string[];
1143
+ limit?: number;
1144
+ search_query?: string;
1145
+ }): Promise<ApiResponse<{
1146
+ findings?: Array<{ id: string; title: string; category: string; severity: string }>;
1147
+ decisions?: Array<{ id: string; title: string; description: string }>;
1148
+ completed_tasks?: Array<{ id: string; title: string; completed_at: string }>;
1149
+ resolved_blockers?: Array<{ id: string; description: string; resolution_note?: string }>;
1150
+ }>> {
1151
+ return this.proxy('query_knowledge_base', {
1152
+ project_id: projectId,
1153
+ ...params
1154
+ });
1155
+ }
1156
+
1157
+ // ============================================================================
1158
+ // Session sync endpoint
1159
+ // ============================================================================
1160
+ async syncSession(sessionId: string, params?: {
1161
+ total_tokens?: number;
1162
+ token_breakdown?: Record<string, unknown>;
1163
+ model_usage?: Record<string, unknown>;
1164
+ }): Promise<ApiResponse<{
1165
+ success: boolean;
1166
+ }>> {
1167
+ return this.proxy('sync_session', {
1168
+ session_id: sessionId,
1169
+ ...params
1170
+ });
1171
+ }
1172
+
1173
+ // ============================================================================
1174
+ // Organization endpoints
1175
+ // ============================================================================
1176
+ async listOrganizations(): Promise<ApiResponse<{
1177
+ organizations: Array<{
1178
+ id: string;
1179
+ name: string;
1180
+ slug: string;
1181
+ description?: string;
1182
+ role: string;
1183
+ }>;
1184
+ }>> {
1185
+ return this.proxy('list_organizations', {});
1186
+ }
1187
+
1188
+ async createOrganization(params: {
1189
+ name: string;
1190
+ slug?: string;
1191
+ description?: string;
1192
+ }): Promise<ApiResponse<{
1193
+ success: boolean;
1194
+ organization: { id: string; name: string; slug: string };
1195
+ }>> {
1196
+ return this.proxy('create_organization', params);
1197
+ }
1198
+
1199
+ async updateOrganization(organizationId: string, updates: {
1200
+ name?: string;
1201
+ description?: string;
1202
+ logo_url?: string;
1203
+ }): Promise<ApiResponse<{
1204
+ success: boolean;
1205
+ organization_id: string;
1206
+ }>> {
1207
+ return this.proxy('update_organization', {
1208
+ organization_id: organizationId,
1209
+ ...updates
1210
+ });
1211
+ }
1212
+
1213
+ async deleteOrganization(organizationId: string): Promise<ApiResponse<{
1214
+ success: boolean;
1215
+ }>> {
1216
+ return this.proxy('delete_organization', { organization_id: organizationId });
1217
+ }
1218
+
1219
+ async listOrgMembers(organizationId: string): Promise<ApiResponse<{
1220
+ members: Array<{
1221
+ user_id: string;
1222
+ email: string;
1223
+ role: string;
1224
+ joined_at: string;
1225
+ }>;
1226
+ }>> {
1227
+ return this.proxy('list_org_members', { organization_id: organizationId });
1228
+ }
1229
+
1230
+ async inviteMember(organizationId: string, email: string, role?: string): Promise<ApiResponse<{
1231
+ success: boolean;
1232
+ invite_id: string;
1233
+ }>> {
1234
+ return this.proxy('invite_member', {
1235
+ organization_id: organizationId,
1236
+ email,
1237
+ role
1238
+ });
1239
+ }
1240
+
1241
+ async updateMemberRole(organizationId: string, userId: string, role: string): Promise<ApiResponse<{
1242
+ success: boolean;
1243
+ }>> {
1244
+ return this.proxy('update_member_role', {
1245
+ organization_id: organizationId,
1246
+ user_id: userId,
1247
+ role
1248
+ });
1249
+ }
1250
+
1251
+ async removeMember(organizationId: string, userId: string): Promise<ApiResponse<{
1252
+ success: boolean;
1253
+ }>> {
1254
+ return this.proxy('remove_member', {
1255
+ organization_id: organizationId,
1256
+ user_id: userId
1257
+ });
1258
+ }
1259
+
1260
+ async shareProjectWithOrg(projectId: string, organizationId: string, permission?: string): Promise<ApiResponse<{
1261
+ success: boolean;
1262
+ }>> {
1263
+ return this.proxy('share_project_with_org', {
1264
+ project_id: projectId,
1265
+ organization_id: organizationId,
1266
+ permission
1267
+ });
1268
+ }
1269
+
1270
+ async unshareProject(projectId: string, organizationId: string): Promise<ApiResponse<{
1271
+ success: boolean;
1272
+ }>> {
1273
+ return this.proxy('unshare_project', {
1274
+ project_id: projectId,
1275
+ organization_id: organizationId
1276
+ });
1277
+ }
1278
+
1279
+ async leaveOrganization(organizationId: string): Promise<ApiResponse<{
1280
+ success: boolean;
1281
+ message: string;
1282
+ }>> {
1283
+ return this.proxy('leave_organization', { organization_id: organizationId });
1284
+ }
1285
+
1286
+ async updateProjectShare(projectId: string, organizationId: string, permission: string): Promise<ApiResponse<{
1287
+ success: boolean;
1288
+ share: { permission: string };
1289
+ }>> {
1290
+ return this.proxy('update_project_share', {
1291
+ project_id: projectId,
1292
+ organization_id: organizationId,
1293
+ permission
1294
+ });
1295
+ }
1296
+
1297
+ async listProjectShares(projectId: string): Promise<ApiResponse<{
1298
+ shares: Array<{
1299
+ id: string;
1300
+ permission: string;
1301
+ shared_at: string;
1302
+ organization: { id: string; name: string; slug: string };
1303
+ }>;
1304
+ count: number;
1305
+ }>> {
1306
+ return this.proxy('list_project_shares', { project_id: projectId });
1307
+ }
1308
+
1309
+ // ============================================================================
1310
+ // Body of work endpoints
1311
+ // ============================================================================
1312
+ async createBodyOfWork(projectId: string, params: {
1313
+ title: string;
1314
+ description?: string;
1315
+ auto_deploy_on_completion?: boolean;
1316
+ deploy_environment?: string;
1317
+ deploy_version_bump?: string;
1318
+ deploy_trigger?: string;
1319
+ }): Promise<ApiResponse<{
1320
+ success: boolean;
1321
+ body_of_work_id: string;
1322
+ }>> {
1323
+ return this.proxy('create_body_of_work', {
1324
+ project_id: projectId,
1325
+ ...params
1326
+ });
1327
+ }
1328
+
1329
+ async getBodyOfWork(bodyOfWorkId: string): Promise<ApiResponse<{
1330
+ body_of_work: {
1331
+ id: string;
1332
+ title: string;
1333
+ description?: string;
1334
+ status: string;
1335
+ auto_deploy_on_completion: boolean;
1336
+ };
1337
+ tasks: {
1338
+ pre: Array<{ id: string; title: string; status: string }>;
1339
+ core: Array<{ id: string; title: string; status: string }>;
1340
+ post: Array<{ id: string; title: string; status: string }>;
1341
+ };
1342
+ }>> {
1343
+ return this.proxy('get_body_of_work', { body_of_work_id: bodyOfWorkId });
1344
+ }
1345
+
1346
+ async getBodiesOfWork(projectId: string, params?: {
1347
+ status?: string;
1348
+ limit?: number;
1349
+ offset?: number;
1350
+ search_query?: string;
1351
+ }): Promise<ApiResponse<{
1352
+ bodies_of_work: Array<{
1353
+ id: string;
1354
+ title: string;
1355
+ description?: string;
1356
+ status: string;
1357
+ task_counts: { pre: number; core: number; post: number };
1358
+ }>;
1359
+ }>> {
1360
+ return this.proxy('get_bodies_of_work', {
1361
+ project_id: projectId,
1362
+ ...params
1363
+ });
1364
+ }
1365
+
1366
+ async updateBodyOfWork(bodyOfWorkId: string, updates: {
1367
+ title?: string;
1368
+ description?: string;
1369
+ auto_deploy_on_completion?: boolean;
1370
+ deploy_environment?: string;
1371
+ deploy_version_bump?: string;
1372
+ deploy_trigger?: string;
1373
+ }): Promise<ApiResponse<{
1374
+ success: boolean;
1375
+ }>> {
1376
+ return this.proxy('update_body_of_work', {
1377
+ body_of_work_id: bodyOfWorkId,
1378
+ ...updates
1379
+ });
1380
+ }
1381
+
1382
+ async deleteBodyOfWork(bodyOfWorkId: string): Promise<ApiResponse<{
1383
+ success: boolean;
1384
+ }>> {
1385
+ return this.proxy('delete_body_of_work', { body_of_work_id: bodyOfWorkId });
1386
+ }
1387
+
1388
+ async addTaskToBodyOfWork(bodyOfWorkId: string, taskId: string, phase?: string, orderIndex?: number): Promise<ApiResponse<{
1389
+ success: boolean;
1390
+ }>> {
1391
+ return this.proxy('add_task_to_body_of_work', {
1392
+ body_of_work_id: bodyOfWorkId,
1393
+ task_id: taskId,
1394
+ phase,
1395
+ order_index: orderIndex
1396
+ });
1397
+ }
1398
+
1399
+ async removeTaskFromBodyOfWork(taskId: string): Promise<ApiResponse<{
1400
+ success: boolean;
1401
+ }>> {
1402
+ return this.proxy('remove_task_from_body_of_work', { task_id: taskId });
1403
+ }
1404
+
1405
+ async activateBodyOfWork(bodyOfWorkId: string): Promise<ApiResponse<{
1406
+ success: boolean;
1407
+ status: string;
1408
+ }>> {
1409
+ return this.proxy('activate_body_of_work', { body_of_work_id: bodyOfWorkId });
1410
+ }
1411
+
1412
+ async addTaskDependency(bodyOfWorkId: string, taskId: string, dependsOnTaskId: string): Promise<ApiResponse<{
1413
+ success: boolean;
1414
+ }>> {
1415
+ return this.proxy('add_task_dependency', {
1416
+ body_of_work_id: bodyOfWorkId,
1417
+ task_id: taskId,
1418
+ depends_on_task_id: dependsOnTaskId
1419
+ });
1420
+ }
1421
+
1422
+ async removeTaskDependency(taskId: string, dependsOnTaskId: string): Promise<ApiResponse<{
1423
+ success: boolean;
1424
+ }>> {
1425
+ return this.proxy('remove_task_dependency', {
1426
+ task_id: taskId,
1427
+ depends_on_task_id: dependsOnTaskId
1428
+ });
1429
+ }
1430
+
1431
+ async getTaskDependencies(params: {
1432
+ body_of_work_id?: string;
1433
+ task_id?: string;
1434
+ }): Promise<ApiResponse<{
1435
+ dependencies: Array<{
1436
+ id: string;
1437
+ task_id: string;
1438
+ depends_on_task_id: string;
1439
+ created_at: string;
1440
+ }>;
1441
+ }>> {
1442
+ return this.proxy('get_task_dependencies', params);
1443
+ }
1444
+
1445
+ async getNextBodyOfWorkTask(bodyOfWorkId: string): Promise<ApiResponse<{
1446
+ task?: {
1447
+ id: string;
1448
+ title: string;
1449
+ priority: number;
1450
+ phase: string;
1451
+ } | null;
1452
+ message?: string;
1453
+ }>> {
1454
+ return this.proxy('get_next_body_of_work_task', { body_of_work_id: bodyOfWorkId });
1455
+ }
1456
+
1457
+ // ============================================================================
1458
+ // Git issues endpoints
1459
+ // ============================================================================
1460
+ async addGitIssue(projectId: string, params: {
1461
+ issue_type: string;
1462
+ branch: string;
1463
+ target_branch?: string;
1464
+ pr_url?: string;
1465
+ conflicting_files?: string[];
1466
+ error_message?: string;
1467
+ task_id?: string;
1468
+ }, sessionId?: string): Promise<ApiResponse<{
1469
+ success: boolean;
1470
+ git_issue_id: string;
1471
+ }>> {
1472
+ return this.proxy('add_git_issue', {
1473
+ project_id: projectId,
1474
+ ...params
1475
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
1476
+ }
1477
+
1478
+ async resolveGitIssue(gitIssueId: string, params?: {
1479
+ resolution_note?: string;
1480
+ auto_resolved?: boolean;
1481
+ }, sessionId?: string): Promise<ApiResponse<{
1482
+ success: boolean;
1483
+ git_issue_id: string;
1484
+ }>> {
1485
+ return this.proxy('resolve_git_issue', {
1486
+ git_issue_id: gitIssueId,
1487
+ ...params
1488
+ }, sessionId ? { session_id: sessionId, persona: null, instance_id: '' } : undefined);
1489
+ }
1490
+
1491
+ async getGitIssues(projectId: string, params?: {
1492
+ status?: string;
1493
+ issue_type?: string;
1494
+ branch?: string;
1495
+ limit?: number;
1496
+ }): Promise<ApiResponse<{
1497
+ git_issues: Array<{
1498
+ id: string;
1499
+ issue_type: string;
1500
+ branch: string;
1501
+ target_branch?: string;
1502
+ pr_url?: string;
1503
+ conflicting_files?: string[];
1504
+ error_message?: string;
1505
+ status: string;
1506
+ created_at: string;
1507
+ resolved_at?: string;
1508
+ }>;
1509
+ }>> {
1510
+ return this.proxy('get_git_issues', {
1511
+ project_id: projectId,
1512
+ ...params
1513
+ });
1514
+ }
1515
+
1516
+ async deleteGitIssue(gitIssueId: string): Promise<ApiResponse<{
1517
+ success: boolean;
1518
+ }>> {
1519
+ return this.proxy('delete_git_issue', { git_issue_id: gitIssueId });
1520
+ }
1521
+
1522
+ // ============================================================================
1523
+ // Cost tracking endpoints
1524
+ // ============================================================================
1525
+ async getCostSummary(projectId: string, params?: {
1526
+ period?: 'daily' | 'weekly' | 'monthly';
1527
+ limit?: number;
1528
+ }): Promise<ApiResponse<{
1529
+ summaries: Array<{
1530
+ date: string;
1531
+ total_cost: number;
1532
+ input_tokens: number;
1533
+ output_tokens: number;
1534
+ }>;
1535
+ }>> {
1536
+ return this.proxy('get_cost_summary', {
1537
+ project_id: projectId,
1538
+ ...params
1539
+ });
1540
+ }
1541
+
1542
+ async getCostAlerts(): Promise<ApiResponse<{
1543
+ alerts: Array<{
1544
+ id: string;
1545
+ threshold_amount: number;
1546
+ threshold_period: string;
1547
+ alert_type: string;
1548
+ enabled: boolean;
1549
+ }>;
1550
+ }>> {
1551
+ return this.proxy('get_cost_alerts', {});
1552
+ }
1553
+
1554
+ async addCostAlert(params: {
1555
+ threshold_amount: number;
1556
+ threshold_period: 'daily' | 'weekly' | 'monthly';
1557
+ alert_type?: 'warning' | 'critical';
1558
+ project_id?: string;
1559
+ }): Promise<ApiResponse<{
1560
+ success: boolean;
1561
+ alert_id: string;
1562
+ }>> {
1563
+ return this.proxy('add_cost_alert', params);
1564
+ }
1565
+
1566
+ async updateCostAlert(alertId: string, updates: {
1567
+ threshold_amount?: number;
1568
+ threshold_period?: string;
1569
+ alert_type?: string;
1570
+ enabled?: boolean;
1571
+ }): Promise<ApiResponse<{
1572
+ success: boolean;
1573
+ }>> {
1574
+ return this.proxy('update_cost_alert', {
1575
+ alert_id: alertId,
1576
+ ...updates
1577
+ });
1578
+ }
1579
+
1580
+ async deleteCostAlert(alertId: string): Promise<ApiResponse<{
1581
+ success: boolean;
1582
+ }>> {
1583
+ return this.proxy('delete_cost_alert', { alert_id: alertId });
1584
+ }
1585
+
1586
+ async getTaskCosts(projectId: string, limit?: number): Promise<ApiResponse<{
1587
+ task_costs: Array<{
1588
+ task_id: string;
1589
+ title: string;
1590
+ total_cost: number;
1591
+ input_tokens: number;
1592
+ output_tokens: number;
1593
+ }>;
1594
+ }>> {
1595
+ return this.proxy('get_task_costs', {
1596
+ project_id: projectId,
1597
+ limit
1598
+ });
1599
+ }
1600
+
1601
+ async getTokenUsage(): Promise<ApiResponse<{
1602
+ session_tokens: number;
1603
+ estimated_cost: number;
1604
+ }>> {
1605
+ return this.proxy('get_token_usage', {});
1606
+ }
1607
+
1608
+ // ============================================================================
1609
+ // Batch operation endpoints
1610
+ // ============================================================================
1611
+ async batchUpdateTasks(updates: Array<{
1612
+ task_id: string;
1613
+ status?: string;
1614
+ priority?: number;
1615
+ progress_percentage?: number;
1616
+ progress_note?: string;
1617
+ }>): Promise<ApiResponse<{
1618
+ success: boolean;
1619
+ updated_count: number;
1620
+ }>> {
1621
+ return this.proxy('batch_update_tasks', { updates });
1622
+ }
1623
+
1624
+ async batchCompleteTasks(completions: Array<{
1625
+ task_id: string;
1626
+ summary?: string;
1627
+ }>): Promise<ApiResponse<{
1628
+ success: boolean;
1629
+ completed_count: number;
1630
+ next_task?: { id: string; title: string } | null;
1631
+ }>> {
1632
+ return this.proxy('batch_complete_tasks', { completions });
1633
+ }
1634
+
1635
+ // ============================================================================
1636
+ // Deployment requirements and scheduling endpoints
1637
+ // ============================================================================
1638
+ async addDeploymentRequirement(projectId: string, params: {
1639
+ type: string;
1640
+ title: string;
1641
+ description?: string;
1642
+ file_path?: string;
1643
+ stage?: string;
1644
+ blocking?: boolean;
1645
+ recurring?: boolean;
1646
+ }): Promise<ApiResponse<{
1647
+ success: boolean;
1648
+ requirement_id: string;
1649
+ }>> {
1650
+ return this.proxy('add_deployment_requirement', {
1651
+ project_id: projectId,
1652
+ ...params
1653
+ });
1654
+ }
1655
+
1656
+ async getDeploymentRequirements(projectId: string, params?: {
1657
+ status?: string;
1658
+ stage?: string;
1659
+ }): Promise<ApiResponse<{
1660
+ requirements: Array<{
1661
+ id: string;
1662
+ type: string;
1663
+ title: string;
1664
+ description?: string;
1665
+ status: string;
1666
+ stage: string;
1667
+ }>;
1668
+ }>> {
1669
+ return this.proxy('get_deployment_requirements', {
1670
+ project_id: projectId,
1671
+ ...params
1672
+ });
1673
+ }
1674
+
1675
+ async completeDeploymentRequirement(requirementId: string): Promise<ApiResponse<{
1676
+ success: boolean;
1677
+ }>> {
1678
+ return this.proxy('complete_deployment_requirement', { requirement_id: requirementId });
1679
+ }
1680
+
1681
+ async scheduleDeployment(projectId: string, params: {
1682
+ scheduled_at: string;
1683
+ schedule_type?: string;
1684
+ environment?: string;
1685
+ version_bump?: string;
1686
+ auto_trigger?: boolean;
1687
+ notes?: string;
1688
+ git_ref?: string;
1689
+ }): Promise<ApiResponse<{
1690
+ success: boolean;
1691
+ schedule_id: string;
1692
+ }>> {
1693
+ return this.proxy('schedule_deployment', {
1694
+ project_id: projectId,
1695
+ ...params
1696
+ });
1697
+ }
1698
+
1699
+ async getScheduledDeployments(projectId: string, includeDisabled?: boolean): Promise<ApiResponse<{
1700
+ schedules: Array<{
1701
+ id: string;
1702
+ scheduled_at: string;
1703
+ schedule_type: string;
1704
+ environment: string;
1705
+ version_bump: string;
1706
+ auto_trigger: boolean;
1707
+ enabled: boolean;
1708
+ git_ref?: string;
1709
+ notes?: string;
1710
+ }>;
1711
+ count: number;
1712
+ due_count: number;
1713
+ }>> {
1714
+ return this.proxy('get_scheduled_deployments', {
1715
+ project_id: projectId,
1716
+ include_disabled: includeDisabled
1717
+ });
1718
+ }
1719
+
1720
+ async updateScheduledDeployment(scheduleId: string, updates: {
1721
+ scheduled_at?: string;
1722
+ schedule_type?: string;
1723
+ environment?: string;
1724
+ version_bump?: string;
1725
+ auto_trigger?: boolean;
1726
+ enabled?: boolean;
1727
+ git_ref?: string;
1728
+ notes?: string;
1729
+ }): Promise<ApiResponse<{
1730
+ success: boolean;
1731
+ schedule_id: string;
1732
+ }>> {
1733
+ return this.proxy('update_scheduled_deployment', {
1734
+ schedule_id: scheduleId,
1735
+ ...updates
1736
+ });
1737
+ }
1738
+
1739
+ async deleteScheduledDeployment(scheduleId: string): Promise<ApiResponse<{
1740
+ success: boolean;
1741
+ }>> {
1742
+ return this.proxy('delete_scheduled_deployment', { schedule_id: scheduleId });
1743
+ }
1744
+
1745
+ async triggerScheduledDeployment(scheduleId: string, sessionId?: string): Promise<ApiResponse<{
1746
+ success: boolean;
1747
+ deployment_id?: string;
1748
+ schedule_id: string;
1749
+ schedule_type: string;
1750
+ next_scheduled_at?: string;
1751
+ message?: string;
1752
+ }>> {
1753
+ return this.proxy('trigger_scheduled_deployment', { schedule_id: scheduleId }, sessionId ? {
1754
+ session_id: sessionId,
1755
+ persona: null,
1756
+ instance_id: ''
1757
+ } : undefined);
1758
+ }
1759
+
1760
+ async checkDueDeployments(projectId: string): Promise<ApiResponse<{
1761
+ due_schedules: Array<{
1762
+ id: string;
1763
+ scheduled_at: string;
1764
+ environment: string;
1765
+ version_bump: string;
1766
+ schedule_type: string;
1767
+ }>;
1768
+ count: number;
1769
+ }>> {
1770
+ return this.proxy('check_due_deployments', { project_id: projectId });
1771
+ }
1772
+
1773
+ // ============================================================================
1774
+ // Project README endpoint
1775
+ // ============================================================================
1776
+ async updateProjectReadme(projectId: string, readmeContent: string): Promise<ApiResponse<{
1777
+ success: boolean;
1778
+ project_id: string;
1779
+ }>> {
1780
+ return this.proxy('update_project_readme', {
1781
+ project_id: projectId,
1782
+ readme_content: readmeContent
1783
+ });
1784
+ }
1785
+
1786
+ // ============================================================================
1787
+ // Help Topics (database-backed)
1788
+ // ============================================================================
1789
+ async getHelpTopic(slug: string): Promise<ApiResponse<{
1790
+ slug: string;
1791
+ title: string;
1792
+ content: string;
1793
+ } | null>> {
1794
+ return this.proxy('get_help_topic', { slug });
1795
+ }
1796
+
1797
+ async getHelpTopics(): Promise<ApiResponse<Array<{
1798
+ slug: string;
1799
+ title: string;
1800
+ }>>> {
1801
+ return this.proxy('get_help_topics', {});
1802
+ }
1803
+ }
1804
+
1805
+ // Singleton instance
1806
+ let apiClient: VibescopeApiClient | null = null;
1807
+
1808
+ export function getApiClient(): VibescopeApiClient {
1809
+ if (!apiClient) {
1810
+ const apiKey = process.env.VIBESCOPE_API_KEY;
1811
+ if (!apiKey) {
1812
+ throw new Error('VIBESCOPE_API_KEY environment variable is required');
1813
+ }
1814
+ apiClient = new VibescopeApiClient({ apiKey });
1815
+ }
1816
+ return apiClient;
1817
+ }
1818
+
1819
+ export function initApiClient(config: ApiClientConfig): VibescopeApiClient {
1820
+ apiClient = new VibescopeApiClient(config);
1821
+ return apiClient;
1822
+ }