@vibescope/mcp-server 0.0.1 → 0.1.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 (170) hide show
  1. package/README.md +113 -98
  2. package/dist/api-client.d.ts +1114 -0
  3. package/dist/api-client.js +698 -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 +106 -476
  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 +112 -828
  16. package/dist/handlers/discovery.js +31 -0
  17. package/dist/handlers/fallback.d.ts +2 -0
  18. package/dist/handlers/fallback.js +39 -134
  19. package/dist/handlers/findings.js +43 -67
  20. package/dist/handlers/git-issues.d.ts +9 -13
  21. package/dist/handlers/git-issues.js +80 -225
  22. package/dist/handlers/ideas.d.ts +3 -0
  23. package/dist/handlers/ideas.js +53 -134
  24. package/dist/handlers/index.d.ts +2 -0
  25. package/dist/handlers/index.js +6 -0
  26. package/dist/handlers/milestones.d.ts +2 -0
  27. package/dist/handlers/milestones.js +51 -98
  28. package/dist/handlers/organizations.js +79 -275
  29. package/dist/handlers/progress.d.ts +2 -0
  30. package/dist/handlers/progress.js +25 -123
  31. package/dist/handlers/project.js +42 -221
  32. package/dist/handlers/requests.d.ts +2 -0
  33. package/dist/handlers/requests.js +23 -83
  34. package/dist/handlers/session.js +99 -585
  35. package/dist/handlers/sprints.d.ts +32 -0
  36. package/dist/handlers/sprints.js +274 -0
  37. package/dist/handlers/tasks.d.ts +7 -10
  38. package/dist/handlers/tasks.js +230 -900
  39. package/dist/handlers/tool-docs.d.ts +8 -0
  40. package/dist/handlers/tool-docs.js +657 -0
  41. package/dist/handlers/types.d.ts +11 -3
  42. package/dist/handlers/validation.d.ts +1 -1
  43. package/dist/handlers/validation.js +26 -153
  44. package/dist/index.js +473 -160
  45. package/dist/knowledge.js +106 -9
  46. package/dist/tools.js +4 -0
  47. package/dist/validators.d.ts +21 -0
  48. package/dist/validators.js +91 -0
  49. package/package.json +2 -3
  50. package/src/api-client.ts +1752 -0
  51. package/src/cli.test.ts +128 -302
  52. package/src/cli.ts +41 -285
  53. package/src/handlers/__test-setup__.ts +210 -0
  54. package/src/handlers/__test-utils__.ts +4 -134
  55. package/src/handlers/blockers.test.ts +114 -124
  56. package/src/handlers/blockers.ts +68 -70
  57. package/src/handlers/bodies-of-work.test.ts +236 -831
  58. package/src/handlers/bodies-of-work.ts +194 -525
  59. package/src/handlers/cost.test.ts +149 -113
  60. package/src/handlers/cost.ts +44 -132
  61. package/src/handlers/decisions.test.ts +111 -209
  62. package/src/handlers/decisions.ts +35 -27
  63. package/src/handlers/deployment.test.ts +193 -239
  64. package/src/handlers/deployment.ts +140 -895
  65. package/src/handlers/discovery.test.ts +20 -67
  66. package/src/handlers/discovery.ts +32 -0
  67. package/src/handlers/fallback.test.ts +128 -361
  68. package/src/handlers/fallback.ts +62 -148
  69. package/src/handlers/findings.test.ts +127 -345
  70. package/src/handlers/findings.ts +49 -66
  71. package/src/handlers/git-issues.test.ts +623 -0
  72. package/src/handlers/git-issues.ts +174 -0
  73. package/src/handlers/ideas.test.ts +229 -343
  74. package/src/handlers/ideas.ts +69 -143
  75. package/src/handlers/index.ts +6 -0
  76. package/src/handlers/milestones.test.ts +167 -281
  77. package/src/handlers/milestones.ts +54 -93
  78. package/src/handlers/organizations.test.ts +275 -467
  79. package/src/handlers/organizations.ts +84 -294
  80. package/src/handlers/progress.test.ts +112 -218
  81. package/src/handlers/progress.ts +29 -142
  82. package/src/handlers/project.test.ts +203 -226
  83. package/src/handlers/project.ts +48 -238
  84. package/src/handlers/requests.test.ts +74 -342
  85. package/src/handlers/requests.ts +25 -83
  86. package/src/handlers/session.test.ts +241 -206
  87. package/src/handlers/session.ts +110 -657
  88. package/src/handlers/sprints.test.ts +711 -0
  89. package/src/handlers/sprints.ts +497 -0
  90. package/src/handlers/tasks.test.ts +608 -353
  91. package/src/handlers/tasks.ts +248 -1025
  92. package/src/handlers/types.ts +12 -4
  93. package/src/handlers/validation.test.ts +189 -572
  94. package/src/handlers/validation.ts +29 -166
  95. package/src/index.ts +473 -184
  96. package/src/knowledge.ts +107 -9
  97. package/src/tools.ts +2506 -0
  98. package/src/validators.test.ts +223 -223
  99. package/src/validators.ts +127 -0
  100. package/tsconfig.json +1 -1
  101. package/vitest.config.ts +14 -13
  102. package/dist/cli.test.d.ts +0 -1
  103. package/dist/cli.test.js +0 -367
  104. package/dist/handlers/__test-utils__.d.ts +0 -72
  105. package/dist/handlers/__test-utils__.js +0 -176
  106. package/dist/handlers/checkouts.d.ts +0 -37
  107. package/dist/handlers/checkouts.js +0 -377
  108. package/dist/handlers/knowledge-query.d.ts +0 -22
  109. package/dist/handlers/knowledge-query.js +0 -253
  110. package/dist/handlers/knowledge.d.ts +0 -12
  111. package/dist/handlers/knowledge.js +0 -108
  112. package/dist/handlers/roles.d.ts +0 -30
  113. package/dist/handlers/roles.js +0 -281
  114. package/dist/handlers/tasks.test.d.ts +0 -1
  115. package/dist/handlers/tasks.test.js +0 -431
  116. package/dist/utils.test.d.ts +0 -1
  117. package/dist/utils.test.js +0 -532
  118. package/dist/validators.test.d.ts +0 -1
  119. package/dist/validators.test.js +0 -176
  120. package/src/tmpclaude-0078-cwd +0 -1
  121. package/src/tmpclaude-0ee1-cwd +0 -1
  122. package/src/tmpclaude-2dd5-cwd +0 -1
  123. package/src/tmpclaude-344c-cwd +0 -1
  124. package/src/tmpclaude-3860-cwd +0 -1
  125. package/src/tmpclaude-4b63-cwd +0 -1
  126. package/src/tmpclaude-5c73-cwd +0 -1
  127. package/src/tmpclaude-5ee3-cwd +0 -1
  128. package/src/tmpclaude-6795-cwd +0 -1
  129. package/src/tmpclaude-709e-cwd +0 -1
  130. package/src/tmpclaude-9839-cwd +0 -1
  131. package/src/tmpclaude-d829-cwd +0 -1
  132. package/src/tmpclaude-e072-cwd +0 -1
  133. package/src/tmpclaude-f6ee-cwd +0 -1
  134. package/tmpclaude-0439-cwd +0 -1
  135. package/tmpclaude-132f-cwd +0 -1
  136. package/tmpclaude-15bb-cwd +0 -1
  137. package/tmpclaude-165a-cwd +0 -1
  138. package/tmpclaude-1ba9-cwd +0 -1
  139. package/tmpclaude-21a3-cwd +0 -1
  140. package/tmpclaude-2a38-cwd +0 -1
  141. package/tmpclaude-2adf-cwd +0 -1
  142. package/tmpclaude-2f56-cwd +0 -1
  143. package/tmpclaude-3626-cwd +0 -1
  144. package/tmpclaude-3727-cwd +0 -1
  145. package/tmpclaude-40bc-cwd +0 -1
  146. package/tmpclaude-436f-cwd +0 -1
  147. package/tmpclaude-4783-cwd +0 -1
  148. package/tmpclaude-4b6d-cwd +0 -1
  149. package/tmpclaude-4ba4-cwd +0 -1
  150. package/tmpclaude-51e6-cwd +0 -1
  151. package/tmpclaude-5ecf-cwd +0 -1
  152. package/tmpclaude-6f97-cwd +0 -1
  153. package/tmpclaude-7fb2-cwd +0 -1
  154. package/tmpclaude-825c-cwd +0 -1
  155. package/tmpclaude-8baf-cwd +0 -1
  156. package/tmpclaude-8d9f-cwd +0 -1
  157. package/tmpclaude-975c-cwd +0 -1
  158. package/tmpclaude-9983-cwd +0 -1
  159. package/tmpclaude-a045-cwd +0 -1
  160. package/tmpclaude-ac4a-cwd +0 -1
  161. package/tmpclaude-b593-cwd +0 -1
  162. package/tmpclaude-b891-cwd +0 -1
  163. package/tmpclaude-c032-cwd +0 -1
  164. package/tmpclaude-cf43-cwd +0 -1
  165. package/tmpclaude-d040-cwd +0 -1
  166. package/tmpclaude-dcdd-cwd +0 -1
  167. package/tmpclaude-dcee-cwd +0 -1
  168. package/tmpclaude-e16b-cwd +0 -1
  169. package/tmpclaude-ecd2-cwd +0 -1
  170. 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
  /**