@mtaap/mcp 0.1.2 → 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.
- package/README.md +25 -7
- package/dist/cli.js +1595 -16
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1550 -7
- package/dist/index.js.map +1 -1
- package/package.json +3 -15
- package/dist/audit-B6CIQU22.js +0 -8
- package/dist/audit-B6CIQU22.js.map +0 -1
- package/dist/chunk-4ILBJI7A.js +0 -1678
- package/dist/chunk-4ILBJI7A.js.map +0 -1
- package/dist/chunk-ASNGTDTC.js +0 -1314
- package/dist/chunk-ASNGTDTC.js.map +0 -1
- package/dist/chunk-IEQQVLM4.js +0 -6016
- package/dist/chunk-IEQQVLM4.js.map +0 -1
- package/dist/dist-NSFD2BPW.js +0 -255
- package/dist/dist-NSFD2BPW.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,1552 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
createMCPServer: () => createMCPServer
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
37
|
+
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
38
|
+
|
|
39
|
+
// src/version.ts
|
|
40
|
+
var VERSION = "0.2.0";
|
|
41
|
+
|
|
42
|
+
// ../../packages/core/dist/constants/enums.js
|
|
43
|
+
var TaskState;
|
|
44
|
+
(function(TaskState3) {
|
|
45
|
+
TaskState3["BACKLOG"] = "BACKLOG";
|
|
46
|
+
TaskState3["READY"] = "READY";
|
|
47
|
+
TaskState3["IN_PROGRESS"] = "IN_PROGRESS";
|
|
48
|
+
TaskState3["REVIEW"] = "REVIEW";
|
|
49
|
+
TaskState3["DONE"] = "DONE";
|
|
50
|
+
})(TaskState || (TaskState = {}));
|
|
51
|
+
var UserRole;
|
|
52
|
+
(function(UserRole2) {
|
|
53
|
+
UserRole2["ADMIN"] = "ADMIN";
|
|
54
|
+
UserRole2["MEMBER"] = "MEMBER";
|
|
55
|
+
})(UserRole || (UserRole = {}));
|
|
56
|
+
var ProjectType;
|
|
57
|
+
(function(ProjectType2) {
|
|
58
|
+
ProjectType2["TEAM"] = "TEAM";
|
|
59
|
+
ProjectType2["PERSONAL"] = "PERSONAL";
|
|
60
|
+
})(ProjectType || (ProjectType = {}));
|
|
61
|
+
var ProjectOrigin;
|
|
62
|
+
(function(ProjectOrigin2) {
|
|
63
|
+
ProjectOrigin2["CREATED"] = "CREATED";
|
|
64
|
+
ProjectOrigin2["PROMOTED"] = "PROMOTED";
|
|
65
|
+
})(ProjectOrigin || (ProjectOrigin = {}));
|
|
66
|
+
var TaskPriority;
|
|
67
|
+
(function(TaskPriority2) {
|
|
68
|
+
TaskPriority2["LOW"] = "LOW";
|
|
69
|
+
TaskPriority2["MEDIUM"] = "MEDIUM";
|
|
70
|
+
TaskPriority2["HIGH"] = "HIGH";
|
|
71
|
+
TaskPriority2["CRITICAL"] = "CRITICAL";
|
|
72
|
+
})(TaskPriority || (TaskPriority = {}));
|
|
73
|
+
var DeploymentMode;
|
|
74
|
+
(function(DeploymentMode2) {
|
|
75
|
+
DeploymentMode2["SAAS"] = "saas";
|
|
76
|
+
DeploymentMode2["ONPREM"] = "onprem";
|
|
77
|
+
})(DeploymentMode || (DeploymentMode = {}));
|
|
78
|
+
var ErrorType;
|
|
79
|
+
(function(ErrorType3) {
|
|
80
|
+
ErrorType3["BUILD_FAILURE"] = "BUILD_FAILURE";
|
|
81
|
+
ErrorType3["TEST_FAILURE"] = "TEST_FAILURE";
|
|
82
|
+
ErrorType3["CONFLICT"] = "CONFLICT";
|
|
83
|
+
ErrorType3["AUTH_ERROR"] = "AUTH_ERROR";
|
|
84
|
+
ErrorType3["OTHER"] = "OTHER";
|
|
85
|
+
})(ErrorType || (ErrorType = {}));
|
|
86
|
+
var PRStatus;
|
|
87
|
+
(function(PRStatus2) {
|
|
88
|
+
PRStatus2["OPEN"] = "OPEN";
|
|
89
|
+
PRStatus2["CLOSED"] = "CLOSED";
|
|
90
|
+
PRStatus2["MERGED"] = "MERGED";
|
|
91
|
+
PRStatus2["DELETED"] = "DELETED";
|
|
92
|
+
})(PRStatus || (PRStatus = {}));
|
|
93
|
+
var PricingTier;
|
|
94
|
+
(function(PricingTier2) {
|
|
95
|
+
PricingTier2["FREE"] = "FREE";
|
|
96
|
+
PricingTier2["PRO"] = "PRO";
|
|
97
|
+
PricingTier2["ENTERPRISE"] = "ENTERPRISE";
|
|
98
|
+
})(PricingTier || (PricingTier = {}));
|
|
99
|
+
var ApiKeyPermission;
|
|
100
|
+
(function(ApiKeyPermission2) {
|
|
101
|
+
ApiKeyPermission2["READ"] = "READ";
|
|
102
|
+
ApiKeyPermission2["WRITE"] = "WRITE";
|
|
103
|
+
ApiKeyPermission2["ADMIN"] = "ADMIN";
|
|
104
|
+
})(ApiKeyPermission || (ApiKeyPermission = {}));
|
|
105
|
+
var WebSocketEventType;
|
|
106
|
+
(function(WebSocketEventType2) {
|
|
107
|
+
WebSocketEventType2["TASK_ASSIGNED"] = "task.assigned";
|
|
108
|
+
WebSocketEventType2["TASK_ABANDONED"] = "task.abandoned";
|
|
109
|
+
WebSocketEventType2["TASK_PROGRESS"] = "task.progress";
|
|
110
|
+
WebSocketEventType2["TASK_PR_CREATED"] = "task.pr_created";
|
|
111
|
+
WebSocketEventType2["TASK_REVIEW_REQUESTED"] = "task.review_requested";
|
|
112
|
+
WebSocketEventType2["TASK_COMPLETED"] = "task.completed";
|
|
113
|
+
WebSocketEventType2["TASK_ERROR"] = "task.error";
|
|
114
|
+
WebSocketEventType2["TASK_STATE_CHANGED"] = "task.state_changed";
|
|
115
|
+
WebSocketEventType2["MEMBER_JOINED"] = "member.joined";
|
|
116
|
+
})(WebSocketEventType || (WebSocketEventType = {}));
|
|
117
|
+
var AuthProvider;
|
|
118
|
+
(function(AuthProvider2) {
|
|
119
|
+
AuthProvider2["CREDENTIALS"] = "credentials";
|
|
120
|
+
AuthProvider2["LDAP"] = "ldap";
|
|
121
|
+
AuthProvider2["SSO"] = "sso";
|
|
122
|
+
})(AuthProvider || (AuthProvider = {}));
|
|
123
|
+
var SubscriptionStatus;
|
|
124
|
+
(function(SubscriptionStatus2) {
|
|
125
|
+
SubscriptionStatus2["ACTIVE"] = "ACTIVE";
|
|
126
|
+
SubscriptionStatus2["INACTIVE"] = "INACTIVE";
|
|
127
|
+
SubscriptionStatus2["PAST_DUE"] = "PAST_DUE";
|
|
128
|
+
SubscriptionStatus2["CANCELED"] = "CANCELED";
|
|
129
|
+
SubscriptionStatus2["INCOMPLETE"] = "INCOMPLETE";
|
|
130
|
+
})(SubscriptionStatus || (SubscriptionStatus = {}));
|
|
131
|
+
var EventType;
|
|
132
|
+
(function(EventType2) {
|
|
133
|
+
EventType2["AUTH"] = "AUTH";
|
|
134
|
+
EventType2["AUTHORIZATION"] = "AUTHORIZATION";
|
|
135
|
+
EventType2["ACCESS"] = "ACCESS";
|
|
136
|
+
EventType2["MODIFICATION"] = "MODIFICATION";
|
|
137
|
+
})(EventType || (EventType = {}));
|
|
138
|
+
|
|
139
|
+
// ../../packages/core/dist/constants/state-machine.js
|
|
140
|
+
var VALID_TRANSITIONS = {
|
|
141
|
+
[TaskState.BACKLOG]: [TaskState.READY],
|
|
142
|
+
[TaskState.READY]: [TaskState.BACKLOG, TaskState.IN_PROGRESS],
|
|
143
|
+
[TaskState.IN_PROGRESS]: [
|
|
144
|
+
TaskState.BACKLOG,
|
|
145
|
+
TaskState.READY,
|
|
146
|
+
TaskState.REVIEW
|
|
147
|
+
],
|
|
148
|
+
[TaskState.REVIEW]: [
|
|
149
|
+
TaskState.BACKLOG,
|
|
150
|
+
TaskState.READY,
|
|
151
|
+
TaskState.IN_PROGRESS,
|
|
152
|
+
TaskState.DONE
|
|
153
|
+
],
|
|
154
|
+
[TaskState.DONE]: []
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// ../../packages/core/dist/version.js
|
|
158
|
+
var VERSION2 = "0.1.0";
|
|
159
|
+
|
|
160
|
+
// ../../packages/core/dist/config/index.js
|
|
161
|
+
var DEPLOYMENT_MODE = process.env.DEPLOYMENT_MODE || "saas";
|
|
162
|
+
var config = {
|
|
163
|
+
version: VERSION2,
|
|
164
|
+
deploymentMode: DEPLOYMENT_MODE,
|
|
165
|
+
billing: {
|
|
166
|
+
enabled: DEPLOYMENT_MODE === "saas",
|
|
167
|
+
revenuecat: {
|
|
168
|
+
publicKey: process.env.REVENUECAT_PUBLIC_API_KEY,
|
|
169
|
+
stripeKey: process.env.STRIPE_SECRET_KEY
|
|
170
|
+
// Required by RevenueCat Web Billing
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
licensing: {
|
|
174
|
+
enabled: DEPLOYMENT_MODE === "onprem",
|
|
175
|
+
licenseKey: process.env.LICENSE_KEY
|
|
176
|
+
},
|
|
177
|
+
auth: {
|
|
178
|
+
credentials: true,
|
|
179
|
+
ldap: process.env.LDAP_ENABLED === "true"
|
|
180
|
+
},
|
|
181
|
+
git: {
|
|
182
|
+
deleteMergedBranches: process.env.DELETE_MERGED_BRANCHES !== "false",
|
|
183
|
+
enforceConventionalCommits: process.env.ENFORCE_CONVENTIONAL_COMMITS === "true",
|
|
184
|
+
defaultBaseBranch: process.env.DEFAULT_BASE_BRANCH || "develop"
|
|
185
|
+
},
|
|
186
|
+
pricing: {
|
|
187
|
+
maxPersonalProjects: {
|
|
188
|
+
FREE: 2,
|
|
189
|
+
PRO: 5,
|
|
190
|
+
ENTERPRISE: 10
|
|
191
|
+
},
|
|
192
|
+
maxCollaboratorsPerProject: {
|
|
193
|
+
FREE: 3,
|
|
194
|
+
PRO: -1,
|
|
195
|
+
ENTERPRISE: -1
|
|
196
|
+
},
|
|
197
|
+
maxProjectsPerOrg: {
|
|
198
|
+
FREE: 5,
|
|
199
|
+
PRO: -1,
|
|
200
|
+
ENTERPRISE: -1
|
|
201
|
+
},
|
|
202
|
+
maxSeats: {
|
|
203
|
+
FREE: 3,
|
|
204
|
+
PRO: -1,
|
|
205
|
+
ENTERPRISE: -1
|
|
206
|
+
},
|
|
207
|
+
// Default seats when subscription doesn't specify an explicit seat count
|
|
208
|
+
defaultSeats: {
|
|
209
|
+
FREE: 3,
|
|
210
|
+
PRO: 10,
|
|
211
|
+
ENTERPRISE: 999999
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
features: {
|
|
215
|
+
stripe: {
|
|
216
|
+
enabled: DEPLOYMENT_MODE === "saas"
|
|
217
|
+
},
|
|
218
|
+
gitlab: {
|
|
219
|
+
enabled: true
|
|
220
|
+
},
|
|
221
|
+
ldap: {
|
|
222
|
+
enabled: process.env.LDAP_ENABLED === "true"
|
|
223
|
+
},
|
|
224
|
+
auditLogs: {
|
|
225
|
+
enabled: process.env.AUDIT_LOGS_ENABLED === "true"
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
api: {
|
|
229
|
+
apiKey: {
|
|
230
|
+
defaultExpiryDays: 90,
|
|
231
|
+
prefix: "usr_"
|
|
232
|
+
},
|
|
233
|
+
rateLimit: {
|
|
234
|
+
requestsPerMinute: 100,
|
|
235
|
+
requestsPerHour: 1e3
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
limits: {
|
|
239
|
+
projectNameMaxLength: 100,
|
|
240
|
+
taskDescriptionMaxLength: 5e3,
|
|
241
|
+
notesMaxLength: 500,
|
|
242
|
+
conventionsNotesMaxLength: 500,
|
|
243
|
+
recentCompletedTasksLimit: 10
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
var DEFAULT_SEAT_LIMITS = {
|
|
247
|
+
[PricingTier.FREE]: config.pricing.defaultSeats.FREE,
|
|
248
|
+
[PricingTier.PRO]: config.pricing.defaultSeats.PRO,
|
|
249
|
+
[PricingTier.ENTERPRISE]: config.pricing.defaultSeats.ENTERPRISE
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// ../../packages/core/dist/types/index.js
|
|
253
|
+
var import_zod = require("zod");
|
|
254
|
+
var UserIdSchema = import_zod.z.string().regex(/^usr_[a-zA-Z0-9]+$/);
|
|
255
|
+
var UserSchema = import_zod.z.object({
|
|
256
|
+
id: UserIdSchema,
|
|
257
|
+
email: import_zod.z.string().email(),
|
|
258
|
+
name: import_zod.z.string().min(1).max(255),
|
|
259
|
+
role: import_zod.z.nativeEnum(UserRole),
|
|
260
|
+
organizationId: import_zod.z.string().optional(),
|
|
261
|
+
lastActiveAt: import_zod.z.coerce.date().optional(),
|
|
262
|
+
createdAt: import_zod.z.coerce.date()
|
|
263
|
+
});
|
|
264
|
+
var OrganizationUserSchema = import_zod.z.object({
|
|
265
|
+
id: import_zod.z.number().int(),
|
|
266
|
+
userId: UserIdSchema,
|
|
267
|
+
organizationId: import_zod.z.string(),
|
|
268
|
+
roleId: import_zod.z.nativeEnum(UserRole).optional(),
|
|
269
|
+
user: UserSchema.pick({ id: true, email: true, name: true, role: true }),
|
|
270
|
+
createdAt: import_zod.z.coerce.date()
|
|
271
|
+
});
|
|
272
|
+
var OrganizationIdSchema = import_zod.z.string().regex(/^org_[a-zA-Z0-9]+$/);
|
|
273
|
+
var OrganizationSchema = import_zod.z.object({
|
|
274
|
+
id: OrganizationIdSchema,
|
|
275
|
+
name: import_zod.z.string().min(1).max(255),
|
|
276
|
+
slug: import_zod.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/),
|
|
277
|
+
logoUrl: import_zod.z.string().url().nullable(),
|
|
278
|
+
accentColor: import_zod.z.string().regex(/^#[0-9A-Fa-f]{6}$/).nullable(),
|
|
279
|
+
tenantName: import_zod.z.string().nullable(),
|
|
280
|
+
pricingTier: import_zod.z.nativeEnum(PricingTier),
|
|
281
|
+
createdAt: import_zod.z.coerce.date()
|
|
282
|
+
});
|
|
283
|
+
var OrganizationSettingsSchema = import_zod.z.object({
|
|
284
|
+
organizationId: OrganizationIdSchema,
|
|
285
|
+
ldapEnabled: import_zod.z.boolean(),
|
|
286
|
+
ldapUrl: import_zod.z.string().url().nullable(),
|
|
287
|
+
ldapBindDN: import_zod.z.string().nullable(),
|
|
288
|
+
ldapSearchBase: import_zod.z.string().nullable(),
|
|
289
|
+
deleteMergedBranches: import_zod.z.boolean(),
|
|
290
|
+
enforceConventionalCommits: import_zod.z.boolean(),
|
|
291
|
+
maxPersonalProjectsPerUser: import_zod.z.number().int().min(0)
|
|
292
|
+
});
|
|
293
|
+
var TagSchema = import_zod.z.object({
|
|
294
|
+
id: import_zod.z.string(),
|
|
295
|
+
name: import_zod.z.string().min(1).max(50),
|
|
296
|
+
organizationId: OrganizationIdSchema,
|
|
297
|
+
createdAt: import_zod.z.coerce.date()
|
|
298
|
+
});
|
|
299
|
+
var ProjectIdSchema = import_zod.z.string().regex(/^prj_[a-zA-Z0-9]+$/);
|
|
300
|
+
var ProjectSchema = import_zod.z.object({
|
|
301
|
+
id: ProjectIdSchema,
|
|
302
|
+
name: import_zod.z.string().min(1).max(100),
|
|
303
|
+
description: import_zod.z.string().max(500).nullable(),
|
|
304
|
+
type: import_zod.z.nativeEnum(ProjectType),
|
|
305
|
+
origin: import_zod.z.nativeEnum(ProjectOrigin),
|
|
306
|
+
organizationId: OrganizationIdSchema,
|
|
307
|
+
ownerId: UserIdSchema.nullable(),
|
|
308
|
+
repositoryUrl: import_zod.z.string().url(),
|
|
309
|
+
baseBranch: import_zod.z.string().default("develop"),
|
|
310
|
+
tags: import_zod.z.array(import_zod.z.string()),
|
|
311
|
+
createdAt: import_zod.z.coerce.date(),
|
|
312
|
+
updatedAt: import_zod.z.coerce.date()
|
|
313
|
+
});
|
|
314
|
+
var EpicIdSchema = import_zod.z.string().regex(/^epc_[a-zA-Z0-9]+$/);
|
|
315
|
+
var EpicSchema = import_zod.z.object({
|
|
316
|
+
id: EpicIdSchema,
|
|
317
|
+
projectId: ProjectIdSchema,
|
|
318
|
+
name: import_zod.z.string().min(1).max(200),
|
|
319
|
+
description: import_zod.z.string().nullable(),
|
|
320
|
+
createdAt: import_zod.z.coerce.date(),
|
|
321
|
+
updatedAt: import_zod.z.coerce.date()
|
|
322
|
+
});
|
|
323
|
+
var TaskIdSchema = import_zod.z.string().regex(/^tsk_[a-zA-Z0-9]+$/);
|
|
324
|
+
var TaskSchema = import_zod.z.object({
|
|
325
|
+
id: TaskIdSchema,
|
|
326
|
+
projectId: ProjectIdSchema,
|
|
327
|
+
epicId: EpicIdSchema.nullable(),
|
|
328
|
+
title: import_zod.z.string().min(1).max(200),
|
|
329
|
+
description: import_zod.z.string().max(5e3),
|
|
330
|
+
state: import_zod.z.nativeEnum(TaskState),
|
|
331
|
+
priority: import_zod.z.nativeEnum(TaskPriority),
|
|
332
|
+
assigneeId: UserIdSchema.nullable(),
|
|
333
|
+
createdBy: UserIdSchema.nullable(),
|
|
334
|
+
assignedAt: import_zod.z.coerce.date().nullable(),
|
|
335
|
+
startedAt: import_zod.z.coerce.date().nullable(),
|
|
336
|
+
completedAt: import_zod.z.coerce.date().nullable(),
|
|
337
|
+
branchName: import_zod.z.string().nullable(),
|
|
338
|
+
pullRequestUrl: import_zod.z.string().url().nullable(),
|
|
339
|
+
pullRequestNumber: import_zod.z.number().int().nullable(),
|
|
340
|
+
pullRequestStatus: import_zod.z.nativeEnum(PRStatus).nullable(),
|
|
341
|
+
errorType: import_zod.z.nativeEnum(ErrorType).nullable(),
|
|
342
|
+
errorMessage: import_zod.z.string().max(1e3).nullable(),
|
|
343
|
+
createdAt: import_zod.z.coerce.date(),
|
|
344
|
+
updatedAt: import_zod.z.coerce.date()
|
|
345
|
+
});
|
|
346
|
+
var AcceptanceCriterionSchema = import_zod.z.object({
|
|
347
|
+
id: import_zod.z.string(),
|
|
348
|
+
taskId: TaskIdSchema,
|
|
349
|
+
description: import_zod.z.string().min(1).max(500),
|
|
350
|
+
completed: import_zod.z.boolean(),
|
|
351
|
+
completedAt: import_zod.z.coerce.date().nullable(),
|
|
352
|
+
order: import_zod.z.number().int(),
|
|
353
|
+
createdAt: import_zod.z.coerce.date()
|
|
354
|
+
});
|
|
355
|
+
var ProgressUpdateSchema = import_zod.z.object({
|
|
356
|
+
id: import_zod.z.string(),
|
|
357
|
+
taskId: TaskIdSchema,
|
|
358
|
+
userId: UserIdSchema,
|
|
359
|
+
message: import_zod.z.string().max(2e3),
|
|
360
|
+
checkpoints: import_zod.z.array(import_zod.z.string()).optional(),
|
|
361
|
+
createdAt: import_zod.z.coerce.date()
|
|
362
|
+
});
|
|
363
|
+
var TaskNoteSchema = import_zod.z.object({
|
|
364
|
+
id: import_zod.z.string(),
|
|
365
|
+
taskId: TaskIdSchema,
|
|
366
|
+
userId: UserIdSchema,
|
|
367
|
+
content: import_zod.z.string().max(500),
|
|
368
|
+
createdAt: import_zod.z.coerce.date()
|
|
369
|
+
});
|
|
370
|
+
var ApiKeyIdSchema = import_zod.z.string().regex(/^key_[a-zA-Z0-9]+$/);
|
|
371
|
+
var ApiKeySchema = import_zod.z.object({
|
|
372
|
+
id: ApiKeyIdSchema,
|
|
373
|
+
userId: UserIdSchema,
|
|
374
|
+
name: import_zod.z.string().min(1).max(100),
|
|
375
|
+
keyHash: import_zod.z.string(),
|
|
376
|
+
permissions: import_zod.z.nativeEnum(ApiKeyPermission),
|
|
377
|
+
lastUsedAt: import_zod.z.coerce.date().nullable(),
|
|
378
|
+
expiresAt: import_zod.z.coerce.date().nullable(),
|
|
379
|
+
revoked: import_zod.z.boolean(),
|
|
380
|
+
createdAt: import_zod.z.coerce.date()
|
|
381
|
+
});
|
|
382
|
+
var SubscriptionIdSchema = import_zod.z.string();
|
|
383
|
+
var SubscriptionSchema = import_zod.z.object({
|
|
384
|
+
id: SubscriptionIdSchema,
|
|
385
|
+
organizationId: OrganizationIdSchema,
|
|
386
|
+
pricingTier: import_zod.z.nativeEnum(PricingTier),
|
|
387
|
+
seats: import_zod.z.number().int().min(0),
|
|
388
|
+
stripeSubscriptionId: import_zod.z.string().nullable(),
|
|
389
|
+
stripeCustomerId: import_zod.z.string().nullable(),
|
|
390
|
+
status: import_zod.z.enum(["active", "past_due", "canceled", "incomplete"]),
|
|
391
|
+
currentPeriodStart: import_zod.z.coerce.date(),
|
|
392
|
+
currentPeriodEnd: import_zod.z.coerce.date(),
|
|
393
|
+
createdAt: import_zod.z.coerce.date()
|
|
394
|
+
});
|
|
395
|
+
var ProjectCollaboratorSchema = import_zod.z.object({
|
|
396
|
+
id: import_zod.z.string(),
|
|
397
|
+
projectId: ProjectIdSchema,
|
|
398
|
+
userId: UserIdSchema,
|
|
399
|
+
addedBy: UserIdSchema,
|
|
400
|
+
createdAt: import_zod.z.coerce.date()
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
// ../../packages/core/dist/validation/index.js
|
|
404
|
+
var import_zod2 = require("zod");
|
|
405
|
+
var ListProjectsInputSchema = import_zod2.z.object({
|
|
406
|
+
workspaceType: import_zod2.z.preprocess((val) => typeof val === "string" ? val.toUpperCase() : val, import_zod2.z.enum(["TEAM", "PERSONAL", "ALL"]).optional())
|
|
407
|
+
});
|
|
408
|
+
var ListTasksInputSchema = import_zod2.z.object({
|
|
409
|
+
projectId: import_zod2.z.string().optional(),
|
|
410
|
+
state: import_zod2.z.nativeEnum(TaskState).optional(),
|
|
411
|
+
assigneeId: import_zod2.z.string().optional()
|
|
412
|
+
});
|
|
413
|
+
var GetTaskInputSchema = import_zod2.z.object({
|
|
414
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/)
|
|
415
|
+
});
|
|
416
|
+
var AssignTaskInputSchema = import_zod2.z.object({
|
|
417
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
|
|
418
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
|
|
419
|
+
expectedState: import_zod2.z.nativeEnum(TaskState).default(TaskState.READY)
|
|
420
|
+
});
|
|
421
|
+
var UpdateProgressInputSchema = import_zod2.z.object({
|
|
422
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
|
|
423
|
+
statusMessage: import_zod2.z.string().max(1e3).optional(),
|
|
424
|
+
completedCheckpointIds: import_zod2.z.array(import_zod2.z.string()).optional(),
|
|
425
|
+
currentCheckpointIndex: import_zod2.z.number().int().optional()
|
|
426
|
+
});
|
|
427
|
+
var CompleteTaskInputSchema = import_zod2.z.object({
|
|
428
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
|
|
429
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
|
|
430
|
+
pullRequestTitle: import_zod2.z.string().min(1).max(300).optional(),
|
|
431
|
+
pullRequestBody: import_zod2.z.string().max(1e4).optional()
|
|
432
|
+
});
|
|
433
|
+
var ReportErrorInputSchema = import_zod2.z.object({
|
|
434
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
|
|
435
|
+
errorType: import_zod2.z.nativeEnum(ErrorType),
|
|
436
|
+
errorMessage: import_zod2.z.string().min(1).max(1e3),
|
|
437
|
+
context: import_zod2.z.string().max(2e3).optional()
|
|
438
|
+
});
|
|
439
|
+
var GetProjectContextInputSchema = import_zod2.z.object({
|
|
440
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/)
|
|
441
|
+
});
|
|
442
|
+
var AddNoteInputSchema = import_zod2.z.object({
|
|
443
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
|
|
444
|
+
content: import_zod2.z.string().min(1).max(500)
|
|
445
|
+
});
|
|
446
|
+
var AbandonTaskInputSchema = import_zod2.z.object({
|
|
447
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
|
|
448
|
+
taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
|
|
449
|
+
deleteBranch: import_zod2.z.boolean().optional()
|
|
450
|
+
});
|
|
451
|
+
var CreatePersonalProjectInputSchema = import_zod2.z.object({
|
|
452
|
+
name: import_zod2.z.string().min(1).max(100),
|
|
453
|
+
description: import_zod2.z.string().max(500).optional(),
|
|
454
|
+
repositoryUrl: import_zod2.z.string().url()
|
|
455
|
+
});
|
|
456
|
+
var CheckActiveTaskInputSchema = import_zod2.z.object({});
|
|
457
|
+
var CreateOrganizationInputSchema = import_zod2.z.object({
|
|
458
|
+
name: import_zod2.z.string().min(1).max(255),
|
|
459
|
+
slug: import_zod2.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
|
|
460
|
+
});
|
|
461
|
+
var UpdateOrganizationInputSchema = import_zod2.z.object({
|
|
462
|
+
organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
|
|
463
|
+
name: import_zod2.z.string().min(1).max(255).optional(),
|
|
464
|
+
logoUrl: import_zod2.z.string().url().nullable().optional(),
|
|
465
|
+
accentColor: import_zod2.z.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
|
|
466
|
+
tenantName: import_zod2.z.string().max(255).nullable().optional()
|
|
467
|
+
});
|
|
468
|
+
var CreateProjectInputSchema = import_zod2.z.object({
|
|
469
|
+
name: import_zod2.z.string().min(1).max(100),
|
|
470
|
+
description: import_zod2.z.string().max(500).optional(),
|
|
471
|
+
type: import_zod2.z.nativeEnum(ProjectType),
|
|
472
|
+
repositoryUrl: import_zod2.z.string().url(),
|
|
473
|
+
baseBranch: import_zod2.z.string().default("develop").optional(),
|
|
474
|
+
tags: import_zod2.z.array(import_zod2.z.string()).default([])
|
|
475
|
+
});
|
|
476
|
+
var UpdateProjectInputSchema = import_zod2.z.object({
|
|
477
|
+
projectId: import_zod2.z.string().min(1).optional(),
|
|
478
|
+
name: import_zod2.z.string().min(1).max(100).optional(),
|
|
479
|
+
description: import_zod2.z.string().max(500).optional(),
|
|
480
|
+
repositoryUrl: import_zod2.z.string().url().optional(),
|
|
481
|
+
baseBranch: import_zod2.z.string().optional(),
|
|
482
|
+
tags: import_zod2.z.array(import_zod2.z.string()).optional()
|
|
483
|
+
});
|
|
484
|
+
var CreateEpicInputSchema = import_zod2.z.object({
|
|
485
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
|
|
486
|
+
name: import_zod2.z.string().min(1).max(200),
|
|
487
|
+
description: import_zod2.z.string().max(2e3).optional()
|
|
488
|
+
});
|
|
489
|
+
var CreateTaskInputSchema = import_zod2.z.object({
|
|
490
|
+
projectId: import_zod2.z.string().min(1),
|
|
491
|
+
epicId: import_zod2.z.string().min(1).nullable().optional(),
|
|
492
|
+
title: import_zod2.z.string().min(1).max(200),
|
|
493
|
+
description: import_zod2.z.string().max(5e3),
|
|
494
|
+
priority: import_zod2.z.nativeEnum(TaskPriority).default(TaskPriority.MEDIUM),
|
|
495
|
+
acceptanceCriteria: import_zod2.z.array(import_zod2.z.object({
|
|
496
|
+
description: import_zod2.z.string().min(1).max(500)
|
|
497
|
+
})).min(1)
|
|
498
|
+
});
|
|
499
|
+
var UpdateTaskInputSchema = import_zod2.z.object({
|
|
500
|
+
taskId: import_zod2.z.string().min(1),
|
|
501
|
+
title: import_zod2.z.string().min(1).max(200).optional(),
|
|
502
|
+
description: import_zod2.z.string().max(5e3).optional(),
|
|
503
|
+
priority: import_zod2.z.nativeEnum(TaskPriority).optional(),
|
|
504
|
+
state: import_zod2.z.nativeEnum(TaskState).optional(),
|
|
505
|
+
assigneeId: import_zod2.z.string().nullable().optional(),
|
|
506
|
+
acceptanceCriteria: import_zod2.z.array(import_zod2.z.object({
|
|
507
|
+
id: import_zod2.z.string().optional(),
|
|
508
|
+
description: import_zod2.z.string().min(1).max(500),
|
|
509
|
+
completed: import_zod2.z.boolean().optional()
|
|
510
|
+
})).optional()
|
|
511
|
+
});
|
|
512
|
+
var AssignTaskWebappInputSchema = import_zod2.z.object({
|
|
513
|
+
taskId: import_zod2.z.string().min(1),
|
|
514
|
+
userId: import_zod2.z.string().min(1)
|
|
515
|
+
});
|
|
516
|
+
var CreateTagInputSchema = import_zod2.z.object({
|
|
517
|
+
organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
|
|
518
|
+
name: import_zod2.z.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
|
|
519
|
+
});
|
|
520
|
+
var UpdateTagInputSchema = import_zod2.z.object({
|
|
521
|
+
name: import_zod2.z.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
|
|
522
|
+
});
|
|
523
|
+
var UpdateOrganizationSettingsInputSchema = import_zod2.z.object({
|
|
524
|
+
organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
|
|
525
|
+
ldapEnabled: import_zod2.z.boolean().optional(),
|
|
526
|
+
ldapUrl: import_zod2.z.string().url().nullable().optional(),
|
|
527
|
+
ldapBindDN: import_zod2.z.string().nullable().optional(),
|
|
528
|
+
ldapSearchBase: import_zod2.z.string().nullable().optional(),
|
|
529
|
+
deleteMergedBranches: import_zod2.z.boolean().optional(),
|
|
530
|
+
enforceConventionalCommits: import_zod2.z.boolean().optional(),
|
|
531
|
+
maxPersonalProjectsPerUser: import_zod2.z.number().int().min(0).optional(),
|
|
532
|
+
logoUrl: import_zod2.z.string().url().nullable().optional(),
|
|
533
|
+
accentColor: import_zod2.z.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
|
|
534
|
+
tenantName: import_zod2.z.string().max(255).nullable().optional()
|
|
535
|
+
});
|
|
536
|
+
var InviteUserInputSchema = import_zod2.z.object({
|
|
537
|
+
organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
|
|
538
|
+
email: import_zod2.z.string().email(),
|
|
539
|
+
role: import_zod2.z.nativeEnum(UserRole).default(UserRole.MEMBER),
|
|
540
|
+
tags: import_zod2.z.array(import_zod2.z.string()).default([])
|
|
541
|
+
});
|
|
542
|
+
var AssignUserTagsInputSchema = import_zod2.z.object({
|
|
543
|
+
userId: import_zod2.z.string().regex(/^usr_[a-zA-Z0-9]+$/),
|
|
544
|
+
tags: import_zod2.z.array(import_zod2.z.string()).min(0)
|
|
545
|
+
});
|
|
546
|
+
var InviteCollaboratorInputSchema = import_zod2.z.object({
|
|
547
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
|
|
548
|
+
email: import_zod2.z.string().email()
|
|
549
|
+
});
|
|
550
|
+
var PublishProjectInputSchema = import_zod2.z.object({
|
|
551
|
+
projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
|
|
552
|
+
transferOwnership: import_zod2.z.boolean().default(false),
|
|
553
|
+
tags: import_zod2.z.array(import_zod2.z.string()).min(1)
|
|
554
|
+
});
|
|
555
|
+
var GenerateApiKeyInputSchema = import_zod2.z.object({
|
|
556
|
+
name: import_zod2.z.string().min(1).max(100),
|
|
557
|
+
expiresInDays: import_zod2.z.number().int().min(1).max(365).default(90),
|
|
558
|
+
permissions: import_zod2.z.nativeEnum(ApiKeyPermission).default(ApiKeyPermission.WRITE)
|
|
559
|
+
});
|
|
560
|
+
var RevokeApiKeyInputSchema = import_zod2.z.object({
|
|
561
|
+
keyId: import_zod2.z.string().regex(/^key_[a-zA-Z0-9]+$/)
|
|
562
|
+
});
|
|
563
|
+
var LoginInputSchema = import_zod2.z.object({
|
|
564
|
+
email: import_zod2.z.string().email(),
|
|
565
|
+
password: import_zod2.z.string().min(8).max(255)
|
|
566
|
+
});
|
|
567
|
+
var RegisterInputSchema = import_zod2.z.object({
|
|
568
|
+
email: import_zod2.z.string().email(),
|
|
569
|
+
password: import_zod2.z.string().min(8).max(255),
|
|
570
|
+
name: import_zod2.z.string().min(1).max(255),
|
|
571
|
+
organizationSlug: import_zod2.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
// ../../packages/core/dist/logging/metrics.js
|
|
575
|
+
var metrics = /* @__PURE__ */ new Map();
|
|
576
|
+
function labelsToKey(labels) {
|
|
577
|
+
if (!labels || Object.keys(labels).length === 0)
|
|
578
|
+
return "";
|
|
579
|
+
return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}="${v}"`).join(",");
|
|
580
|
+
}
|
|
581
|
+
function createCounter(name, help) {
|
|
582
|
+
const data = {
|
|
583
|
+
name,
|
|
584
|
+
type: "counter",
|
|
585
|
+
help,
|
|
586
|
+
values: /* @__PURE__ */ new Map()
|
|
587
|
+
};
|
|
588
|
+
metrics.set(name, data);
|
|
589
|
+
return {
|
|
590
|
+
inc(labels, value = 1) {
|
|
591
|
+
const key = labelsToKey(labels);
|
|
592
|
+
const current = data.values.get(key) || 0;
|
|
593
|
+
data.values.set(key, current + value);
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
function createGauge(name, help) {
|
|
598
|
+
const data = {
|
|
599
|
+
name,
|
|
600
|
+
type: "gauge",
|
|
601
|
+
help,
|
|
602
|
+
values: /* @__PURE__ */ new Map()
|
|
603
|
+
};
|
|
604
|
+
metrics.set(name, data);
|
|
605
|
+
return {
|
|
606
|
+
set(labels, value) {
|
|
607
|
+
const key = labelsToKey(labels);
|
|
608
|
+
data.values.set(key, value);
|
|
609
|
+
},
|
|
610
|
+
inc(labels, value = 1) {
|
|
611
|
+
const key = labelsToKey(labels);
|
|
612
|
+
const current = data.values.get(key) || 0;
|
|
613
|
+
data.values.set(key, current + value);
|
|
614
|
+
},
|
|
615
|
+
dec(labels, value = 1) {
|
|
616
|
+
const key = labelsToKey(labels);
|
|
617
|
+
const current = data.values.get(key) || 0;
|
|
618
|
+
data.values.set(key, current - value);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
function createHistogram(name, help, buckets = [5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]) {
|
|
623
|
+
const data = {
|
|
624
|
+
name,
|
|
625
|
+
type: "histogram",
|
|
626
|
+
help,
|
|
627
|
+
values: /* @__PURE__ */ new Map(),
|
|
628
|
+
buckets
|
|
629
|
+
};
|
|
630
|
+
metrics.set(name, data);
|
|
631
|
+
return {
|
|
632
|
+
observe(labels, value) {
|
|
633
|
+
const baseKey = labelsToKey(labels);
|
|
634
|
+
const sumKey = `${baseKey}|sum`;
|
|
635
|
+
const countKey = `${baseKey}|count`;
|
|
636
|
+
data.values.set(sumKey, (data.values.get(sumKey) || 0) + value);
|
|
637
|
+
data.values.set(countKey, (data.values.get(countKey) || 0) + 1);
|
|
638
|
+
for (const bucket of buckets) {
|
|
639
|
+
const bucketKey = `${baseKey}|le="${bucket}"`;
|
|
640
|
+
if (value <= bucket) {
|
|
641
|
+
data.values.set(bucketKey, (data.values.get(bucketKey) || 0) + 1);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const infKey = `${baseKey}|le="+Inf"`;
|
|
645
|
+
data.values.set(infKey, (data.values.get(infKey) || 0) + 1);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
var httpRequestsTotal = createCounter("mtaap_http_requests_total", "Total number of HTTP requests");
|
|
650
|
+
var httpRequestDuration = createHistogram("mtaap_http_request_duration_seconds", "HTTP request duration in seconds");
|
|
651
|
+
var activeUsers = createGauge("mtaap_active_users", "Number of active users");
|
|
652
|
+
var tasksTotal = createCounter("mtaap_tasks_total", "Total number of tasks by state");
|
|
653
|
+
var taskStateChanges = createCounter("mtaap_task_state_changes_total", "Total number of task state changes");
|
|
654
|
+
var httpErrorsTotal = createCounter("mtaap_http_errors_total", "Total number of HTTP errors");
|
|
655
|
+
var httpActiveConnections = createGauge("mtaap_http_active_connections", "Number of active HTTP connections");
|
|
656
|
+
var newSignupsTotal = createCounter("mtaap_new_signups_total", "Total number of new user signups");
|
|
657
|
+
var loginSuccessTotal = createCounter("mtaap_login_success_total", "Total number of successful logins");
|
|
658
|
+
var loginFailureTotal = createCounter("mtaap_login_failure_total", "Total number of failed logins");
|
|
659
|
+
var dbConnectionPoolActive = createGauge("mtaap_db_connection_pool_active", "Number of active database connections");
|
|
660
|
+
var dbConnectionPoolIdle = createGauge("mtaap_db_connection_pool_idle", "Number of idle database connections");
|
|
661
|
+
var dbConnectionPoolMax = createGauge("mtaap_db_connection_pool_max", "Maximum number of database connections");
|
|
662
|
+
var dbQueryDuration = createHistogram("mtaap_db_query_duration_seconds", "Database query duration in seconds");
|
|
663
|
+
var dbSlowQueriesTotal = createCounter("mtaap_db_slow_queries_total", "Total number of slow database queries (>1s)");
|
|
664
|
+
var dbErrorsTotal = createCounter("mtaap_db_errors_total", "Total number of database errors");
|
|
665
|
+
var tasksCreatedTotal = createCounter("mtaap_tasks_created_total", "Total number of tasks created");
|
|
666
|
+
var tasksAssignedTotal = createCounter("mtaap_tasks_assigned_total", "Total number of tasks assigned");
|
|
667
|
+
var tasksCompletedTotal = createCounter("mtaap_tasks_completed_total", "Total number of tasks completed");
|
|
668
|
+
var tasksByState = createGauge("mtaap_tasks_by_state", "Number of tasks by state");
|
|
669
|
+
|
|
670
|
+
// ../../packages/core/dist/logging/performance-monitor.js
|
|
671
|
+
var MAX_SAMPLES = 1e3;
|
|
672
|
+
var ALERT_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
673
|
+
var DEFAULT_THRESHOLDS = {
|
|
674
|
+
api: {
|
|
675
|
+
p50: 100,
|
|
676
|
+
p95: 500,
|
|
677
|
+
p99: 1e3
|
|
678
|
+
},
|
|
679
|
+
db: {
|
|
680
|
+
p95: 100,
|
|
681
|
+
p99: 500
|
|
682
|
+
},
|
|
683
|
+
webvitals: {
|
|
684
|
+
FCP: 2e3,
|
|
685
|
+
LCP: 2500,
|
|
686
|
+
FID: 100,
|
|
687
|
+
CLS: 0.1
|
|
688
|
+
}
|
|
8
689
|
};
|
|
690
|
+
function cloneThresholds() {
|
|
691
|
+
return Object.fromEntries(Object.entries(DEFAULT_THRESHOLDS).map(([category, metrics2]) => [
|
|
692
|
+
category,
|
|
693
|
+
{ ...metrics2 }
|
|
694
|
+
]));
|
|
695
|
+
}
|
|
696
|
+
function labelsToKey2(labels) {
|
|
697
|
+
if (!labels || Object.keys(labels).length === 0)
|
|
698
|
+
return "";
|
|
699
|
+
return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}="${value}"`).join(",");
|
|
700
|
+
}
|
|
701
|
+
function percentile(sortedValues, percentileValue) {
|
|
702
|
+
if (sortedValues.length === 0)
|
|
703
|
+
return 0;
|
|
704
|
+
const rank = Math.ceil(percentileValue / 100 * sortedValues.length);
|
|
705
|
+
const index = Math.min(Math.max(rank - 1, 0), sortedValues.length - 1);
|
|
706
|
+
return sortedValues[index];
|
|
707
|
+
}
|
|
708
|
+
var CircularBuffer = class {
|
|
709
|
+
capacity;
|
|
710
|
+
values = [];
|
|
711
|
+
index = 0;
|
|
712
|
+
size = 0;
|
|
713
|
+
constructor(capacity) {
|
|
714
|
+
this.capacity = capacity;
|
|
715
|
+
}
|
|
716
|
+
add(value) {
|
|
717
|
+
if (this.size < this.capacity) {
|
|
718
|
+
this.values.push(value);
|
|
719
|
+
this.size += 1;
|
|
720
|
+
this.index = this.size % this.capacity;
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
this.values[this.index] = value;
|
|
724
|
+
this.index = (this.index + 1) % this.capacity;
|
|
725
|
+
}
|
|
726
|
+
getValues() {
|
|
727
|
+
if (this.size < this.capacity) {
|
|
728
|
+
return this.values.slice(0, this.size);
|
|
729
|
+
}
|
|
730
|
+
return this.values.slice();
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
var PerformanceMonitor = class {
|
|
734
|
+
samples = /* @__PURE__ */ new Map();
|
|
735
|
+
thresholds = cloneThresholds();
|
|
736
|
+
alertCallback;
|
|
737
|
+
lastAlertTimestamps = /* @__PURE__ */ new Map();
|
|
738
|
+
recordTiming(category, name, durationMs, labels) {
|
|
739
|
+
if (!Number.isFinite(durationMs))
|
|
740
|
+
return;
|
|
741
|
+
const categoryMap = this.getCategoryMap(category);
|
|
742
|
+
const nameMap = this.getNameMap(categoryMap, name);
|
|
743
|
+
const labelKey = labelsToKey2(labels);
|
|
744
|
+
const buffer = nameMap.get(labelKey) ?? new CircularBuffer(MAX_SAMPLES);
|
|
745
|
+
buffer.add(durationMs);
|
|
746
|
+
nameMap.set(labelKey, buffer);
|
|
747
|
+
}
|
|
748
|
+
getPercentiles(category, name) {
|
|
749
|
+
const samples = this.collectSamples(category, name);
|
|
750
|
+
if (samples.length === 0) {
|
|
751
|
+
return { p50: 0, p95: 0, p99: 0 };
|
|
752
|
+
}
|
|
753
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
754
|
+
return {
|
|
755
|
+
p50: percentile(sorted, 50),
|
|
756
|
+
p95: percentile(sorted, 95),
|
|
757
|
+
p99: percentile(sorted, 99)
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
checkThresholds() {
|
|
761
|
+
const alerts = [];
|
|
762
|
+
const now = Date.now();
|
|
763
|
+
const callbackAlerts = [];
|
|
764
|
+
for (const [category, nameMap] of this.samples) {
|
|
765
|
+
const thresholds = this.thresholds[category];
|
|
766
|
+
if (!thresholds)
|
|
767
|
+
continue;
|
|
768
|
+
for (const name of nameMap.keys()) {
|
|
769
|
+
const percentiles = this.getPercentiles(category, name);
|
|
770
|
+
for (const [metric, threshold] of Object.entries(thresholds)) {
|
|
771
|
+
const value = this.resolveMetricValue(metric, name, percentiles);
|
|
772
|
+
if (value === void 0 || value <= threshold)
|
|
773
|
+
continue;
|
|
774
|
+
const alert = {
|
|
775
|
+
category,
|
|
776
|
+
name,
|
|
777
|
+
metric,
|
|
778
|
+
value,
|
|
779
|
+
threshold
|
|
780
|
+
};
|
|
781
|
+
alerts.push(alert);
|
|
782
|
+
const alertKey = `${category}|${name}|${metric}`;
|
|
783
|
+
const lastAlertTime = this.lastAlertTimestamps.get(alertKey);
|
|
784
|
+
if (!lastAlertTime || now - lastAlertTime >= ALERT_COOLDOWN_MS) {
|
|
785
|
+
this.lastAlertTimestamps.set(alertKey, now);
|
|
786
|
+
callbackAlerts.push(alert);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
if (callbackAlerts.length > 0 && this.alertCallback) {
|
|
792
|
+
this.alertCallback(callbackAlerts);
|
|
793
|
+
}
|
|
794
|
+
return alerts;
|
|
795
|
+
}
|
|
796
|
+
setAlertCallback(callback) {
|
|
797
|
+
this.alertCallback = callback;
|
|
798
|
+
}
|
|
799
|
+
setThreshold(category, metric, value) {
|
|
800
|
+
if (!this.thresholds[category]) {
|
|
801
|
+
this.thresholds[category] = {};
|
|
802
|
+
}
|
|
803
|
+
this.thresholds[category][metric] = value;
|
|
804
|
+
}
|
|
805
|
+
collectSamples(category, name) {
|
|
806
|
+
const categoryMap = this.samples.get(category);
|
|
807
|
+
if (!categoryMap)
|
|
808
|
+
return [];
|
|
809
|
+
const entries = name ? [[name, categoryMap.get(name)]] : Array.from(categoryMap.entries());
|
|
810
|
+
const samples = [];
|
|
811
|
+
for (const [, labelMap] of entries) {
|
|
812
|
+
if (!labelMap)
|
|
813
|
+
continue;
|
|
814
|
+
for (const buffer of labelMap.values()) {
|
|
815
|
+
samples.push(...buffer.getValues());
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return samples;
|
|
819
|
+
}
|
|
820
|
+
resolveMetricValue(metric, name, percentiles) {
|
|
821
|
+
if (metric === "p50")
|
|
822
|
+
return percentiles.p50;
|
|
823
|
+
if (metric === "p95")
|
|
824
|
+
return percentiles.p95;
|
|
825
|
+
if (metric === "p99")
|
|
826
|
+
return percentiles.p99;
|
|
827
|
+
if (metric === name)
|
|
828
|
+
return percentiles.p95;
|
|
829
|
+
return void 0;
|
|
830
|
+
}
|
|
831
|
+
getCategoryMap(category) {
|
|
832
|
+
const existing = this.samples.get(category);
|
|
833
|
+
if (existing)
|
|
834
|
+
return existing;
|
|
835
|
+
const created = /* @__PURE__ */ new Map();
|
|
836
|
+
this.samples.set(category, created);
|
|
837
|
+
return created;
|
|
838
|
+
}
|
|
839
|
+
getNameMap(categoryMap, name) {
|
|
840
|
+
const existing = categoryMap.get(name);
|
|
841
|
+
if (existing)
|
|
842
|
+
return existing;
|
|
843
|
+
const created = /* @__PURE__ */ new Map();
|
|
844
|
+
categoryMap.set(name, created);
|
|
845
|
+
return created;
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
var defaultMonitor = new PerformanceMonitor();
|
|
849
|
+
|
|
850
|
+
// ../../packages/core/dist/logging/error-tracker.js
|
|
851
|
+
var NoOpErrorTracker = class {
|
|
852
|
+
captureError(error, context) {
|
|
853
|
+
console.error("Error captured:", error.message, context);
|
|
854
|
+
}
|
|
855
|
+
captureException(error, context) {
|
|
856
|
+
console.error("Exception captured:", error, context);
|
|
857
|
+
}
|
|
858
|
+
captureMessage(message, level, context) {
|
|
859
|
+
console[level === "warning" ? "warn" : level](`Message captured [${level}]:`, message, context);
|
|
860
|
+
}
|
|
861
|
+
setUser(user) {
|
|
862
|
+
console.log("User set:", user);
|
|
863
|
+
}
|
|
864
|
+
clearUser() {
|
|
865
|
+
console.log("User cleared");
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
var errorTrackerInstance = new NoOpErrorTracker();
|
|
869
|
+
|
|
870
|
+
// src/api-client.ts
|
|
871
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
872
|
+
var ApiError = class extends Error {
|
|
873
|
+
constructor(message, code, status, details) {
|
|
874
|
+
super(message);
|
|
875
|
+
this.code = code;
|
|
876
|
+
this.status = status;
|
|
877
|
+
this.details = details;
|
|
878
|
+
this.name = "ApiError";
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
var MCPApiClient = class {
|
|
882
|
+
baseUrl;
|
|
883
|
+
apiKey;
|
|
884
|
+
timeout;
|
|
885
|
+
debug;
|
|
886
|
+
authContext = null;
|
|
887
|
+
constructor(config2) {
|
|
888
|
+
this.baseUrl = config2.baseUrl.replace(/\/$/, "");
|
|
889
|
+
this.apiKey = config2.apiKey;
|
|
890
|
+
this.timeout = config2.timeout ?? DEFAULT_TIMEOUT;
|
|
891
|
+
this.debug = config2.debug ?? false;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Make an HTTP request to the API
|
|
895
|
+
*/
|
|
896
|
+
async request(method, path, body) {
|
|
897
|
+
const url = `${this.baseUrl}${path}`;
|
|
898
|
+
const controller = new AbortController();
|
|
899
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
900
|
+
if (this.debug) {
|
|
901
|
+
console.error(`[mcp-api] ${method} ${url}`);
|
|
902
|
+
}
|
|
903
|
+
try {
|
|
904
|
+
const response = await fetch(url, {
|
|
905
|
+
method,
|
|
906
|
+
headers: {
|
|
907
|
+
"Content-Type": "application/json",
|
|
908
|
+
"X-API-Key": this.apiKey
|
|
909
|
+
},
|
|
910
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
911
|
+
signal: controller.signal
|
|
912
|
+
});
|
|
913
|
+
clearTimeout(timeoutId);
|
|
914
|
+
const data = await response.json();
|
|
915
|
+
if (!response.ok) {
|
|
916
|
+
throw new ApiError(
|
|
917
|
+
data.error || "API request failed",
|
|
918
|
+
data.code || "UNKNOWN_ERROR",
|
|
919
|
+
response.status,
|
|
920
|
+
data.details
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
return data;
|
|
924
|
+
} catch (error) {
|
|
925
|
+
clearTimeout(timeoutId);
|
|
926
|
+
if (error instanceof ApiError) {
|
|
927
|
+
throw error;
|
|
928
|
+
}
|
|
929
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
930
|
+
throw new ApiError(
|
|
931
|
+
"Request timed out",
|
|
932
|
+
"TIMEOUT",
|
|
933
|
+
408
|
|
934
|
+
);
|
|
935
|
+
}
|
|
936
|
+
throw new ApiError(
|
|
937
|
+
error instanceof Error ? error.message : "Unknown error",
|
|
938
|
+
"NETWORK_ERROR",
|
|
939
|
+
0
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Authenticate and get user context
|
|
945
|
+
*/
|
|
946
|
+
async authenticate() {
|
|
947
|
+
const context = await this.request("GET", "/api/mcp/auth");
|
|
948
|
+
this.authContext = context;
|
|
949
|
+
return context;
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Get cached auth context or authenticate
|
|
953
|
+
*/
|
|
954
|
+
async getAuthContext() {
|
|
955
|
+
if (this.authContext) {
|
|
956
|
+
return this.authContext;
|
|
957
|
+
}
|
|
958
|
+
return this.authenticate();
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* List accessible projects
|
|
962
|
+
*/
|
|
963
|
+
async listProjects(workspaceType = "ALL") {
|
|
964
|
+
return this.request(
|
|
965
|
+
"GET",
|
|
966
|
+
`/api/mcp/projects?workspaceType=${encodeURIComponent(workspaceType)}`
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Get single project details
|
|
971
|
+
*/
|
|
972
|
+
async getProject(projectId) {
|
|
973
|
+
return this.request("GET", `/api/mcp/projects/${projectId}`);
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Get project context (README, stack, conventions)
|
|
977
|
+
*/
|
|
978
|
+
async getProjectContext(projectId) {
|
|
979
|
+
return this.request(
|
|
980
|
+
"GET",
|
|
981
|
+
`/api/mcp/projects/${projectId}/context`
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Create a personal project
|
|
986
|
+
*/
|
|
987
|
+
async createPersonalProject(name, description, repositoryUrl) {
|
|
988
|
+
return this.request(
|
|
989
|
+
"POST",
|
|
990
|
+
"/api/mcp/projects/personal",
|
|
991
|
+
{ name, description, repositoryUrl }
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* List tasks with optional filters
|
|
996
|
+
*/
|
|
997
|
+
async listTasks(filters = {}) {
|
|
998
|
+
const params = new URLSearchParams();
|
|
999
|
+
if (filters.projectId) params.set("projectId", filters.projectId);
|
|
1000
|
+
if (filters.state) params.set("state", filters.state);
|
|
1001
|
+
if (filters.assigneeId) params.set("assigneeId", filters.assigneeId);
|
|
1002
|
+
const queryString = params.toString();
|
|
1003
|
+
const path = queryString ? `/api/mcp/tasks?${queryString}` : "/api/mcp/tasks";
|
|
1004
|
+
return this.request("GET", path);
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Get full task details
|
|
1008
|
+
*/
|
|
1009
|
+
async getTask(taskId) {
|
|
1010
|
+
return this.request("GET", `/api/mcp/tasks/${taskId}`);
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Assign task to current user and create branch
|
|
1014
|
+
*/
|
|
1015
|
+
async assignTask(taskId, projectId, expectedState = TaskState.READY) {
|
|
1016
|
+
return this.request("POST", `/api/mcp/tasks/${taskId}/assign`, {
|
|
1017
|
+
projectId,
|
|
1018
|
+
expectedState
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Update task progress
|
|
1023
|
+
*/
|
|
1024
|
+
async updateProgress(taskId, data) {
|
|
1025
|
+
return this.request("POST", `/api/mcp/tasks/${taskId}/progress`, data);
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Complete task and create PR
|
|
1029
|
+
*/
|
|
1030
|
+
async completeTask(taskId, projectId, pullRequestTitle, pullRequestBody) {
|
|
1031
|
+
return this.request("POST", `/api/mcp/tasks/${taskId}/complete`, {
|
|
1032
|
+
projectId,
|
|
1033
|
+
pullRequestTitle,
|
|
1034
|
+
pullRequestBody
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Abandon task and optionally delete branch
|
|
1039
|
+
*/
|
|
1040
|
+
async abandonTask(taskId, projectId, deleteBranch = false) {
|
|
1041
|
+
return this.request("POST", `/api/mcp/tasks/${taskId}/abandon`, {
|
|
1042
|
+
projectId,
|
|
1043
|
+
deleteBranch
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Report task error
|
|
1048
|
+
*/
|
|
1049
|
+
async reportError(taskId, errorType, errorMessage, context) {
|
|
1050
|
+
return this.request("POST", `/api/mcp/tasks/${taskId}/error`, {
|
|
1051
|
+
errorType,
|
|
1052
|
+
errorMessage,
|
|
1053
|
+
context
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Add note to task
|
|
1058
|
+
*/
|
|
1059
|
+
async addNote(taskId, content) {
|
|
1060
|
+
return this.request("POST", `/api/mcp/tasks/${taskId}/notes`, { content });
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Get GitHub token
|
|
1064
|
+
*/
|
|
1065
|
+
async getGitHubToken(organizationId) {
|
|
1066
|
+
const path = organizationId ? `/api/mcp/github-token?organizationId=${encodeURIComponent(organizationId)}` : "/api/mcp/github-token";
|
|
1067
|
+
return this.request("GET", path);
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
function createApiClientFromEnv() {
|
|
1071
|
+
const baseUrl = process.env.MTAAP_BASE_URL;
|
|
1072
|
+
const apiKey = process.env.MTAAP_API_KEY;
|
|
1073
|
+
if (!baseUrl) {
|
|
1074
|
+
throw new Error("MTAAP_BASE_URL environment variable is required");
|
|
1075
|
+
}
|
|
1076
|
+
if (!apiKey) {
|
|
1077
|
+
throw new Error("MTAAP_API_KEY environment variable is required");
|
|
1078
|
+
}
|
|
1079
|
+
return new MCPApiClient({
|
|
1080
|
+
baseUrl,
|
|
1081
|
+
apiKey,
|
|
1082
|
+
debug: process.env.MTAAP_DEBUG === "true"
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/permissions.ts
|
|
1087
|
+
var PERMISSION_RANK = {
|
|
1088
|
+
READ: 1,
|
|
1089
|
+
WRITE: 2,
|
|
1090
|
+
ADMIN: 3
|
|
1091
|
+
};
|
|
1092
|
+
function assertApiKeyPermission(apiKey, required, toolName) {
|
|
1093
|
+
const actualRank = PERMISSION_RANK[apiKey.permissions] ?? 0;
|
|
1094
|
+
const requiredRank = PERMISSION_RANK[required] ?? 0;
|
|
1095
|
+
if (actualRank >= requiredRank) {
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
console.warn("API key permission violation", {
|
|
1099
|
+
keyId: apiKey.id,
|
|
1100
|
+
requiredPermission: required,
|
|
1101
|
+
actualPermission: apiKey.permissions,
|
|
1102
|
+
tool: toolName
|
|
1103
|
+
});
|
|
1104
|
+
const error = new Error(
|
|
1105
|
+
`API key lacks required permissions (required: ${required})`
|
|
1106
|
+
);
|
|
1107
|
+
error.status = 403;
|
|
1108
|
+
throw error;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// src/index.ts
|
|
1112
|
+
async function createMCPServer() {
|
|
1113
|
+
const server = new import_mcp.McpServer({
|
|
1114
|
+
name: "mtaap",
|
|
1115
|
+
version: VERSION
|
|
1116
|
+
});
|
|
1117
|
+
const apiClient = createApiClientFromEnv();
|
|
1118
|
+
let authContext;
|
|
1119
|
+
try {
|
|
1120
|
+
authContext = await apiClient.authenticate();
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
if (error instanceof ApiError) {
|
|
1123
|
+
throw new Error(`Authentication failed: ${error.message}`);
|
|
1124
|
+
}
|
|
1125
|
+
throw error;
|
|
1126
|
+
}
|
|
1127
|
+
const mockApiKey = {
|
|
1128
|
+
permissions: authContext.permissions.includes("ADMIN") ? ApiKeyPermission.ADMIN : authContext.permissions.includes("WRITE") ? ApiKeyPermission.WRITE : ApiKeyPermission.READ
|
|
1129
|
+
};
|
|
1130
|
+
server.registerTool(
|
|
1131
|
+
"list_projects",
|
|
1132
|
+
{
|
|
1133
|
+
description: "List accessible projects (personal + team via tags)"
|
|
1134
|
+
},
|
|
1135
|
+
async (args) => {
|
|
1136
|
+
assertApiKeyPermission(
|
|
1137
|
+
mockApiKey,
|
|
1138
|
+
ApiKeyPermission.READ,
|
|
1139
|
+
"list_projects"
|
|
1140
|
+
);
|
|
1141
|
+
const validated = ListProjectsInputSchema.parse(args);
|
|
1142
|
+
try {
|
|
1143
|
+
const projects = await apiClient.listProjects(validated.workspaceType);
|
|
1144
|
+
return {
|
|
1145
|
+
content: [
|
|
1146
|
+
{
|
|
1147
|
+
type: "text",
|
|
1148
|
+
text: JSON.stringify(projects, null, 2)
|
|
1149
|
+
}
|
|
1150
|
+
]
|
|
1151
|
+
};
|
|
1152
|
+
} catch (error) {
|
|
1153
|
+
return handleApiError(error);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
);
|
|
1157
|
+
server.registerTool(
|
|
1158
|
+
"list_tasks",
|
|
1159
|
+
{
|
|
1160
|
+
description: "Returns available tasks (filterable by project, state)"
|
|
1161
|
+
},
|
|
1162
|
+
async (args) => {
|
|
1163
|
+
assertApiKeyPermission(mockApiKey, ApiKeyPermission.READ, "list_tasks");
|
|
1164
|
+
const validated = ListTasksInputSchema.parse(args);
|
|
1165
|
+
try {
|
|
1166
|
+
const tasks = await apiClient.listTasks({
|
|
1167
|
+
projectId: validated.projectId,
|
|
1168
|
+
state: validated.state,
|
|
1169
|
+
assigneeId: validated.assigneeId
|
|
1170
|
+
});
|
|
1171
|
+
return {
|
|
1172
|
+
content: [
|
|
1173
|
+
{
|
|
1174
|
+
type: "text",
|
|
1175
|
+
text: JSON.stringify(tasks, null, 2)
|
|
1176
|
+
}
|
|
1177
|
+
]
|
|
1178
|
+
};
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
return handleApiError(error);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
);
|
|
1184
|
+
server.registerTool(
|
|
1185
|
+
"get_task",
|
|
1186
|
+
{
|
|
1187
|
+
description: "Full task details including acceptance criteria"
|
|
1188
|
+
},
|
|
1189
|
+
async (args) => {
|
|
1190
|
+
assertApiKeyPermission(mockApiKey, ApiKeyPermission.READ, "get_task");
|
|
1191
|
+
const validated = GetTaskInputSchema.parse(args);
|
|
1192
|
+
try {
|
|
1193
|
+
const task = await apiClient.getTask(validated.taskId);
|
|
1194
|
+
return {
|
|
1195
|
+
content: [
|
|
1196
|
+
{
|
|
1197
|
+
type: "text",
|
|
1198
|
+
text: JSON.stringify(task, null, 2)
|
|
1199
|
+
}
|
|
1200
|
+
]
|
|
1201
|
+
};
|
|
1202
|
+
} catch (error) {
|
|
1203
|
+
return handleApiError(error);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
);
|
|
1207
|
+
server.registerTool(
|
|
1208
|
+
"assign_task",
|
|
1209
|
+
{
|
|
1210
|
+
description: "Atomic claim - creates branch. Fails if already taken."
|
|
1211
|
+
},
|
|
1212
|
+
async (args) => {
|
|
1213
|
+
assertApiKeyPermission(
|
|
1214
|
+
mockApiKey,
|
|
1215
|
+
ApiKeyPermission.WRITE,
|
|
1216
|
+
"assign_task"
|
|
1217
|
+
);
|
|
1218
|
+
const validated = AssignTaskInputSchema.parse(args);
|
|
1219
|
+
try {
|
|
1220
|
+
const result = await apiClient.assignTask(
|
|
1221
|
+
validated.taskId,
|
|
1222
|
+
validated.projectId,
|
|
1223
|
+
validated.expectedState
|
|
1224
|
+
);
|
|
1225
|
+
return {
|
|
1226
|
+
content: [
|
|
1227
|
+
{
|
|
1228
|
+
type: "text",
|
|
1229
|
+
text: JSON.stringify(result, null, 2)
|
|
1230
|
+
}
|
|
1231
|
+
]
|
|
1232
|
+
};
|
|
1233
|
+
} catch (error) {
|
|
1234
|
+
return handleApiError(error);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
);
|
|
1238
|
+
server.registerTool(
|
|
1239
|
+
"update_progress",
|
|
1240
|
+
{
|
|
1241
|
+
description: "Reports status, updates checkboxes, writes checkpoint"
|
|
1242
|
+
},
|
|
1243
|
+
async (args) => {
|
|
1244
|
+
assertApiKeyPermission(
|
|
1245
|
+
mockApiKey,
|
|
1246
|
+
ApiKeyPermission.WRITE,
|
|
1247
|
+
"update_progress"
|
|
1248
|
+
);
|
|
1249
|
+
const validated = UpdateProgressInputSchema.parse(args);
|
|
1250
|
+
try {
|
|
1251
|
+
const result = await apiClient.updateProgress(validated.taskId, {
|
|
1252
|
+
statusMessage: validated.statusMessage,
|
|
1253
|
+
completedCheckpointIds: validated.completedCheckpointIds,
|
|
1254
|
+
currentCheckpointIndex: validated.currentCheckpointIndex
|
|
1255
|
+
});
|
|
1256
|
+
return {
|
|
1257
|
+
content: [
|
|
1258
|
+
{
|
|
1259
|
+
type: "text",
|
|
1260
|
+
text: JSON.stringify(result, null, 2)
|
|
1261
|
+
}
|
|
1262
|
+
]
|
|
1263
|
+
};
|
|
1264
|
+
} catch (error) {
|
|
1265
|
+
return handleApiError(error);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
);
|
|
1269
|
+
server.registerTool(
|
|
1270
|
+
"complete_task",
|
|
1271
|
+
{
|
|
1272
|
+
description: "Marks complete, triggers PR, deletes local state file"
|
|
1273
|
+
},
|
|
1274
|
+
async (args) => {
|
|
1275
|
+
assertApiKeyPermission(
|
|
1276
|
+
mockApiKey,
|
|
1277
|
+
ApiKeyPermission.WRITE,
|
|
1278
|
+
"complete_task"
|
|
1279
|
+
);
|
|
1280
|
+
const validated = CompleteTaskInputSchema.parse(args);
|
|
1281
|
+
try {
|
|
1282
|
+
const result = await apiClient.completeTask(
|
|
1283
|
+
validated.taskId,
|
|
1284
|
+
validated.projectId,
|
|
1285
|
+
validated.pullRequestTitle,
|
|
1286
|
+
validated.pullRequestBody
|
|
1287
|
+
);
|
|
1288
|
+
return {
|
|
1289
|
+
content: [
|
|
1290
|
+
{
|
|
1291
|
+
type: "text",
|
|
1292
|
+
text: JSON.stringify(result, null, 2)
|
|
1293
|
+
}
|
|
1294
|
+
]
|
|
1295
|
+
};
|
|
1296
|
+
} catch (error) {
|
|
1297
|
+
return handleApiError(error);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
);
|
|
1301
|
+
server.registerTool(
|
|
1302
|
+
"check_active_task",
|
|
1303
|
+
{
|
|
1304
|
+
description: "Check for resumable task in .mtaap/active-task.json"
|
|
1305
|
+
},
|
|
1306
|
+
async () => {
|
|
1307
|
+
assertApiKeyPermission(
|
|
1308
|
+
mockApiKey,
|
|
1309
|
+
ApiKeyPermission.READ,
|
|
1310
|
+
"check_active_task"
|
|
1311
|
+
);
|
|
1312
|
+
const result = await checkActiveTask();
|
|
1313
|
+
return {
|
|
1314
|
+
content: [
|
|
1315
|
+
{
|
|
1316
|
+
type: "text",
|
|
1317
|
+
text: JSON.stringify(result, null, 2)
|
|
1318
|
+
}
|
|
1319
|
+
]
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
server.registerTool(
|
|
1324
|
+
"report_error",
|
|
1325
|
+
{
|
|
1326
|
+
description: "Report unrecoverable error, displays on task in webapp"
|
|
1327
|
+
},
|
|
1328
|
+
async (args) => {
|
|
1329
|
+
assertApiKeyPermission(
|
|
1330
|
+
mockApiKey,
|
|
1331
|
+
ApiKeyPermission.WRITE,
|
|
1332
|
+
"report_error"
|
|
1333
|
+
);
|
|
1334
|
+
const validated = ReportErrorInputSchema.parse(args);
|
|
1335
|
+
try {
|
|
1336
|
+
const result = await apiClient.reportError(
|
|
1337
|
+
validated.taskId,
|
|
1338
|
+
validated.errorType,
|
|
1339
|
+
validated.errorMessage,
|
|
1340
|
+
validated.context
|
|
1341
|
+
);
|
|
1342
|
+
return {
|
|
1343
|
+
content: [
|
|
1344
|
+
{
|
|
1345
|
+
type: "text",
|
|
1346
|
+
text: JSON.stringify(result, null, 2)
|
|
1347
|
+
}
|
|
1348
|
+
]
|
|
1349
|
+
};
|
|
1350
|
+
} catch (error) {
|
|
1351
|
+
return handleApiError(error);
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
);
|
|
1355
|
+
server.registerTool(
|
|
1356
|
+
"get_project_context",
|
|
1357
|
+
{
|
|
1358
|
+
description: "Returns assembled context (README, stack, conventions)"
|
|
1359
|
+
},
|
|
1360
|
+
async (args) => {
|
|
1361
|
+
assertApiKeyPermission(
|
|
1362
|
+
mockApiKey,
|
|
1363
|
+
ApiKeyPermission.READ,
|
|
1364
|
+
"get_project_context"
|
|
1365
|
+
);
|
|
1366
|
+
const validated = GetProjectContextInputSchema.parse(args);
|
|
1367
|
+
try {
|
|
1368
|
+
const context = await apiClient.getProjectContext(validated.projectId);
|
|
1369
|
+
return {
|
|
1370
|
+
content: [
|
|
1371
|
+
{
|
|
1372
|
+
type: "text",
|
|
1373
|
+
text: JSON.stringify(context, null, 2)
|
|
1374
|
+
}
|
|
1375
|
+
]
|
|
1376
|
+
};
|
|
1377
|
+
} catch (error) {
|
|
1378
|
+
return handleApiError(error);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
);
|
|
1382
|
+
server.registerTool(
|
|
1383
|
+
"add_note",
|
|
1384
|
+
{
|
|
1385
|
+
description: "Append implementation notes to task"
|
|
1386
|
+
},
|
|
1387
|
+
async (args) => {
|
|
1388
|
+
assertApiKeyPermission(mockApiKey, ApiKeyPermission.WRITE, "add_note");
|
|
1389
|
+
const validated = AddNoteInputSchema.parse(args);
|
|
1390
|
+
try {
|
|
1391
|
+
const result = await apiClient.addNote(
|
|
1392
|
+
validated.taskId,
|
|
1393
|
+
validated.content
|
|
1394
|
+
);
|
|
1395
|
+
return {
|
|
1396
|
+
content: [
|
|
1397
|
+
{
|
|
1398
|
+
type: "text",
|
|
1399
|
+
text: JSON.stringify(result, null, 2)
|
|
1400
|
+
}
|
|
1401
|
+
]
|
|
1402
|
+
};
|
|
1403
|
+
} catch (error) {
|
|
1404
|
+
return handleApiError(error);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
);
|
|
1408
|
+
server.registerTool(
|
|
1409
|
+
"abandon_task",
|
|
1410
|
+
{
|
|
1411
|
+
description: "Unassign from a task and optionally delete the branch"
|
|
1412
|
+
},
|
|
1413
|
+
async (args) => {
|
|
1414
|
+
assertApiKeyPermission(
|
|
1415
|
+
mockApiKey,
|
|
1416
|
+
ApiKeyPermission.WRITE,
|
|
1417
|
+
"abandon_task"
|
|
1418
|
+
);
|
|
1419
|
+
const validated = AbandonTaskInputSchema.parse(args);
|
|
1420
|
+
try {
|
|
1421
|
+
const result = await apiClient.abandonTask(
|
|
1422
|
+
validated.taskId,
|
|
1423
|
+
validated.projectId,
|
|
1424
|
+
validated.deleteBranch
|
|
1425
|
+
);
|
|
1426
|
+
return {
|
|
1427
|
+
content: [
|
|
1428
|
+
{
|
|
1429
|
+
type: "text",
|
|
1430
|
+
text: JSON.stringify(result, null, 2)
|
|
1431
|
+
}
|
|
1432
|
+
]
|
|
1433
|
+
};
|
|
1434
|
+
} catch (error) {
|
|
1435
|
+
return handleApiError(error);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
);
|
|
1439
|
+
server.registerTool(
|
|
1440
|
+
"create_personal_project",
|
|
1441
|
+
{
|
|
1442
|
+
description: "Create project in user's personal workspace"
|
|
1443
|
+
},
|
|
1444
|
+
async (args) => {
|
|
1445
|
+
assertApiKeyPermission(
|
|
1446
|
+
mockApiKey,
|
|
1447
|
+
ApiKeyPermission.WRITE,
|
|
1448
|
+
"create_personal_project"
|
|
1449
|
+
);
|
|
1450
|
+
const validated = CreatePersonalProjectInputSchema.parse(args);
|
|
1451
|
+
try {
|
|
1452
|
+
const result = await apiClient.createPersonalProject(
|
|
1453
|
+
validated.name,
|
|
1454
|
+
validated.description,
|
|
1455
|
+
validated.repositoryUrl
|
|
1456
|
+
);
|
|
1457
|
+
return {
|
|
1458
|
+
content: [
|
|
1459
|
+
{
|
|
1460
|
+
type: "text",
|
|
1461
|
+
text: JSON.stringify(result, null, 2)
|
|
1462
|
+
}
|
|
1463
|
+
]
|
|
1464
|
+
};
|
|
1465
|
+
} catch (error) {
|
|
1466
|
+
return handleApiError(error);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
);
|
|
1470
|
+
server.registerTool(
|
|
1471
|
+
"get_version",
|
|
1472
|
+
{
|
|
1473
|
+
description: "Get the current MTAAP version"
|
|
1474
|
+
},
|
|
1475
|
+
async () => {
|
|
1476
|
+
assertApiKeyPermission(mockApiKey, ApiKeyPermission.READ, "get_version");
|
|
1477
|
+
return {
|
|
1478
|
+
content: [
|
|
1479
|
+
{
|
|
1480
|
+
type: "text",
|
|
1481
|
+
text: JSON.stringify(
|
|
1482
|
+
{
|
|
1483
|
+
version: VERSION,
|
|
1484
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1485
|
+
},
|
|
1486
|
+
null,
|
|
1487
|
+
2
|
|
1488
|
+
)
|
|
1489
|
+
}
|
|
1490
|
+
]
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
);
|
|
1494
|
+
const transport = new import_stdio.StdioServerTransport();
|
|
1495
|
+
await server.connect(transport);
|
|
1496
|
+
}
|
|
1497
|
+
function handleApiError(error) {
|
|
1498
|
+
if (error instanceof ApiError) {
|
|
1499
|
+
return {
|
|
1500
|
+
content: [
|
|
1501
|
+
{
|
|
1502
|
+
type: "text",
|
|
1503
|
+
text: JSON.stringify(
|
|
1504
|
+
{
|
|
1505
|
+
error: error.message,
|
|
1506
|
+
code: error.code,
|
|
1507
|
+
status: error.status,
|
|
1508
|
+
details: error.details
|
|
1509
|
+
},
|
|
1510
|
+
null,
|
|
1511
|
+
2
|
|
1512
|
+
)
|
|
1513
|
+
}
|
|
1514
|
+
],
|
|
1515
|
+
isError: true
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1519
|
+
return {
|
|
1520
|
+
content: [
|
|
1521
|
+
{
|
|
1522
|
+
type: "text",
|
|
1523
|
+
text: JSON.stringify({ error: message }, null, 2)
|
|
1524
|
+
}
|
|
1525
|
+
],
|
|
1526
|
+
isError: true
|
|
1527
|
+
};
|
|
1528
|
+
}
|
|
1529
|
+
async function checkActiveTask() {
|
|
1530
|
+
const fs = await import("fs");
|
|
1531
|
+
const path = await import("path");
|
|
1532
|
+
const activeTaskPath = path.join(process.cwd(), ".mtaap", "active-task.json");
|
|
1533
|
+
try {
|
|
1534
|
+
await fs.promises.access(activeTaskPath);
|
|
1535
|
+
const content = await fs.promises.readFile(activeTaskPath, "utf-8");
|
|
1536
|
+
const activeTask = JSON.parse(content);
|
|
1537
|
+
return {
|
|
1538
|
+
hasActiveTask: true,
|
|
1539
|
+
task: activeTask
|
|
1540
|
+
};
|
|
1541
|
+
} catch {
|
|
1542
|
+
return {
|
|
1543
|
+
hasActiveTask: false,
|
|
1544
|
+
task: null
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1549
|
+
0 && (module.exports = {
|
|
1550
|
+
createMCPServer
|
|
1551
|
+
});
|
|
9
1552
|
//# sourceMappingURL=index.js.map
|