@vibescope/mcp-server 0.2.0 → 0.2.2
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 +60 -7
- package/dist/api-client.d.ts +251 -1
- package/dist/api-client.js +82 -3
- package/dist/handlers/blockers.js +9 -8
- package/dist/handlers/bodies-of-work.js +96 -63
- package/dist/handlers/connectors.d.ts +45 -0
- package/dist/handlers/connectors.js +183 -0
- package/dist/handlers/cost.d.ts +10 -0
- package/dist/handlers/cost.js +112 -50
- package/dist/handlers/decisions.js +32 -19
- package/dist/handlers/deployment.js +144 -122
- package/dist/handlers/discovery.d.ts +7 -0
- package/dist/handlers/discovery.js +96 -7
- package/dist/handlers/fallback.js +29 -23
- package/dist/handlers/file-checkouts.d.ts +20 -0
- package/dist/handlers/file-checkouts.js +133 -0
- package/dist/handlers/findings.d.ts +6 -0
- package/dist/handlers/findings.js +96 -40
- package/dist/handlers/git-issues.js +40 -36
- package/dist/handlers/ideas.js +49 -31
- package/dist/handlers/index.d.ts +3 -0
- package/dist/handlers/index.js +9 -0
- package/dist/handlers/milestones.js +39 -32
- package/dist/handlers/organizations.js +99 -91
- package/dist/handlers/progress.js +24 -13
- package/dist/handlers/project.js +68 -28
- package/dist/handlers/requests.js +18 -14
- package/dist/handlers/roles.d.ts +18 -0
- package/dist/handlers/roles.js +130 -0
- package/dist/handlers/session.js +58 -17
- package/dist/handlers/sprints.js +93 -81
- package/dist/handlers/tasks.d.ts +2 -0
- package/dist/handlers/tasks.js +189 -91
- package/dist/handlers/types.d.ts +64 -2
- package/dist/handlers/types.js +48 -1
- package/dist/handlers/validation.js +21 -17
- package/dist/index.js +7 -2716
- package/dist/token-tracking.d.ts +74 -0
- package/dist/token-tracking.js +122 -0
- package/dist/tools.js +685 -9
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +17 -0
- package/docs/TOOLS.md +2053 -0
- package/package.json +4 -1
- package/scripts/generate-docs.ts +212 -0
- package/src/api-client.test.ts +718 -0
- package/src/api-client.ts +320 -6
- package/src/handlers/__test-setup__.ts +16 -0
- package/src/handlers/blockers.test.ts +31 -19
- package/src/handlers/blockers.ts +9 -8
- package/src/handlers/bodies-of-work.test.ts +55 -32
- package/src/handlers/bodies-of-work.ts +115 -115
- package/src/handlers/connectors.test.ts +834 -0
- package/src/handlers/connectors.ts +229 -0
- package/src/handlers/cost.test.ts +34 -44
- package/src/handlers/cost.ts +136 -85
- package/src/handlers/decisions.test.ts +37 -27
- package/src/handlers/decisions.ts +35 -30
- package/src/handlers/deployment.ts +180 -208
- package/src/handlers/discovery.test.ts +4 -5
- package/src/handlers/discovery.ts +98 -8
- package/src/handlers/fallback.test.ts +26 -22
- package/src/handlers/fallback.ts +36 -33
- package/src/handlers/file-checkouts.test.ts +670 -0
- package/src/handlers/file-checkouts.ts +165 -0
- package/src/handlers/findings.test.ts +178 -19
- package/src/handlers/findings.ts +112 -74
- package/src/handlers/git-issues.test.ts +51 -43
- package/src/handlers/git-issues.ts +44 -84
- package/src/handlers/ideas.test.ts +28 -23
- package/src/handlers/ideas.ts +61 -59
- package/src/handlers/index.ts +9 -0
- package/src/handlers/milestones.test.ts +33 -28
- package/src/handlers/milestones.ts +52 -50
- package/src/handlers/organizations.test.ts +104 -83
- package/src/handlers/organizations.ts +117 -142
- package/src/handlers/progress.test.ts +20 -14
- package/src/handlers/progress.ts +26 -24
- package/src/handlers/project.test.ts +34 -27
- package/src/handlers/project.ts +95 -63
- package/src/handlers/requests.test.ts +27 -18
- package/src/handlers/requests.ts +21 -17
- package/src/handlers/roles.test.ts +303 -0
- package/src/handlers/roles.ts +208 -0
- package/src/handlers/session.test.ts +47 -0
- package/src/handlers/session.ts +71 -26
- package/src/handlers/sprints.test.ts +71 -50
- package/src/handlers/sprints.ts +113 -146
- package/src/handlers/tasks.test.ts +77 -15
- package/src/handlers/tasks.ts +231 -156
- package/src/handlers/tool-categories.test.ts +66 -0
- package/src/handlers/types.ts +81 -2
- package/src/handlers/validation.test.ts +78 -45
- package/src/handlers/validation.ts +23 -25
- package/src/index.ts +12 -2732
- package/src/token-tracking.test.ts +453 -0
- package/src/token-tracking.ts +164 -0
- package/src/tools.ts +685 -9
- package/src/utils.test.ts +2 -2
- package/src/utils.ts +17 -0
- package/dist/config/tool-categories.d.ts +0 -31
- package/dist/config/tool-categories.js +0 -253
- package/dist/knowledge.d.ts +0 -6
- package/dist/knowledge.js +0 -218
package/dist/handlers/cost.js
CHANGED
|
@@ -8,21 +8,66 @@
|
|
|
8
8
|
* - update_cost_alert
|
|
9
9
|
* - delete_cost_alert
|
|
10
10
|
* - get_task_costs
|
|
11
|
+
* - get_body_of_work_costs
|
|
12
|
+
* - get_sprint_costs
|
|
11
13
|
*/
|
|
14
|
+
import { parseArgs, uuidValidator, createEnumValidator, ValidationError } from '../validators.js';
|
|
12
15
|
import { getApiClient } from '../api-client.js';
|
|
16
|
+
const VALID_PERIODS = ['daily', 'weekly', 'monthly'];
|
|
17
|
+
const VALID_ALERT_TYPES = ['warning', 'critical'];
|
|
18
|
+
// Argument schemas for type-safe parsing
|
|
19
|
+
const getCostSummarySchema = {
|
|
20
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
21
|
+
period: { type: 'string', default: 'daily', validate: createEnumValidator(VALID_PERIODS) },
|
|
22
|
+
limit: { type: 'number', default: 30 },
|
|
23
|
+
};
|
|
24
|
+
const getCostAlertsSchema = {
|
|
25
|
+
project_id: { type: 'string', validate: uuidValidator },
|
|
26
|
+
};
|
|
27
|
+
const addCostAlertSchema = {
|
|
28
|
+
project_id: { type: 'string', validate: uuidValidator },
|
|
29
|
+
threshold_amount: { type: 'number', required: true },
|
|
30
|
+
threshold_period: { type: 'string', required: true, validate: createEnumValidator(VALID_PERIODS) },
|
|
31
|
+
alert_type: { type: 'string', default: 'warning', validate: createEnumValidator(VALID_ALERT_TYPES) },
|
|
32
|
+
};
|
|
33
|
+
const updateCostAlertSchema = {
|
|
34
|
+
alert_id: { type: 'string', required: true, validate: uuidValidator },
|
|
35
|
+
threshold_amount: { type: 'number' },
|
|
36
|
+
threshold_period: { type: 'string', validate: createEnumValidator(VALID_PERIODS) },
|
|
37
|
+
alert_type: { type: 'string', validate: createEnumValidator(VALID_ALERT_TYPES) },
|
|
38
|
+
enabled: { type: 'boolean' },
|
|
39
|
+
};
|
|
40
|
+
const deleteCostAlertSchema = {
|
|
41
|
+
alert_id: { type: 'string', required: true, validate: uuidValidator },
|
|
42
|
+
};
|
|
43
|
+
const getTaskCostsSchema = {
|
|
44
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
45
|
+
limit: { type: 'number', default: 20 },
|
|
46
|
+
};
|
|
47
|
+
const getBodyOfWorkCostsSchema = {
|
|
48
|
+
body_of_work_id: { type: 'string', validate: uuidValidator },
|
|
49
|
+
project_id: { type: 'string', validate: uuidValidator },
|
|
50
|
+
};
|
|
51
|
+
const getSprintCostsSchema = {
|
|
52
|
+
sprint_id: { type: 'string', validate: uuidValidator },
|
|
53
|
+
project_id: { type: 'string', validate: uuidValidator },
|
|
54
|
+
};
|
|
55
|
+
// Custom validator for positive numbers
|
|
56
|
+
function validatePositiveNumber(value, fieldName) {
|
|
57
|
+
if (value !== undefined && value <= 0) {
|
|
58
|
+
throw new ValidationError(`${fieldName} must be a positive number`, { field: fieldName });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
13
61
|
/**
|
|
14
62
|
* Get cost summary for a project (daily, weekly, or monthly)
|
|
15
63
|
*/
|
|
16
|
-
export const getCostSummary = async (args,
|
|
17
|
-
const { project_id, period
|
|
18
|
-
if (!project_id) {
|
|
19
|
-
return {
|
|
20
|
-
result: { error: 'project_id is required' },
|
|
21
|
-
isError: true,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
64
|
+
export const getCostSummary = async (args, _ctx) => {
|
|
65
|
+
const { project_id, period, limit } = parseArgs(args, getCostSummarySchema);
|
|
24
66
|
const apiClient = getApiClient();
|
|
25
|
-
const response = await apiClient.getCostSummary(project_id, {
|
|
67
|
+
const response = await apiClient.getCostSummary(project_id, {
|
|
68
|
+
period: period,
|
|
69
|
+
limit
|
|
70
|
+
});
|
|
26
71
|
if (!response.ok) {
|
|
27
72
|
return {
|
|
28
73
|
result: { error: response.error || 'Failed to get cost summary' },
|
|
@@ -34,8 +79,8 @@ export const getCostSummary = async (args, ctx) => {
|
|
|
34
79
|
/**
|
|
35
80
|
* Get cost alerts for the current user
|
|
36
81
|
*/
|
|
37
|
-
export const getCostAlerts = async (args,
|
|
38
|
-
const { project_id } = args;
|
|
82
|
+
export const getCostAlerts = async (args, _ctx) => {
|
|
83
|
+
const { project_id } = parseArgs(args, getCostAlertsSchema);
|
|
39
84
|
const apiClient = getApiClient();
|
|
40
85
|
const response = await apiClient.getCostAlerts();
|
|
41
86
|
if (!response.ok) {
|
|
@@ -49,26 +94,16 @@ export const getCostAlerts = async (args, ctx) => {
|
|
|
49
94
|
/**
|
|
50
95
|
* Add a cost alert
|
|
51
96
|
*/
|
|
52
|
-
export const addCostAlert = async (args,
|
|
53
|
-
const { project_id, threshold_amount, threshold_period, alert_type
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
result: { error: 'threshold_amount must be a positive number' },
|
|
57
|
-
isError: true,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
if (!threshold_period || !['daily', 'weekly', 'monthly'].includes(threshold_period)) {
|
|
61
|
-
return {
|
|
62
|
-
result: { error: 'threshold_period must be "daily", "weekly", or "monthly"' },
|
|
63
|
-
isError: true,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
97
|
+
export const addCostAlert = async (args, _ctx) => {
|
|
98
|
+
const { project_id, threshold_amount, threshold_period, alert_type } = parseArgs(args, addCostAlertSchema);
|
|
99
|
+
// Additional validation for positive amount
|
|
100
|
+
validatePositiveNumber(threshold_amount, 'threshold_amount');
|
|
66
101
|
const apiClient = getApiClient();
|
|
67
102
|
const response = await apiClient.addCostAlert({
|
|
68
103
|
project_id,
|
|
69
|
-
threshold_amount,
|
|
70
|
-
threshold_period,
|
|
71
|
-
alert_type
|
|
104
|
+
threshold_amount: threshold_amount,
|
|
105
|
+
threshold_period: threshold_period,
|
|
106
|
+
alert_type: alert_type
|
|
72
107
|
});
|
|
73
108
|
if (!response.ok) {
|
|
74
109
|
return {
|
|
@@ -81,11 +116,12 @@ export const addCostAlert = async (args, ctx) => {
|
|
|
81
116
|
/**
|
|
82
117
|
* Update a cost alert
|
|
83
118
|
*/
|
|
84
|
-
export const updateCostAlert = async (args,
|
|
85
|
-
const { alert_id, threshold_amount, threshold_period, alert_type, enabled
|
|
86
|
-
|
|
119
|
+
export const updateCostAlert = async (args, _ctx) => {
|
|
120
|
+
const { alert_id, threshold_amount, threshold_period, alert_type, enabled } = parseArgs(args, updateCostAlertSchema);
|
|
121
|
+
// Check that at least one update is provided
|
|
122
|
+
if (threshold_amount === undefined && threshold_period === undefined && alert_type === undefined && enabled === undefined) {
|
|
87
123
|
return {
|
|
88
|
-
result: { error: '
|
|
124
|
+
result: { error: 'No updates provided' },
|
|
89
125
|
isError: true,
|
|
90
126
|
};
|
|
91
127
|
}
|
|
@@ -98,59 +134,83 @@ export const updateCostAlert = async (args, ctx) => {
|
|
|
98
134
|
updates.alert_type = alert_type;
|
|
99
135
|
if (enabled !== undefined)
|
|
100
136
|
updates.enabled = enabled;
|
|
101
|
-
|
|
137
|
+
const apiClient = getApiClient();
|
|
138
|
+
const response = await apiClient.updateCostAlert(alert_id, updates);
|
|
139
|
+
if (!response.ok) {
|
|
102
140
|
return {
|
|
103
|
-
result: { error: '
|
|
141
|
+
result: { error: response.error || 'Failed to update cost alert' },
|
|
104
142
|
isError: true,
|
|
105
143
|
};
|
|
106
144
|
}
|
|
145
|
+
return { result: response.data };
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Delete a cost alert
|
|
149
|
+
*/
|
|
150
|
+
export const deleteCostAlert = async (args, _ctx) => {
|
|
151
|
+
const { alert_id } = parseArgs(args, deleteCostAlertSchema);
|
|
107
152
|
const apiClient = getApiClient();
|
|
108
|
-
const response = await apiClient.
|
|
153
|
+
const response = await apiClient.deleteCostAlert(alert_id);
|
|
109
154
|
if (!response.ok) {
|
|
110
155
|
return {
|
|
111
|
-
result: { error: response.error || 'Failed to
|
|
156
|
+
result: { error: response.error || 'Failed to delete cost alert' },
|
|
112
157
|
isError: true,
|
|
113
158
|
};
|
|
114
159
|
}
|
|
115
160
|
return { result: response.data };
|
|
116
161
|
};
|
|
117
162
|
/**
|
|
118
|
-
*
|
|
163
|
+
* Get task costs for a project
|
|
164
|
+
*/
|
|
165
|
+
export const getTaskCosts = async (args, _ctx) => {
|
|
166
|
+
const { project_id, limit } = parseArgs(args, getTaskCostsSchema);
|
|
167
|
+
const apiClient = getApiClient();
|
|
168
|
+
const response = await apiClient.getTaskCosts(project_id, limit);
|
|
169
|
+
if (!response.ok) {
|
|
170
|
+
return {
|
|
171
|
+
result: { error: response.error || 'Failed to get task costs' },
|
|
172
|
+
isError: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return { result: response.data };
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Get body of work costs with phase breakdown
|
|
119
179
|
*/
|
|
120
|
-
export const
|
|
121
|
-
const {
|
|
122
|
-
if (!
|
|
180
|
+
export const getBodyOfWorkCosts = async (args, _ctx) => {
|
|
181
|
+
const { body_of_work_id, project_id } = parseArgs(args, getBodyOfWorkCostsSchema);
|
|
182
|
+
if (!body_of_work_id && !project_id) {
|
|
123
183
|
return {
|
|
124
|
-
result: { error: '
|
|
184
|
+
result: { error: 'Either body_of_work_id or project_id is required' },
|
|
125
185
|
isError: true,
|
|
126
186
|
};
|
|
127
187
|
}
|
|
128
188
|
const apiClient = getApiClient();
|
|
129
|
-
const response = await apiClient.
|
|
189
|
+
const response = await apiClient.getBodyOfWorkCosts({ body_of_work_id, project_id });
|
|
130
190
|
if (!response.ok) {
|
|
131
191
|
return {
|
|
132
|
-
result: { error: response.error || 'Failed to
|
|
192
|
+
result: { error: response.error || 'Failed to get body of work costs' },
|
|
133
193
|
isError: true,
|
|
134
194
|
};
|
|
135
195
|
}
|
|
136
196
|
return { result: response.data };
|
|
137
197
|
};
|
|
138
198
|
/**
|
|
139
|
-
* Get
|
|
199
|
+
* Get sprint costs with velocity metrics
|
|
140
200
|
*/
|
|
141
|
-
export const
|
|
142
|
-
const {
|
|
143
|
-
if (!project_id) {
|
|
201
|
+
export const getSprintCosts = async (args, _ctx) => {
|
|
202
|
+
const { sprint_id, project_id } = parseArgs(args, getSprintCostsSchema);
|
|
203
|
+
if (!sprint_id && !project_id) {
|
|
144
204
|
return {
|
|
145
|
-
result: { error: 'project_id is required' },
|
|
205
|
+
result: { error: 'Either sprint_id or project_id is required' },
|
|
146
206
|
isError: true,
|
|
147
207
|
};
|
|
148
208
|
}
|
|
149
209
|
const apiClient = getApiClient();
|
|
150
|
-
const response = await apiClient.
|
|
210
|
+
const response = await apiClient.getSprintCosts({ sprint_id, project_id });
|
|
151
211
|
if (!response.ok) {
|
|
152
212
|
return {
|
|
153
|
-
result: { error: response.error || 'Failed to get
|
|
213
|
+
result: { error: response.error || 'Failed to get sprint costs' },
|
|
154
214
|
isError: true,
|
|
155
215
|
};
|
|
156
216
|
}
|
|
@@ -166,4 +226,6 @@ export const costHandlers = {
|
|
|
166
226
|
update_cost_alert: updateCostAlert,
|
|
167
227
|
delete_cost_alert: deleteCostAlert,
|
|
168
228
|
get_task_costs: getTaskCosts,
|
|
229
|
+
get_body_of_work_costs: getBodyOfWorkCosts,
|
|
230
|
+
get_sprint_costs: getSprintCosts,
|
|
169
231
|
};
|
|
@@ -8,35 +8,50 @@
|
|
|
8
8
|
*
|
|
9
9
|
* MIGRATED: Uses Vibescope API client instead of direct Supabase
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import { parseArgs, uuidValidator } from '../validators.js';
|
|
12
12
|
import { getApiClient } from '../api-client.js';
|
|
13
|
+
// Argument schemas for type-safe parsing
|
|
14
|
+
const logDecisionSchema = {
|
|
15
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
16
|
+
title: { type: 'string', required: true },
|
|
17
|
+
description: { type: 'string', required: true },
|
|
18
|
+
rationale: { type: 'string' },
|
|
19
|
+
alternatives_considered: { type: 'array' },
|
|
20
|
+
};
|
|
21
|
+
const getDecisionsSchema = {
|
|
22
|
+
project_id: { type: 'string', required: true, validate: uuidValidator },
|
|
23
|
+
limit: { type: 'number', default: 50 },
|
|
24
|
+
offset: { type: 'number', default: 0 },
|
|
25
|
+
search_query: { type: 'string' },
|
|
26
|
+
};
|
|
27
|
+
const deleteDecisionSchema = {
|
|
28
|
+
decision_id: { type: 'string', required: true, validate: uuidValidator },
|
|
29
|
+
};
|
|
13
30
|
export const logDecision = async (args, ctx) => {
|
|
14
|
-
const { project_id, title, description, rationale, alternatives_considered } = args;
|
|
15
|
-
validateRequired(project_id, 'project_id');
|
|
16
|
-
validateUUID(project_id, 'project_id');
|
|
17
|
-
validateRequired(title, 'title');
|
|
18
|
-
validateRequired(description, 'description');
|
|
31
|
+
const { project_id, title, description, rationale, alternatives_considered } = parseArgs(args, logDecisionSchema);
|
|
19
32
|
const { session } = ctx;
|
|
20
33
|
const apiClient = getApiClient();
|
|
21
34
|
const response = await apiClient.logDecision(project_id, {
|
|
22
35
|
title,
|
|
23
36
|
description,
|
|
24
37
|
rationale,
|
|
25
|
-
alternatives_considered
|
|
38
|
+
alternatives_considered: alternatives_considered
|
|
26
39
|
}, session.currentSessionId || undefined);
|
|
27
40
|
if (!response.ok) {
|
|
28
|
-
|
|
41
|
+
return { result: { error: response.error || 'Failed to log decision' }, isError: true };
|
|
29
42
|
}
|
|
30
43
|
return { result: { success: true, title, decision_id: response.data?.decision_id } };
|
|
31
44
|
};
|
|
32
|
-
export const getDecisions = async (args,
|
|
33
|
-
const { project_id } = args;
|
|
34
|
-
validateRequired(project_id, 'project_id');
|
|
35
|
-
validateUUID(project_id, 'project_id');
|
|
45
|
+
export const getDecisions = async (args, _ctx) => {
|
|
46
|
+
const { project_id, limit, offset, search_query } = parseArgs(args, getDecisionsSchema);
|
|
36
47
|
const apiClient = getApiClient();
|
|
37
|
-
const response = await apiClient.getDecisions(project_id
|
|
48
|
+
const response = await apiClient.getDecisions(project_id, {
|
|
49
|
+
limit,
|
|
50
|
+
offset,
|
|
51
|
+
search_query
|
|
52
|
+
});
|
|
38
53
|
if (!response.ok) {
|
|
39
|
-
|
|
54
|
+
return { result: { error: response.error || 'Failed to fetch decisions' }, isError: true };
|
|
40
55
|
}
|
|
41
56
|
return {
|
|
42
57
|
result: {
|
|
@@ -44,14 +59,12 @@ export const getDecisions = async (args, ctx) => {
|
|
|
44
59
|
},
|
|
45
60
|
};
|
|
46
61
|
};
|
|
47
|
-
export const deleteDecision = async (args,
|
|
48
|
-
const { decision_id } = args;
|
|
49
|
-
validateRequired(decision_id, 'decision_id');
|
|
50
|
-
validateUUID(decision_id, 'decision_id');
|
|
62
|
+
export const deleteDecision = async (args, _ctx) => {
|
|
63
|
+
const { decision_id } = parseArgs(args, deleteDecisionSchema);
|
|
51
64
|
const apiClient = getApiClient();
|
|
52
65
|
const response = await apiClient.deleteDecision(decision_id);
|
|
53
66
|
if (!response.ok) {
|
|
54
|
-
|
|
67
|
+
return { result: { error: response.error || 'Failed to delete decision' }, isError: true };
|
|
55
68
|
}
|
|
56
69
|
return { result: { success: true } };
|
|
57
70
|
};
|