@vibescope/mcp-server 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -0
- package/dist/cli.d.ts +34 -0
- package/dist/cli.js +356 -0
- package/dist/cli.test.d.ts +1 -0
- package/dist/cli.test.js +367 -0
- package/dist/handlers/__test-utils__.d.ts +72 -0
- package/dist/handlers/__test-utils__.js +176 -0
- package/dist/handlers/blockers.d.ts +18 -0
- package/dist/handlers/blockers.js +81 -0
- package/dist/handlers/bodies-of-work.d.ts +34 -0
- package/dist/handlers/bodies-of-work.js +614 -0
- package/dist/handlers/checkouts.d.ts +37 -0
- package/dist/handlers/checkouts.js +377 -0
- package/dist/handlers/cost.d.ts +39 -0
- package/dist/handlers/cost.js +247 -0
- package/dist/handlers/decisions.d.ts +16 -0
- package/dist/handlers/decisions.js +64 -0
- package/dist/handlers/deployment.d.ts +36 -0
- package/dist/handlers/deployment.js +1062 -0
- package/dist/handlers/discovery.d.ts +14 -0
- package/dist/handlers/discovery.js +870 -0
- package/dist/handlers/fallback.d.ts +18 -0
- package/dist/handlers/fallback.js +216 -0
- package/dist/handlers/findings.d.ts +18 -0
- package/dist/handlers/findings.js +110 -0
- package/dist/handlers/git-issues.d.ts +22 -0
- package/dist/handlers/git-issues.js +247 -0
- package/dist/handlers/ideas.d.ts +19 -0
- package/dist/handlers/ideas.js +188 -0
- package/dist/handlers/index.d.ts +29 -0
- package/dist/handlers/index.js +65 -0
- package/dist/handlers/knowledge-query.d.ts +22 -0
- package/dist/handlers/knowledge-query.js +253 -0
- package/dist/handlers/knowledge.d.ts +12 -0
- package/dist/handlers/knowledge.js +108 -0
- package/dist/handlers/milestones.d.ts +20 -0
- package/dist/handlers/milestones.js +179 -0
- package/dist/handlers/organizations.d.ts +36 -0
- package/dist/handlers/organizations.js +428 -0
- package/dist/handlers/progress.d.ts +14 -0
- package/dist/handlers/progress.js +149 -0
- package/dist/handlers/project.d.ts +20 -0
- package/dist/handlers/project.js +278 -0
- package/dist/handlers/requests.d.ts +16 -0
- package/dist/handlers/requests.js +131 -0
- package/dist/handlers/roles.d.ts +30 -0
- package/dist/handlers/roles.js +281 -0
- package/dist/handlers/session.d.ts +20 -0
- package/dist/handlers/session.js +791 -0
- package/dist/handlers/tasks.d.ts +52 -0
- package/dist/handlers/tasks.js +1111 -0
- package/dist/handlers/tasks.test.d.ts +1 -0
- package/dist/handlers/tasks.test.js +431 -0
- package/dist/handlers/types.d.ts +94 -0
- package/dist/handlers/types.js +1 -0
- package/dist/handlers/validation.d.ts +16 -0
- package/dist/handlers/validation.js +188 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2707 -0
- package/dist/knowledge.d.ts +6 -0
- package/dist/knowledge.js +121 -0
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +2498 -0
- package/dist/utils.d.ts +149 -0
- package/dist/utils.js +317 -0
- package/dist/utils.test.d.ts +1 -0
- package/dist/utils.test.js +532 -0
- package/dist/validators.d.ts +35 -0
- package/dist/validators.js +111 -0
- package/dist/validators.test.d.ts +1 -0
- package/dist/validators.test.js +176 -0
- package/package.json +44 -0
- package/src/cli.test.ts +442 -0
- package/src/cli.ts +439 -0
- package/src/handlers/__test-utils__.ts +217 -0
- package/src/handlers/blockers.test.ts +390 -0
- package/src/handlers/blockers.ts +110 -0
- package/src/handlers/bodies-of-work.test.ts +1276 -0
- package/src/handlers/bodies-of-work.ts +783 -0
- package/src/handlers/cost.test.ts +436 -0
- package/src/handlers/cost.ts +322 -0
- package/src/handlers/decisions.test.ts +401 -0
- package/src/handlers/decisions.ts +86 -0
- package/src/handlers/deployment.test.ts +516 -0
- package/src/handlers/deployment.ts +1289 -0
- package/src/handlers/discovery.test.ts +254 -0
- package/src/handlers/discovery.ts +969 -0
- package/src/handlers/fallback.test.ts +687 -0
- package/src/handlers/fallback.ts +260 -0
- package/src/handlers/findings.test.ts +565 -0
- package/src/handlers/findings.ts +153 -0
- package/src/handlers/ideas.test.ts +753 -0
- package/src/handlers/ideas.ts +247 -0
- package/src/handlers/index.ts +69 -0
- package/src/handlers/milestones.test.ts +584 -0
- package/src/handlers/milestones.ts +217 -0
- package/src/handlers/organizations.test.ts +997 -0
- package/src/handlers/organizations.ts +550 -0
- package/src/handlers/progress.test.ts +369 -0
- package/src/handlers/progress.ts +188 -0
- package/src/handlers/project.test.ts +562 -0
- package/src/handlers/project.ts +352 -0
- package/src/handlers/requests.test.ts +531 -0
- package/src/handlers/requests.ts +150 -0
- package/src/handlers/session.test.ts +459 -0
- package/src/handlers/session.ts +912 -0
- package/src/handlers/tasks.test.ts +602 -0
- package/src/handlers/tasks.ts +1393 -0
- package/src/handlers/types.ts +88 -0
- package/src/handlers/validation.test.ts +880 -0
- package/src/handlers/validation.ts +223 -0
- package/src/index.ts +3205 -0
- package/src/knowledge.ts +132 -0
- package/src/tmpclaude-0078-cwd +1 -0
- package/src/tmpclaude-0ee1-cwd +1 -0
- package/src/tmpclaude-2dd5-cwd +1 -0
- package/src/tmpclaude-344c-cwd +1 -0
- package/src/tmpclaude-3860-cwd +1 -0
- package/src/tmpclaude-4b63-cwd +1 -0
- package/src/tmpclaude-5c73-cwd +1 -0
- package/src/tmpclaude-5ee3-cwd +1 -0
- package/src/tmpclaude-6795-cwd +1 -0
- package/src/tmpclaude-709e-cwd +1 -0
- package/src/tmpclaude-9839-cwd +1 -0
- package/src/tmpclaude-d829-cwd +1 -0
- package/src/tmpclaude-e072-cwd +1 -0
- package/src/tmpclaude-f6ee-cwd +1 -0
- package/src/utils.test.ts +681 -0
- package/src/utils.ts +375 -0
- package/src/validators.test.ts +223 -0
- package/src/validators.ts +122 -0
- package/tmpclaude-0439-cwd +1 -0
- package/tmpclaude-132f-cwd +1 -0
- package/tmpclaude-15bb-cwd +1 -0
- package/tmpclaude-165a-cwd +1 -0
- package/tmpclaude-1ba9-cwd +1 -0
- package/tmpclaude-21a3-cwd +1 -0
- package/tmpclaude-2a38-cwd +1 -0
- package/tmpclaude-2adf-cwd +1 -0
- package/tmpclaude-2f56-cwd +1 -0
- package/tmpclaude-3626-cwd +1 -0
- package/tmpclaude-3727-cwd +1 -0
- package/tmpclaude-40bc-cwd +1 -0
- package/tmpclaude-436f-cwd +1 -0
- package/tmpclaude-4783-cwd +1 -0
- package/tmpclaude-4b6d-cwd +1 -0
- package/tmpclaude-4ba4-cwd +1 -0
- package/tmpclaude-51e6-cwd +1 -0
- package/tmpclaude-5ecf-cwd +1 -0
- package/tmpclaude-6f97-cwd +1 -0
- package/tmpclaude-7fb2-cwd +1 -0
- package/tmpclaude-825c-cwd +1 -0
- package/tmpclaude-8baf-cwd +1 -0
- package/tmpclaude-8d9f-cwd +1 -0
- package/tmpclaude-975c-cwd +1 -0
- package/tmpclaude-9983-cwd +1 -0
- package/tmpclaude-a045-cwd +1 -0
- package/tmpclaude-ac4a-cwd +1 -0
- package/tmpclaude-b593-cwd +1 -0
- package/tmpclaude-b891-cwd +1 -0
- package/tmpclaude-c032-cwd +1 -0
- package/tmpclaude-cf43-cwd +1 -0
- package/tmpclaude-d040-cwd +1 -0
- package/tmpclaude-dcdd-cwd +1 -0
- package/tmpclaude-dcee-cwd +1 -0
- package/tmpclaude-e16b-cwd +1 -0
- package/tmpclaude-ecd2-cwd +1 -0
- package/tmpclaude-f48d-cwd +1 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role Handlers
|
|
3
|
+
*
|
|
4
|
+
* Manages agent roles for specialized work:
|
|
5
|
+
* - get_role_settings: Get role configuration for a project
|
|
6
|
+
* - update_role_settings: Update role settings
|
|
7
|
+
* - set_session_role: Change the current session's role
|
|
8
|
+
* - get_agents_by_role: Get active agents grouped by role
|
|
9
|
+
*/
|
|
10
|
+
import { validateUUID, validateRequired } from '../validators.js';
|
|
11
|
+
// Valid agent roles - must match AgentRole type in types.ts and database enum
|
|
12
|
+
const VALID_ROLES = ['developer', 'validator', 'deployer', 'reviewer', 'maintainer'];
|
|
13
|
+
function isValidRole(role) {
|
|
14
|
+
return VALID_ROLES.includes(role);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Verify the user owns or has access to the project
|
|
18
|
+
* This is needed because MCP server uses service_role which bypasses RLS
|
|
19
|
+
*/
|
|
20
|
+
async function verifyProjectAccess(ctx, projectId) {
|
|
21
|
+
const { supabase, auth } = ctx;
|
|
22
|
+
// Check if user owns the project
|
|
23
|
+
const { data: ownedProject } = await supabase
|
|
24
|
+
.from('projects')
|
|
25
|
+
.select('id')
|
|
26
|
+
.eq('id', projectId)
|
|
27
|
+
.eq('user_id', auth.userId)
|
|
28
|
+
.single();
|
|
29
|
+
if (ownedProject)
|
|
30
|
+
return;
|
|
31
|
+
// Check if project is shared with user's organization (for org-scoped keys)
|
|
32
|
+
if (auth.scope === 'organization' && auth.organizationId) {
|
|
33
|
+
const { data: sharedProject } = await supabase
|
|
34
|
+
.from('project_shares')
|
|
35
|
+
.select('project_id')
|
|
36
|
+
.eq('project_id', projectId)
|
|
37
|
+
.eq('organization_id', auth.organizationId)
|
|
38
|
+
.single();
|
|
39
|
+
if (sharedProject)
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
throw new Error('Project not found or access denied');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get role settings for a project
|
|
46
|
+
*/
|
|
47
|
+
export const getRoleSettings = async (args, ctx) => {
|
|
48
|
+
const { project_id } = args;
|
|
49
|
+
const { supabase } = ctx;
|
|
50
|
+
validateRequired(project_id, 'project_id');
|
|
51
|
+
validateUUID(project_id, 'project_id');
|
|
52
|
+
// Verify user has access to this project
|
|
53
|
+
await verifyProjectAccess(ctx, project_id);
|
|
54
|
+
const { data: settings, error } = await supabase
|
|
55
|
+
.from('project_role_settings')
|
|
56
|
+
.select('*')
|
|
57
|
+
.eq('project_id', project_id)
|
|
58
|
+
.order('role');
|
|
59
|
+
if (error) {
|
|
60
|
+
throw new Error(`Failed to get role settings: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
// If no settings exist, return defaults
|
|
63
|
+
if (!settings || settings.length === 0) {
|
|
64
|
+
return {
|
|
65
|
+
result: {
|
|
66
|
+
project_id,
|
|
67
|
+
settings: VALID_ROLES.map(role => ({
|
|
68
|
+
role,
|
|
69
|
+
enabled: true,
|
|
70
|
+
display_name: role.charAt(0).toUpperCase() + role.slice(1),
|
|
71
|
+
description: getRoleDescription(role),
|
|
72
|
+
})),
|
|
73
|
+
note: 'Using default settings. Call update_role_settings to customize.',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
result: {
|
|
79
|
+
project_id,
|
|
80
|
+
settings,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
function getRoleDescription(role) {
|
|
85
|
+
const descriptions = {
|
|
86
|
+
developer: 'General development work, picks up any available task',
|
|
87
|
+
validator: 'Focuses on validating completed tasks',
|
|
88
|
+
deployer: 'Handles deployment coordination and monitoring',
|
|
89
|
+
reviewer: 'Code review and quality checks',
|
|
90
|
+
maintainer: 'Task management, git orchestration, housekeeping',
|
|
91
|
+
};
|
|
92
|
+
return descriptions[role];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Update role settings for a project
|
|
96
|
+
*/
|
|
97
|
+
export const updateRoleSettings = async (args, ctx) => {
|
|
98
|
+
const { project_id, role, enabled, display_name, description, priority_filter, fallback_activities, auto_assign_validation, auto_assign_deployment, } = args;
|
|
99
|
+
const { supabase } = ctx;
|
|
100
|
+
validateRequired(project_id, 'project_id');
|
|
101
|
+
validateUUID(project_id, 'project_id');
|
|
102
|
+
validateRequired(role, 'role');
|
|
103
|
+
if (!isValidRole(role)) {
|
|
104
|
+
throw new Error(`Invalid role: ${role}. Valid roles: ${VALID_ROLES.join(', ')}`);
|
|
105
|
+
}
|
|
106
|
+
// Verify user has access to this project
|
|
107
|
+
await verifyProjectAccess(ctx, project_id);
|
|
108
|
+
const updates = {
|
|
109
|
+
updated_at: new Date().toISOString(),
|
|
110
|
+
};
|
|
111
|
+
if (enabled !== undefined)
|
|
112
|
+
updates.enabled = enabled;
|
|
113
|
+
if (display_name !== undefined)
|
|
114
|
+
updates.display_name = display_name;
|
|
115
|
+
if (description !== undefined)
|
|
116
|
+
updates.description = description;
|
|
117
|
+
if (priority_filter !== undefined)
|
|
118
|
+
updates.priority_filter = priority_filter;
|
|
119
|
+
if (fallback_activities !== undefined)
|
|
120
|
+
updates.fallback_activities = fallback_activities;
|
|
121
|
+
if (auto_assign_validation !== undefined)
|
|
122
|
+
updates.auto_assign_validation = auto_assign_validation;
|
|
123
|
+
if (auto_assign_deployment !== undefined)
|
|
124
|
+
updates.auto_assign_deployment = auto_assign_deployment;
|
|
125
|
+
// Upsert the role settings
|
|
126
|
+
const { data, error } = await supabase
|
|
127
|
+
.from('project_role_settings')
|
|
128
|
+
.upsert({
|
|
129
|
+
project_id,
|
|
130
|
+
role,
|
|
131
|
+
...updates,
|
|
132
|
+
}, {
|
|
133
|
+
onConflict: 'project_id,role',
|
|
134
|
+
})
|
|
135
|
+
.select()
|
|
136
|
+
.single();
|
|
137
|
+
if (error) {
|
|
138
|
+
throw new Error(`Failed to update role settings: ${error.message}`);
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
result: {
|
|
142
|
+
success: true,
|
|
143
|
+
settings: data,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Set the current session's role
|
|
149
|
+
*/
|
|
150
|
+
export const setSessionRole = async (args, ctx) => {
|
|
151
|
+
const { role, role_config } = args;
|
|
152
|
+
const { supabase, session, updateSession } = ctx;
|
|
153
|
+
validateRequired(role, 'role');
|
|
154
|
+
if (!isValidRole(role)) {
|
|
155
|
+
throw new Error(`Invalid role: ${role}. Valid roles: ${VALID_ROLES.join(', ')}`);
|
|
156
|
+
}
|
|
157
|
+
const sessionId = session.currentSessionId;
|
|
158
|
+
if (!sessionId) {
|
|
159
|
+
throw new Error('No active session. Call start_work_session first.');
|
|
160
|
+
}
|
|
161
|
+
const updates = {
|
|
162
|
+
role,
|
|
163
|
+
updated_at: new Date().toISOString(),
|
|
164
|
+
};
|
|
165
|
+
// Allow role_config for custom configurations (e.g., maintainer with specific focus areas)
|
|
166
|
+
if (role_config) {
|
|
167
|
+
updates.role_config = role_config;
|
|
168
|
+
}
|
|
169
|
+
const { error } = await supabase
|
|
170
|
+
.from('agent_sessions')
|
|
171
|
+
.update(updates)
|
|
172
|
+
.eq('id', sessionId);
|
|
173
|
+
if (error) {
|
|
174
|
+
throw new Error(`Failed to set role: ${error.message}`);
|
|
175
|
+
}
|
|
176
|
+
// Update session state
|
|
177
|
+
updateSession({ currentRole: role });
|
|
178
|
+
// Get role-specific guidance
|
|
179
|
+
const guidance = getRoleGuidance(role);
|
|
180
|
+
return {
|
|
181
|
+
result: {
|
|
182
|
+
success: true,
|
|
183
|
+
role,
|
|
184
|
+
persona: session.currentPersona,
|
|
185
|
+
guidance,
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
function getRoleGuidance(role) {
|
|
190
|
+
const guidance = {
|
|
191
|
+
developer: 'Focus on implementing features and fixing bugs. Use get_next_task to find work.',
|
|
192
|
+
validator: 'Prioritize validation tasks. Use get_tasks_awaiting_validation to find completed tasks to review.',
|
|
193
|
+
deployer: 'Monitor deployment status with check_deployment_status. Handle deployment requests and coordination.',
|
|
194
|
+
reviewer: 'Run code reviews using code_review fallback activity. Check for security and quality issues.',
|
|
195
|
+
maintainer: 'Handle task management, git orchestration. Run performance_audit, dependency_audit when idle.',
|
|
196
|
+
};
|
|
197
|
+
return guidance[role];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get active agents grouped by role
|
|
201
|
+
*/
|
|
202
|
+
export const getAgentsByRole = async (args, ctx) => {
|
|
203
|
+
const { project_id } = args;
|
|
204
|
+
const { supabase } = ctx;
|
|
205
|
+
validateRequired(project_id, 'project_id');
|
|
206
|
+
validateUUID(project_id, 'project_id');
|
|
207
|
+
// Verify user has access to this project
|
|
208
|
+
await verifyProjectAccess(ctx, project_id);
|
|
209
|
+
const { data: agents, error } = await supabase
|
|
210
|
+
.from('agent_sessions')
|
|
211
|
+
.select(`
|
|
212
|
+
id,
|
|
213
|
+
agent_name,
|
|
214
|
+
role,
|
|
215
|
+
status,
|
|
216
|
+
current_task_id,
|
|
217
|
+
last_synced_at,
|
|
218
|
+
role_config
|
|
219
|
+
`)
|
|
220
|
+
.eq('project_id', project_id)
|
|
221
|
+
.neq('status', 'disconnected')
|
|
222
|
+
.gte('last_synced_at', new Date(Date.now() - 5 * 60 * 1000).toISOString());
|
|
223
|
+
if (error) {
|
|
224
|
+
throw new Error(`Failed to get agents: ${error.message}`);
|
|
225
|
+
}
|
|
226
|
+
// Group by role
|
|
227
|
+
const byRole = {};
|
|
228
|
+
for (const agent of agents || []) {
|
|
229
|
+
const role = agent.role || 'developer';
|
|
230
|
+
if (!byRole[role]) {
|
|
231
|
+
byRole[role] = [];
|
|
232
|
+
}
|
|
233
|
+
byRole[role].push(agent);
|
|
234
|
+
}
|
|
235
|
+
// Get current task titles
|
|
236
|
+
const taskIds = (agents || [])
|
|
237
|
+
.map(a => a.current_task_id)
|
|
238
|
+
.filter((id) => !!id);
|
|
239
|
+
let taskTitles = {};
|
|
240
|
+
if (taskIds.length > 0) {
|
|
241
|
+
const { data: tasks } = await supabase
|
|
242
|
+
.from('tasks')
|
|
243
|
+
.select('id, title')
|
|
244
|
+
.in('id', taskIds);
|
|
245
|
+
taskTitles = (tasks || []).reduce((acc, t) => {
|
|
246
|
+
acc[t.id] = t.title;
|
|
247
|
+
return acc;
|
|
248
|
+
}, {});
|
|
249
|
+
}
|
|
250
|
+
// Enrich agents with task titles
|
|
251
|
+
const enrichedByRole = {};
|
|
252
|
+
for (const [role, roleAgents] of Object.entries(byRole)) {
|
|
253
|
+
enrichedByRole[role] = roleAgents.map(agent => ({
|
|
254
|
+
id: agent.id,
|
|
255
|
+
agent_name: agent.agent_name,
|
|
256
|
+
role: agent.role || 'developer',
|
|
257
|
+
status: agent.status,
|
|
258
|
+
current_task: agent.current_task_id
|
|
259
|
+
? { id: agent.current_task_id, title: taskTitles[agent.current_task_id] || 'Unknown' }
|
|
260
|
+
: null,
|
|
261
|
+
last_synced_at: agent.last_synced_at,
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
result: {
|
|
266
|
+
project_id,
|
|
267
|
+
total_agents: agents?.length || 0,
|
|
268
|
+
by_role: enrichedByRole,
|
|
269
|
+
available_roles: VALID_ROLES,
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* Role handlers registry
|
|
275
|
+
*/
|
|
276
|
+
export const roleHandlers = {
|
|
277
|
+
get_role_settings: getRoleSettings,
|
|
278
|
+
update_role_settings: updateRoleSettings,
|
|
279
|
+
set_session_role: setSessionRole,
|
|
280
|
+
get_agents_by_role: getAgentsByRole,
|
|
281
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Handlers
|
|
3
|
+
*
|
|
4
|
+
* Handles agent session lifecycle:
|
|
5
|
+
* - start_work_session
|
|
6
|
+
* - heartbeat
|
|
7
|
+
* - end_work_session
|
|
8
|
+
* - get_help
|
|
9
|
+
* - get_token_usage
|
|
10
|
+
*/
|
|
11
|
+
import type { Handler, HandlerRegistry } from './types.js';
|
|
12
|
+
export declare const startWorkSession: Handler;
|
|
13
|
+
export declare const heartbeat: Handler;
|
|
14
|
+
export declare const endWorkSession: Handler;
|
|
15
|
+
export declare const getHelp: Handler;
|
|
16
|
+
export declare const getTokenUsage: Handler;
|
|
17
|
+
/**
|
|
18
|
+
* Session handlers registry
|
|
19
|
+
*/
|
|
20
|
+
export declare const sessionHandlers: HandlerRegistry;
|