@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
@@ -9,75 +9,9 @@
9
9
  * - update_project_readme
10
10
  */
11
11
 
12
- import type { Handler, HandlerRegistry, UserUpdates, AuthContext } from './types.js';
13
- import type { SupabaseClient } from '@supabase/supabase-js';
12
+ import type { Handler, HandlerRegistry } from './types.js';
14
13
  import { validateRequired, validateUUID, validateProjectStatus } from '../validators.js';
15
-
16
- /**
17
- * Get user-created items since last sync
18
- */
19
- async function getUserUpdates(
20
- supabase: SupabaseClient,
21
- auth: AuthContext,
22
- projectId: string,
23
- currentSessionId: string | null
24
- ): Promise<UserUpdates | undefined> {
25
- let lastSyncedAt: string;
26
-
27
- if (currentSessionId) {
28
- const { data: session } = await supabase
29
- .from('agent_sessions')
30
- .select('last_synced_at')
31
- .eq('id', currentSessionId)
32
- .single();
33
- lastSyncedAt = session?.last_synced_at || new Date(0).toISOString();
34
- } else {
35
- const { data: session } = await supabase
36
- .from('agent_sessions')
37
- .select('last_synced_at')
38
- .eq('api_key_id', auth.apiKeyId)
39
- .eq('project_id', projectId)
40
- .single();
41
- lastSyncedAt = session?.last_synced_at || new Date(0).toISOString();
42
- }
43
-
44
- const [tasksResult, blockersResult, ideasResult] = await Promise.all([
45
- supabase
46
- .from('tasks')
47
- .select('id, title, created_at')
48
- .eq('project_id', projectId)
49
- .eq('created_by', 'user')
50
- .gt('created_at', lastSyncedAt)
51
- .order('created_at', { ascending: false })
52
- .limit(5),
53
- supabase
54
- .from('blockers')
55
- .select('id, description, created_at')
56
- .eq('project_id', projectId)
57
- .eq('created_by', 'user')
58
- .gt('created_at', lastSyncedAt)
59
- .order('created_at', { ascending: false })
60
- .limit(5),
61
- supabase
62
- .from('ideas')
63
- .select('id, title, created_at')
64
- .eq('project_id', projectId)
65
- .eq('created_by', 'user')
66
- .gt('created_at', lastSyncedAt)
67
- .order('created_at', { ascending: false })
68
- .limit(5),
69
- ]);
70
-
71
- const tasks = tasksResult.data || [];
72
- const blockers = blockersResult.data || [];
73
- const ideas = ideasResult.data || [];
74
-
75
- if (tasks.length === 0 && blockers.length === 0 && ideas.length === 0) {
76
- return undefined;
77
- }
78
-
79
- return { tasks, blockers, ideas };
80
- }
14
+ import { getApiClient } from '../api-client.js';
81
15
 
82
16
  export const getProjectContext: Handler = async (args, ctx) => {
83
17
  const { project_id, git_url } = args as {
@@ -85,90 +19,36 @@ export const getProjectContext: Handler = async (args, ctx) => {
85
19
  git_url?: string;
86
20
  };
87
21
 
88
- const { supabase, auth, session } = ctx;
22
+ const apiClient = getApiClient();
89
23
 
90
24
  // If no project_id or git_url, list all projects
91
25
  if (!project_id && !git_url) {
92
- const { data: projects, error } = await supabase
93
- .from('projects')
94
- .select('id, name, description, status, git_url')
95
- .eq('user_id', auth.userId)
96
- .order('updated_at', { ascending: false });
26
+ const response = await apiClient.listProjects();
27
+
28
+ if (!response.ok) {
29
+ throw new Error(response.error || 'Failed to fetch projects');
30
+ }
97
31
 
98
- if (error) throw new Error(`Failed to fetch projects: ${error.message}`);
99
- return { result: { projects: projects || [] } };
32
+ return { result: { projects: response.data?.projects || [] } };
100
33
  }
101
34
 
102
35
  // Find project by ID or git_url
103
- let query = supabase
104
- .from('projects')
105
- .select('id, name, description, goal, status, git_url, agent_instructions, tech_stack')
106
- .eq('user_id', auth.userId);
36
+ const response = await apiClient.getProject(project_id || 'by-git-url', git_url);
107
37
 
108
- if (project_id) {
109
- query = query.eq('id', project_id);
110
- } else if (git_url) {
111
- query = query.eq('git_url', git_url);
38
+ if (!response.ok) {
39
+ throw new Error(response.error || 'Failed to fetch project');
112
40
  }
113
41
 
114
- const { data: project, error: projectError } = await query.single();
115
-
116
- if (projectError || !project) {
42
+ if (!response.data?.found) {
117
43
  return {
118
44
  result: {
119
45
  found: false,
120
- message: 'Project not found. Use create_project to create one.',
46
+ message: response.data?.message || 'Project not found. Use create_project to create one.',
121
47
  },
122
48
  };
123
49
  }
124
50
 
125
- // Fetch related data with minimal fields
126
- const [tasksResult, blockersResult, decisionsResult, progressResult] = await Promise.all([
127
- supabase
128
- .from('tasks')
129
- .select('id, title, description, priority, status, estimated_minutes')
130
- .eq('project_id', project.id)
131
- .in('status', ['pending', 'in_progress'])
132
- .order('priority', { ascending: true })
133
- .limit(10),
134
- supabase
135
- .from('blockers')
136
- .select('id, description')
137
- .eq('project_id', project.id)
138
- .eq('status', 'open')
139
- .limit(5),
140
- supabase
141
- .from('decisions')
142
- .select('title')
143
- .eq('project_id', project.id)
144
- .order('created_at', { ascending: false })
145
- .limit(5),
146
- supabase
147
- .from('progress_logs')
148
- .select('summary')
149
- .eq('project_id', project.id)
150
- .order('created_at', { ascending: false })
151
- .limit(5),
152
- ]);
153
-
154
- const userUpdates = await getUserUpdates(supabase, auth, project.id, session.currentSessionId);
155
-
156
- // Build compact response
157
- const result: Record<string, unknown> = {
158
- found: true,
159
- project,
160
- active_tasks: tasksResult.data || [],
161
- };
162
-
163
- const blockers = blockersResult.data || [];
164
- const decisions = decisionsResult.data || [];
165
- const progress = progressResult.data || [];
166
-
167
- if (blockers.length > 0) result.open_blockers = blockers;
168
- if (decisions.length > 0) result.recent_decisions = decisions;
169
- if (progress.length > 0) result.recent_progress = progress;
170
-
171
- return { result, user_updates: userUpdates } as { result: Record<string, unknown>; user_updates?: UserUpdates };
51
+ return { result: response.data };
172
52
  };
173
53
 
174
54
  export const getGitWorkflow: Handler = async (args, ctx) => {
@@ -180,79 +60,14 @@ export const getGitWorkflow: Handler = async (args, ctx) => {
180
60
  validateRequired(project_id, 'project_id');
181
61
  validateUUID(project_id, 'project_id');
182
62
 
183
- const { supabase } = ctx;
184
-
185
- const { data: project, error } = await supabase
186
- .from('projects')
187
- .select('git_workflow, git_main_branch, git_develop_branch, git_auto_branch, git_auto_tag, git_url')
188
- .eq('id', project_id)
189
- .single();
190
-
191
- if (error || !project) throw new Error(`Project not found: ${project_id}`);
192
-
193
- let task = null;
194
- if (task_id) {
195
- const { data: taskData } = await supabase
196
- .from('tasks')
197
- .select('id, title, git_branch')
198
- .eq('id', task_id)
199
- .single();
200
- task = taskData;
201
- }
202
-
203
- // Generate workflow instructions
204
- const workflow = project.git_workflow || 'none';
205
- const mainBranch = project.git_main_branch || 'main';
206
- const developBranch = project.git_develop_branch || 'develop';
207
-
208
- const instructions: Record<string, string[]> = {
209
- 'none': [
210
- 'No git workflow configured for this project.',
211
- 'Commit changes directly without branching strategy.',
212
- ],
213
- 'trunk-based': [
214
- `Work directly on the ${mainBranch} branch.`,
215
- 'Make small, frequent commits.',
216
- 'Ensure all tests pass before committing.',
217
- `Tag deployments on ${mainBranch} (e.g., git tag v1.0.0).`,
218
- ],
219
- 'github-flow': [
220
- task ? `Create feature branch: git checkout -b feature/${task.id.slice(0, 8)}-${task.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 30)}` : 'Create a feature branch for each task.',
221
- 'Make commits with descriptive messages.',
222
- 'Push branch and create a pull request.',
223
- `Merge to ${mainBranch} after review/validation.`,
224
- project.git_auto_tag ? 'Deployments will be automatically tagged.' : `Tag deployments manually on ${mainBranch}.`,
225
- ],
226
- 'git-flow': [
227
- task ? `Create feature branch from ${developBranch}: git checkout -b feature/${task.id.slice(0, 8)}-${task.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 30)} ${developBranch}` : `Create feature branches from ${developBranch}.`,
228
- `Merge completed features back to ${developBranch}.`,
229
- `Create release branches from ${developBranch} when ready.`,
230
- `Merge releases to both ${mainBranch} and ${developBranch}.`,
231
- `Tag releases on ${mainBranch}.`,
232
- ],
233
- };
234
-
235
- const result: Record<string, unknown> = {
236
- workflow,
237
- main_branch: mainBranch,
238
- develop_branch: workflow === 'git-flow' ? developBranch : null,
239
- auto_branch: project.git_auto_branch,
240
- auto_tag: project.git_auto_tag,
241
- instructions: instructions[workflow] || instructions['none'],
242
- };
63
+ const apiClient = getApiClient();
64
+ const response = await apiClient.getGitWorkflow(project_id, task_id);
243
65
 
244
- if (task) {
245
- result.task = {
246
- id: task.id,
247
- title: task.title,
248
- current_branch: task.git_branch,
249
- suggested_branch: workflow !== 'none' && workflow !== 'trunk-based'
250
- ? `feature/${task.id.slice(0, 8)}-${task.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 30)}`
251
- : null,
252
- };
66
+ if (!response.ok) {
67
+ throw new Error(response.error || 'Failed to get git workflow');
253
68
  }
254
69
 
255
- return { result };
70
+ return { result: response.data };
256
71
  };
257
72
 
258
73
  export const createProject: Handler = async (args, ctx) => {
@@ -264,23 +79,22 @@ export const createProject: Handler = async (args, ctx) => {
264
79
  tech_stack?: string[];
265
80
  };
266
81
 
267
- const { supabase, auth } = ctx;
82
+ validateRequired(name, 'name');
83
+
84
+ const apiClient = getApiClient();
85
+ const response = await apiClient.createProject({
86
+ name,
87
+ description,
88
+ goal,
89
+ git_url,
90
+ tech_stack
91
+ });
268
92
 
269
- const { data, error } = await supabase
270
- .from('projects')
271
- .insert({
272
- user_id: auth.userId,
273
- name,
274
- description: description || null,
275
- goal: goal || null,
276
- git_url: git_url || null,
277
- tech_stack: tech_stack || null,
278
- })
279
- .select()
280
- .single();
93
+ if (!response.ok) {
94
+ throw new Error(response.error || 'Failed to create project');
95
+ }
281
96
 
282
- if (error) throw new Error(`Failed to create project: ${error.message}`);
283
- return { result: { success: true, project: data } };
97
+ return { result: response.data };
284
98
  };
285
99
 
286
100
  export const updateProject: Handler = async (args, ctx) => {
@@ -297,6 +111,8 @@ export const updateProject: Handler = async (args, ctx) => {
297
111
  git_develop_branch?: string;
298
112
  git_auto_branch?: boolean;
299
113
  git_auto_tag?: boolean;
114
+ git_auto_commit_on_complete?: boolean;
115
+ git_auto_pr_on_complete?: boolean;
300
116
  deployment_instructions?: string;
301
117
  };
302
118
 
@@ -304,17 +120,14 @@ export const updateProject: Handler = async (args, ctx) => {
304
120
  validateUUID(project_id, 'project_id');
305
121
  validateProjectStatus(updates.status);
306
122
 
307
- const { supabase, auth } = ctx;
308
-
309
- const { error } = await supabase
310
- .from('projects')
311
- .update(updates)
312
- .eq('id', project_id)
313
- .eq('user_id', auth.userId);
123
+ const apiClient = getApiClient();
124
+ const response = await apiClient.updateProject(project_id, updates);
314
125
 
315
- if (error) throw new Error(`Failed to update project: ${error.message}`);
126
+ if (!response.ok) {
127
+ throw new Error(response.error || 'Failed to update project');
128
+ }
316
129
 
317
- return { result: { success: true, project_id } };
130
+ return { result: response.data };
318
131
  };
319
132
 
320
133
  export const updateProjectReadme: Handler = async (args, ctx) => {
@@ -327,17 +140,14 @@ export const updateProjectReadme: Handler = async (args, ctx) => {
327
140
  validateUUID(project_id, 'project_id');
328
141
  validateRequired(readme_content, 'readme_content');
329
142
 
330
- const { error } = await ctx.supabase
331
- .from('projects')
332
- .update({
333
- readme_content,
334
- readme_updated_at: new Date().toISOString(),
335
- })
336
- .eq('id', project_id);
143
+ const apiClient = getApiClient();
144
+ const response = await apiClient.updateProjectReadme(project_id, readme_content);
337
145
 
338
- if (error) throw new Error(`Failed to update README: ${error.message}`);
146
+ if (!response.ok) {
147
+ throw new Error(response.error || 'Failed to update README');
148
+ }
339
149
 
340
- return { result: { success: true } };
150
+ return { result: response.data };
341
151
  };
342
152
 
343
153
  /**