@mtaap/mcp 0.1.3 → 0.2.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.
@@ -1,2268 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
18
-
19
- // src/index.ts
20
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
21
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
22
-
23
- // ../../packages/db/dist/index.js
24
- var dist_exports = {};
25
- __export(dist_exports, {
26
- prisma: () => prisma2
27
- });
28
-
29
- // ../../packages/db/dist/client.js
30
- var client_exports = {};
31
- __export(client_exports, {
32
- default: () => client_default,
33
- prisma: () => prisma
34
- });
35
- __reExport(client_exports, client_star);
36
- import { PrismaClient } from "@prisma/client";
37
- import { PrismaPg } from "@prisma/adapter-pg";
38
- import * as client_star from "@prisma/client";
39
- var adapter = new PrismaPg({
40
- connectionString: process.env.DATABASE_URL
41
- });
42
- var globalForPrisma = globalThis;
43
- var prisma = globalForPrisma.prisma ?? new PrismaClient({
44
- adapter
45
- });
46
- if (process.env.NODE_ENV !== "production") {
47
- globalForPrisma.prisma = prisma;
48
- }
49
- var client_default = prisma;
50
-
51
- // ../../packages/core/dist/constants/enums.js
52
- var TaskState;
53
- (function(TaskState2) {
54
- TaskState2["BACKLOG"] = "BACKLOG";
55
- TaskState2["READY"] = "READY";
56
- TaskState2["IN_PROGRESS"] = "IN_PROGRESS";
57
- TaskState2["REVIEW"] = "REVIEW";
58
- TaskState2["DONE"] = "DONE";
59
- })(TaskState || (TaskState = {}));
60
- var UserRole;
61
- (function(UserRole2) {
62
- UserRole2["ADMIN"] = "ADMIN";
63
- UserRole2["MEMBER"] = "MEMBER";
64
- })(UserRole || (UserRole = {}));
65
- var ProjectType;
66
- (function(ProjectType2) {
67
- ProjectType2["TEAM"] = "TEAM";
68
- ProjectType2["PERSONAL"] = "PERSONAL";
69
- })(ProjectType || (ProjectType = {}));
70
- var ProjectOrigin;
71
- (function(ProjectOrigin2) {
72
- ProjectOrigin2["CREATED"] = "CREATED";
73
- ProjectOrigin2["PROMOTED"] = "PROMOTED";
74
- })(ProjectOrigin || (ProjectOrigin = {}));
75
- var TaskPriority;
76
- (function(TaskPriority2) {
77
- TaskPriority2["LOW"] = "LOW";
78
- TaskPriority2["MEDIUM"] = "MEDIUM";
79
- TaskPriority2["HIGH"] = "HIGH";
80
- TaskPriority2["CRITICAL"] = "CRITICAL";
81
- })(TaskPriority || (TaskPriority = {}));
82
- var DeploymentMode;
83
- (function(DeploymentMode2) {
84
- DeploymentMode2["SAAS"] = "saas";
85
- DeploymentMode2["ONPREM"] = "onprem";
86
- })(DeploymentMode || (DeploymentMode = {}));
87
- var ErrorType;
88
- (function(ErrorType3) {
89
- ErrorType3["BUILD_FAILURE"] = "BUILD_FAILURE";
90
- ErrorType3["TEST_FAILURE"] = "TEST_FAILURE";
91
- ErrorType3["CONFLICT"] = "CONFLICT";
92
- ErrorType3["AUTH_ERROR"] = "AUTH_ERROR";
93
- ErrorType3["OTHER"] = "OTHER";
94
- })(ErrorType || (ErrorType = {}));
95
- var PRStatus;
96
- (function(PRStatus2) {
97
- PRStatus2["OPEN"] = "OPEN";
98
- PRStatus2["CLOSED"] = "CLOSED";
99
- PRStatus2["MERGED"] = "MERGED";
100
- PRStatus2["DELETED"] = "DELETED";
101
- })(PRStatus || (PRStatus = {}));
102
- var PricingTier;
103
- (function(PricingTier2) {
104
- PricingTier2["FREE"] = "FREE";
105
- PricingTier2["PRO"] = "PRO";
106
- PricingTier2["ENTERPRISE"] = "ENTERPRISE";
107
- })(PricingTier || (PricingTier = {}));
108
- var ApiKeyPermission;
109
- (function(ApiKeyPermission2) {
110
- ApiKeyPermission2["READ"] = "READ";
111
- ApiKeyPermission2["WRITE"] = "WRITE";
112
- ApiKeyPermission2["ADMIN"] = "ADMIN";
113
- })(ApiKeyPermission || (ApiKeyPermission = {}));
114
- var WebSocketEventType;
115
- (function(WebSocketEventType2) {
116
- WebSocketEventType2["TASK_ASSIGNED"] = "task.assigned";
117
- WebSocketEventType2["TASK_ABANDONED"] = "task.abandoned";
118
- WebSocketEventType2["TASK_PROGRESS"] = "task.progress";
119
- WebSocketEventType2["TASK_PR_CREATED"] = "task.pr_created";
120
- WebSocketEventType2["TASK_REVIEW_REQUESTED"] = "task.review_requested";
121
- WebSocketEventType2["TASK_COMPLETED"] = "task.completed";
122
- WebSocketEventType2["TASK_ERROR"] = "task.error";
123
- WebSocketEventType2["TASK_STATE_CHANGED"] = "task.state_changed";
124
- WebSocketEventType2["MEMBER_JOINED"] = "member.joined";
125
- })(WebSocketEventType || (WebSocketEventType = {}));
126
- var AuthProvider;
127
- (function(AuthProvider2) {
128
- AuthProvider2["CREDENTIALS"] = "credentials";
129
- AuthProvider2["LDAP"] = "ldap";
130
- AuthProvider2["SSO"] = "sso";
131
- })(AuthProvider || (AuthProvider = {}));
132
- var SubscriptionStatus;
133
- (function(SubscriptionStatus2) {
134
- SubscriptionStatus2["ACTIVE"] = "ACTIVE";
135
- SubscriptionStatus2["INACTIVE"] = "INACTIVE";
136
- SubscriptionStatus2["PAST_DUE"] = "PAST_DUE";
137
- SubscriptionStatus2["CANCELED"] = "CANCELED";
138
- SubscriptionStatus2["INCOMPLETE"] = "INCOMPLETE";
139
- })(SubscriptionStatus || (SubscriptionStatus = {}));
140
- var EventType;
141
- (function(EventType2) {
142
- EventType2["AUTH"] = "AUTH";
143
- EventType2["AUTHORIZATION"] = "AUTHORIZATION";
144
- EventType2["ACCESS"] = "ACCESS";
145
- EventType2["MODIFICATION"] = "MODIFICATION";
146
- })(EventType || (EventType = {}));
147
-
148
- // ../../packages/core/dist/constants/state-machine.js
149
- var VALID_TRANSITIONS = {
150
- [TaskState.BACKLOG]: [TaskState.READY],
151
- [TaskState.READY]: [TaskState.BACKLOG, TaskState.IN_PROGRESS],
152
- [TaskState.IN_PROGRESS]: [
153
- TaskState.BACKLOG,
154
- TaskState.READY,
155
- TaskState.REVIEW
156
- ],
157
- [TaskState.REVIEW]: [
158
- TaskState.BACKLOG,
159
- TaskState.READY,
160
- TaskState.IN_PROGRESS,
161
- TaskState.DONE
162
- ],
163
- [TaskState.DONE]: []
164
- };
165
-
166
- // ../../packages/core/dist/version.js
167
- var VERSION = "0.1.0";
168
-
169
- // ../../packages/core/dist/config/index.js
170
- var DEPLOYMENT_MODE = process.env.DEPLOYMENT_MODE || "saas";
171
- var config = {
172
- version: VERSION,
173
- deploymentMode: DEPLOYMENT_MODE,
174
- billing: {
175
- enabled: DEPLOYMENT_MODE === "saas",
176
- revenuecat: {
177
- publicKey: process.env.REVENUECAT_PUBLIC_API_KEY,
178
- stripeKey: process.env.STRIPE_SECRET_KEY
179
- // Required by RevenueCat Web Billing
180
- }
181
- },
182
- licensing: {
183
- enabled: DEPLOYMENT_MODE === "onprem",
184
- licenseKey: process.env.LICENSE_KEY
185
- },
186
- auth: {
187
- credentials: true,
188
- ldap: process.env.LDAP_ENABLED === "true"
189
- },
190
- git: {
191
- deleteMergedBranches: process.env.DELETE_MERGED_BRANCHES !== "false",
192
- enforceConventionalCommits: process.env.ENFORCE_CONVENTIONAL_COMMITS === "true",
193
- defaultBaseBranch: process.env.DEFAULT_BASE_BRANCH || "develop"
194
- },
195
- pricing: {
196
- maxPersonalProjects: {
197
- FREE: 2,
198
- PRO: 5,
199
- ENTERPRISE: 10
200
- },
201
- maxCollaboratorsPerProject: {
202
- FREE: 3,
203
- PRO: -1,
204
- ENTERPRISE: -1
205
- },
206
- maxProjectsPerOrg: {
207
- FREE: 5,
208
- PRO: -1,
209
- ENTERPRISE: -1
210
- },
211
- maxSeats: {
212
- FREE: 3,
213
- PRO: -1,
214
- ENTERPRISE: -1
215
- },
216
- // Default seats when subscription doesn't specify an explicit seat count
217
- defaultSeats: {
218
- FREE: 3,
219
- PRO: 10,
220
- ENTERPRISE: 999999
221
- }
222
- },
223
- features: {
224
- stripe: {
225
- enabled: DEPLOYMENT_MODE === "saas"
226
- },
227
- gitlab: {
228
- enabled: true
229
- },
230
- ldap: {
231
- enabled: process.env.LDAP_ENABLED === "true"
232
- },
233
- auditLogs: {
234
- enabled: process.env.AUDIT_LOGS_ENABLED === "true"
235
- }
236
- },
237
- api: {
238
- apiKey: {
239
- defaultExpiryDays: 90,
240
- prefix: "usr_"
241
- },
242
- rateLimit: {
243
- requestsPerMinute: 100,
244
- requestsPerHour: 1e3
245
- }
246
- },
247
- limits: {
248
- projectNameMaxLength: 100,
249
- taskDescriptionMaxLength: 5e3,
250
- notesMaxLength: 500,
251
- conventionsNotesMaxLength: 500,
252
- recentCompletedTasksLimit: 10
253
- }
254
- };
255
- var DEFAULT_SEAT_LIMITS = {
256
- [PricingTier.FREE]: config.pricing.defaultSeats.FREE,
257
- [PricingTier.PRO]: config.pricing.defaultSeats.PRO,
258
- [PricingTier.ENTERPRISE]: config.pricing.defaultSeats.ENTERPRISE
259
- };
260
-
261
- // ../../packages/core/dist/types/index.js
262
- import { z } from "zod";
263
- var UserIdSchema = z.string().regex(/^usr_[a-zA-Z0-9]+$/);
264
- var UserSchema = z.object({
265
- id: UserIdSchema,
266
- email: z.string().email(),
267
- name: z.string().min(1).max(255),
268
- role: z.nativeEnum(UserRole),
269
- organizationId: z.string().optional(),
270
- lastActiveAt: z.coerce.date().optional(),
271
- createdAt: z.coerce.date()
272
- });
273
- var OrganizationUserSchema = z.object({
274
- id: z.number().int(),
275
- userId: UserIdSchema,
276
- organizationId: z.string(),
277
- roleId: z.nativeEnum(UserRole).optional(),
278
- user: UserSchema.pick({ id: true, email: true, name: true, role: true }),
279
- createdAt: z.coerce.date()
280
- });
281
- var OrganizationIdSchema = z.string().regex(/^org_[a-zA-Z0-9]+$/);
282
- var OrganizationSchema = z.object({
283
- id: OrganizationIdSchema,
284
- name: z.string().min(1).max(255),
285
- slug: z.string().min(1).max(100).regex(/^[a-z0-9-]+$/),
286
- logoUrl: z.string().url().nullable(),
287
- accentColor: z.string().regex(/^#[0-9A-Fa-f]{6}$/).nullable(),
288
- tenantName: z.string().nullable(),
289
- pricingTier: z.nativeEnum(PricingTier),
290
- createdAt: z.coerce.date()
291
- });
292
- var OrganizationSettingsSchema = z.object({
293
- organizationId: OrganizationIdSchema,
294
- ldapEnabled: z.boolean(),
295
- ldapUrl: z.string().url().nullable(),
296
- ldapBindDN: z.string().nullable(),
297
- ldapSearchBase: z.string().nullable(),
298
- deleteMergedBranches: z.boolean(),
299
- enforceConventionalCommits: z.boolean(),
300
- maxPersonalProjectsPerUser: z.number().int().min(0)
301
- });
302
- var TagSchema = z.object({
303
- id: z.string(),
304
- name: z.string().min(1).max(50),
305
- organizationId: OrganizationIdSchema,
306
- createdAt: z.coerce.date()
307
- });
308
- var ProjectIdSchema = z.string().regex(/^prj_[a-zA-Z0-9]+$/);
309
- var ProjectSchema = z.object({
310
- id: ProjectIdSchema,
311
- name: z.string().min(1).max(100),
312
- description: z.string().max(500).nullable(),
313
- type: z.nativeEnum(ProjectType),
314
- origin: z.nativeEnum(ProjectOrigin),
315
- organizationId: OrganizationIdSchema,
316
- ownerId: UserIdSchema.nullable(),
317
- repositoryUrl: z.string().url(),
318
- baseBranch: z.string().default("develop"),
319
- tags: z.array(z.string()),
320
- createdAt: z.coerce.date(),
321
- updatedAt: z.coerce.date()
322
- });
323
- var EpicIdSchema = z.string().regex(/^epc_[a-zA-Z0-9]+$/);
324
- var EpicSchema = z.object({
325
- id: EpicIdSchema,
326
- projectId: ProjectIdSchema,
327
- name: z.string().min(1).max(200),
328
- description: z.string().nullable(),
329
- createdAt: z.coerce.date(),
330
- updatedAt: z.coerce.date()
331
- });
332
- var TaskIdSchema = z.string().regex(/^tsk_[a-zA-Z0-9]+$/);
333
- var TaskSchema = z.object({
334
- id: TaskIdSchema,
335
- projectId: ProjectIdSchema,
336
- epicId: EpicIdSchema.nullable(),
337
- title: z.string().min(1).max(200),
338
- description: z.string().max(5e3),
339
- state: z.nativeEnum(TaskState),
340
- priority: z.nativeEnum(TaskPriority),
341
- assigneeId: UserIdSchema.nullable(),
342
- createdBy: UserIdSchema.nullable(),
343
- assignedAt: z.coerce.date().nullable(),
344
- startedAt: z.coerce.date().nullable(),
345
- completedAt: z.coerce.date().nullable(),
346
- branchName: z.string().nullable(),
347
- pullRequestUrl: z.string().url().nullable(),
348
- pullRequestNumber: z.number().int().nullable(),
349
- pullRequestStatus: z.nativeEnum(PRStatus).nullable(),
350
- errorType: z.nativeEnum(ErrorType).nullable(),
351
- errorMessage: z.string().max(1e3).nullable(),
352
- createdAt: z.coerce.date(),
353
- updatedAt: z.coerce.date()
354
- });
355
- var AcceptanceCriterionSchema = z.object({
356
- id: z.string(),
357
- taskId: TaskIdSchema,
358
- description: z.string().min(1).max(500),
359
- completed: z.boolean(),
360
- completedAt: z.coerce.date().nullable(),
361
- order: z.number().int(),
362
- createdAt: z.coerce.date()
363
- });
364
- var ProgressUpdateSchema = z.object({
365
- id: z.string(),
366
- taskId: TaskIdSchema,
367
- userId: UserIdSchema,
368
- message: z.string().max(2e3),
369
- checkpoints: z.array(z.string()).optional(),
370
- createdAt: z.coerce.date()
371
- });
372
- var TaskNoteSchema = z.object({
373
- id: z.string(),
374
- taskId: TaskIdSchema,
375
- userId: UserIdSchema,
376
- content: z.string().max(500),
377
- createdAt: z.coerce.date()
378
- });
379
- var ApiKeyIdSchema = z.string().regex(/^key_[a-zA-Z0-9]+$/);
380
- var ApiKeySchema = z.object({
381
- id: ApiKeyIdSchema,
382
- userId: UserIdSchema,
383
- name: z.string().min(1).max(100),
384
- keyHash: z.string(),
385
- permissions: z.nativeEnum(ApiKeyPermission),
386
- lastUsedAt: z.coerce.date().nullable(),
387
- expiresAt: z.coerce.date().nullable(),
388
- revoked: z.boolean(),
389
- createdAt: z.coerce.date()
390
- });
391
- var SubscriptionIdSchema = z.string();
392
- var SubscriptionSchema = z.object({
393
- id: SubscriptionIdSchema,
394
- organizationId: OrganizationIdSchema,
395
- pricingTier: z.nativeEnum(PricingTier),
396
- seats: z.number().int().min(0),
397
- stripeSubscriptionId: z.string().nullable(),
398
- stripeCustomerId: z.string().nullable(),
399
- status: z.enum(["active", "past_due", "canceled", "incomplete"]),
400
- currentPeriodStart: z.coerce.date(),
401
- currentPeriodEnd: z.coerce.date(),
402
- createdAt: z.coerce.date()
403
- });
404
- var ProjectCollaboratorSchema = z.object({
405
- id: z.string(),
406
- projectId: ProjectIdSchema,
407
- userId: UserIdSchema,
408
- addedBy: UserIdSchema,
409
- createdAt: z.coerce.date()
410
- });
411
-
412
- // ../../packages/core/dist/validation/index.js
413
- import { z as z2 } from "zod";
414
- var ListProjectsInputSchema = z2.object({
415
- workspaceType: z2.preprocess((val) => typeof val === "string" ? val.toUpperCase() : val, z2.enum(["TEAM", "PERSONAL", "ALL"]).optional())
416
- });
417
- var ListTasksInputSchema = z2.object({
418
- projectId: z2.string().optional(),
419
- state: z2.nativeEnum(TaskState).optional(),
420
- assigneeId: z2.string().optional()
421
- });
422
- var GetTaskInputSchema = z2.object({
423
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/)
424
- });
425
- var AssignTaskInputSchema = z2.object({
426
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/),
427
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/),
428
- expectedState: z2.nativeEnum(TaskState).default(TaskState.READY)
429
- });
430
- var UpdateProgressInputSchema = z2.object({
431
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/),
432
- statusMessage: z2.string().max(1e3).optional(),
433
- completedCheckpointIds: z2.array(z2.string()).optional(),
434
- currentCheckpointIndex: z2.number().int().optional()
435
- });
436
- var CompleteTaskInputSchema = z2.object({
437
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/),
438
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/),
439
- pullRequestTitle: z2.string().min(1).max(300).optional(),
440
- pullRequestBody: z2.string().max(1e4).optional()
441
- });
442
- var ReportErrorInputSchema = z2.object({
443
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/),
444
- errorType: z2.nativeEnum(ErrorType),
445
- errorMessage: z2.string().min(1).max(1e3),
446
- context: z2.string().max(2e3).optional()
447
- });
448
- var GetProjectContextInputSchema = z2.object({
449
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/)
450
- });
451
- var AddNoteInputSchema = z2.object({
452
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/),
453
- content: z2.string().min(1).max(500)
454
- });
455
- var AbandonTaskInputSchema = z2.object({
456
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/),
457
- taskId: z2.string().regex(/^tsk_[a-zA-Z0-9]+$/),
458
- deleteBranch: z2.boolean().optional()
459
- });
460
- var CreatePersonalProjectInputSchema = z2.object({
461
- name: z2.string().min(1).max(100),
462
- description: z2.string().max(500).optional(),
463
- repositoryUrl: z2.string().url()
464
- });
465
- var CheckActiveTaskInputSchema = z2.object({});
466
- var CreateOrganizationInputSchema = z2.object({
467
- name: z2.string().min(1).max(255),
468
- slug: z2.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
469
- });
470
- var UpdateOrganizationInputSchema = z2.object({
471
- organizationId: z2.string().regex(/^org_[a-zA-Z0-9]+$/),
472
- name: z2.string().min(1).max(255).optional(),
473
- logoUrl: z2.string().url().nullable().optional(),
474
- accentColor: z2.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
475
- tenantName: z2.string().max(255).nullable().optional()
476
- });
477
- var CreateProjectInputSchema = z2.object({
478
- name: z2.string().min(1).max(100),
479
- description: z2.string().max(500).optional(),
480
- type: z2.nativeEnum(ProjectType),
481
- repositoryUrl: z2.string().url(),
482
- baseBranch: z2.string().default("develop").optional(),
483
- tags: z2.array(z2.string()).default([])
484
- });
485
- var UpdateProjectInputSchema = z2.object({
486
- projectId: z2.string().min(1).optional(),
487
- name: z2.string().min(1).max(100).optional(),
488
- description: z2.string().max(500).optional(),
489
- repositoryUrl: z2.string().url().optional(),
490
- baseBranch: z2.string().optional(),
491
- tags: z2.array(z2.string()).optional()
492
- });
493
- var CreateEpicInputSchema = z2.object({
494
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/),
495
- name: z2.string().min(1).max(200),
496
- description: z2.string().max(2e3).optional()
497
- });
498
- var CreateTaskInputSchema = z2.object({
499
- projectId: z2.string().min(1),
500
- epicId: z2.string().min(1).nullable().optional(),
501
- title: z2.string().min(1).max(200),
502
- description: z2.string().max(5e3),
503
- priority: z2.nativeEnum(TaskPriority).default(TaskPriority.MEDIUM),
504
- acceptanceCriteria: z2.array(z2.object({
505
- description: z2.string().min(1).max(500)
506
- })).min(1)
507
- });
508
- var UpdateTaskInputSchema = z2.object({
509
- taskId: z2.string().min(1),
510
- title: z2.string().min(1).max(200).optional(),
511
- description: z2.string().max(5e3).optional(),
512
- priority: z2.nativeEnum(TaskPriority).optional(),
513
- state: z2.nativeEnum(TaskState).optional(),
514
- assigneeId: z2.string().nullable().optional(),
515
- acceptanceCriteria: z2.array(z2.object({
516
- id: z2.string().optional(),
517
- description: z2.string().min(1).max(500),
518
- completed: z2.boolean().optional()
519
- })).optional()
520
- });
521
- var AssignTaskWebappInputSchema = z2.object({
522
- taskId: z2.string().min(1),
523
- userId: z2.string().min(1)
524
- });
525
- var CreateTagInputSchema = z2.object({
526
- organizationId: z2.string().regex(/^org_[a-zA-Z0-9]+$/),
527
- name: z2.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
528
- });
529
- var UpdateTagInputSchema = z2.object({
530
- name: z2.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
531
- });
532
- var UpdateOrganizationSettingsInputSchema = z2.object({
533
- organizationId: z2.string().regex(/^org_[a-zA-Z0-9]+$/),
534
- ldapEnabled: z2.boolean().optional(),
535
- ldapUrl: z2.string().url().nullable().optional(),
536
- ldapBindDN: z2.string().nullable().optional(),
537
- ldapSearchBase: z2.string().nullable().optional(),
538
- deleteMergedBranches: z2.boolean().optional(),
539
- enforceConventionalCommits: z2.boolean().optional(),
540
- maxPersonalProjectsPerUser: z2.number().int().min(0).optional(),
541
- logoUrl: z2.string().url().nullable().optional(),
542
- accentColor: z2.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
543
- tenantName: z2.string().max(255).nullable().optional()
544
- });
545
- var InviteUserInputSchema = z2.object({
546
- organizationId: z2.string().regex(/^org_[a-zA-Z0-9]+$/),
547
- email: z2.string().email(),
548
- role: z2.nativeEnum(UserRole).default(UserRole.MEMBER),
549
- tags: z2.array(z2.string()).default([])
550
- });
551
- var AssignUserTagsInputSchema = z2.object({
552
- userId: z2.string().regex(/^usr_[a-zA-Z0-9]+$/),
553
- tags: z2.array(z2.string()).min(0)
554
- });
555
- var InviteCollaboratorInputSchema = z2.object({
556
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/),
557
- email: z2.string().email()
558
- });
559
- var PublishProjectInputSchema = z2.object({
560
- projectId: z2.string().regex(/^prj_[a-zA-Z0-9]+$/),
561
- transferOwnership: z2.boolean().default(false),
562
- tags: z2.array(z2.string()).min(1)
563
- });
564
- var GenerateApiKeyInputSchema = z2.object({
565
- name: z2.string().min(1).max(100),
566
- expiresInDays: z2.number().int().min(1).max(365).default(90),
567
- permissions: z2.nativeEnum(ApiKeyPermission).default(ApiKeyPermission.WRITE)
568
- });
569
- var RevokeApiKeyInputSchema = z2.object({
570
- keyId: z2.string().regex(/^key_[a-zA-Z0-9]+$/)
571
- });
572
- var LoginInputSchema = z2.object({
573
- email: z2.string().email(),
574
- password: z2.string().min(8).max(255)
575
- });
576
- var RegisterInputSchema = z2.object({
577
- email: z2.string().email(),
578
- password: z2.string().min(8).max(255),
579
- name: z2.string().min(1).max(255),
580
- organizationSlug: z2.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
581
- });
582
-
583
- // ../../packages/core/dist/logging/metrics.js
584
- var metrics = /* @__PURE__ */ new Map();
585
- function labelsToKey(labels) {
586
- if (!labels || Object.keys(labels).length === 0)
587
- return "";
588
- return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}="${v}"`).join(",");
589
- }
590
- function createCounter(name, help) {
591
- const data = {
592
- name,
593
- type: "counter",
594
- help,
595
- values: /* @__PURE__ */ new Map()
596
- };
597
- metrics.set(name, data);
598
- return {
599
- inc(labels, value = 1) {
600
- const key = labelsToKey(labels);
601
- const current = data.values.get(key) || 0;
602
- data.values.set(key, current + value);
603
- }
604
- };
605
- }
606
- function createGauge(name, help) {
607
- const data = {
608
- name,
609
- type: "gauge",
610
- help,
611
- values: /* @__PURE__ */ new Map()
612
- };
613
- metrics.set(name, data);
614
- return {
615
- set(labels, value) {
616
- const key = labelsToKey(labels);
617
- data.values.set(key, value);
618
- },
619
- inc(labels, value = 1) {
620
- const key = labelsToKey(labels);
621
- const current = data.values.get(key) || 0;
622
- data.values.set(key, current + value);
623
- },
624
- dec(labels, value = 1) {
625
- const key = labelsToKey(labels);
626
- const current = data.values.get(key) || 0;
627
- data.values.set(key, current - value);
628
- }
629
- };
630
- }
631
- function createHistogram(name, help, buckets = [5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]) {
632
- const data = {
633
- name,
634
- type: "histogram",
635
- help,
636
- values: /* @__PURE__ */ new Map(),
637
- buckets
638
- };
639
- metrics.set(name, data);
640
- return {
641
- observe(labels, value) {
642
- const baseKey = labelsToKey(labels);
643
- const sumKey = `${baseKey}|sum`;
644
- const countKey = `${baseKey}|count`;
645
- data.values.set(sumKey, (data.values.get(sumKey) || 0) + value);
646
- data.values.set(countKey, (data.values.get(countKey) || 0) + 1);
647
- for (const bucket of buckets) {
648
- const bucketKey = `${baseKey}|le="${bucket}"`;
649
- if (value <= bucket) {
650
- data.values.set(bucketKey, (data.values.get(bucketKey) || 0) + 1);
651
- }
652
- }
653
- const infKey = `${baseKey}|le="+Inf"`;
654
- data.values.set(infKey, (data.values.get(infKey) || 0) + 1);
655
- }
656
- };
657
- }
658
- var httpRequestsTotal = createCounter("mtaap_http_requests_total", "Total number of HTTP requests");
659
- var httpRequestDuration = createHistogram("mtaap_http_request_duration_seconds", "HTTP request duration in seconds");
660
- var activeUsers = createGauge("mtaap_active_users", "Number of active users");
661
- var tasksTotal = createCounter("mtaap_tasks_total", "Total number of tasks by state");
662
- var taskStateChanges = createCounter("mtaap_task_state_changes_total", "Total number of task state changes");
663
- var httpErrorsTotal = createCounter("mtaap_http_errors_total", "Total number of HTTP errors");
664
- var httpActiveConnections = createGauge("mtaap_http_active_connections", "Number of active HTTP connections");
665
- var newSignupsTotal = createCounter("mtaap_new_signups_total", "Total number of new user signups");
666
- var loginSuccessTotal = createCounter("mtaap_login_success_total", "Total number of successful logins");
667
- var loginFailureTotal = createCounter("mtaap_login_failure_total", "Total number of failed logins");
668
- var dbConnectionPoolActive = createGauge("mtaap_db_connection_pool_active", "Number of active database connections");
669
- var dbConnectionPoolIdle = createGauge("mtaap_db_connection_pool_idle", "Number of idle database connections");
670
- var dbConnectionPoolMax = createGauge("mtaap_db_connection_pool_max", "Maximum number of database connections");
671
- var dbQueryDuration = createHistogram("mtaap_db_query_duration_seconds", "Database query duration in seconds");
672
- var dbSlowQueriesTotal = createCounter("mtaap_db_slow_queries_total", "Total number of slow database queries (>1s)");
673
- var dbErrorsTotal = createCounter("mtaap_db_errors_total", "Total number of database errors");
674
- var tasksCreatedTotal = createCounter("mtaap_tasks_created_total", "Total number of tasks created");
675
- var tasksAssignedTotal = createCounter("mtaap_tasks_assigned_total", "Total number of tasks assigned");
676
- var tasksCompletedTotal = createCounter("mtaap_tasks_completed_total", "Total number of tasks completed");
677
- var tasksByState = createGauge("mtaap_tasks_by_state", "Number of tasks by state");
678
-
679
- // ../../packages/core/dist/logging/performance-monitor.js
680
- var MAX_SAMPLES = 1e3;
681
- var ALERT_COOLDOWN_MS = 5 * 60 * 1e3;
682
- var DEFAULT_THRESHOLDS = {
683
- api: {
684
- p50: 100,
685
- p95: 500,
686
- p99: 1e3
687
- },
688
- db: {
689
- p95: 100,
690
- p99: 500
691
- },
692
- webvitals: {
693
- FCP: 2e3,
694
- LCP: 2500,
695
- FID: 100,
696
- CLS: 0.1
697
- }
698
- };
699
- function cloneThresholds() {
700
- return Object.fromEntries(Object.entries(DEFAULT_THRESHOLDS).map(([category, metrics2]) => [
701
- category,
702
- { ...metrics2 }
703
- ]));
704
- }
705
- function labelsToKey2(labels) {
706
- if (!labels || Object.keys(labels).length === 0)
707
- return "";
708
- return Object.entries(labels).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}="${value}"`).join(",");
709
- }
710
- function percentile(sortedValues, percentileValue) {
711
- if (sortedValues.length === 0)
712
- return 0;
713
- const rank = Math.ceil(percentileValue / 100 * sortedValues.length);
714
- const index = Math.min(Math.max(rank - 1, 0), sortedValues.length - 1);
715
- return sortedValues[index];
716
- }
717
- var CircularBuffer = class {
718
- capacity;
719
- values = [];
720
- index = 0;
721
- size = 0;
722
- constructor(capacity) {
723
- this.capacity = capacity;
724
- }
725
- add(value) {
726
- if (this.size < this.capacity) {
727
- this.values.push(value);
728
- this.size += 1;
729
- this.index = this.size % this.capacity;
730
- return;
731
- }
732
- this.values[this.index] = value;
733
- this.index = (this.index + 1) % this.capacity;
734
- }
735
- getValues() {
736
- if (this.size < this.capacity) {
737
- return this.values.slice(0, this.size);
738
- }
739
- return this.values.slice();
740
- }
741
- };
742
- var PerformanceMonitor = class {
743
- samples = /* @__PURE__ */ new Map();
744
- thresholds = cloneThresholds();
745
- alertCallback;
746
- lastAlertTimestamps = /* @__PURE__ */ new Map();
747
- recordTiming(category, name, durationMs, labels) {
748
- if (!Number.isFinite(durationMs))
749
- return;
750
- const categoryMap = this.getCategoryMap(category);
751
- const nameMap = this.getNameMap(categoryMap, name);
752
- const labelKey = labelsToKey2(labels);
753
- const buffer = nameMap.get(labelKey) ?? new CircularBuffer(MAX_SAMPLES);
754
- buffer.add(durationMs);
755
- nameMap.set(labelKey, buffer);
756
- }
757
- getPercentiles(category, name) {
758
- const samples = this.collectSamples(category, name);
759
- if (samples.length === 0) {
760
- return { p50: 0, p95: 0, p99: 0 };
761
- }
762
- const sorted = [...samples].sort((a, b) => a - b);
763
- return {
764
- p50: percentile(sorted, 50),
765
- p95: percentile(sorted, 95),
766
- p99: percentile(sorted, 99)
767
- };
768
- }
769
- checkThresholds() {
770
- const alerts = [];
771
- const now = Date.now();
772
- const callbackAlerts = [];
773
- for (const [category, nameMap] of this.samples) {
774
- const thresholds = this.thresholds[category];
775
- if (!thresholds)
776
- continue;
777
- for (const name of nameMap.keys()) {
778
- const percentiles = this.getPercentiles(category, name);
779
- for (const [metric, threshold] of Object.entries(thresholds)) {
780
- const value = this.resolveMetricValue(metric, name, percentiles);
781
- if (value === void 0 || value <= threshold)
782
- continue;
783
- const alert = {
784
- category,
785
- name,
786
- metric,
787
- value,
788
- threshold
789
- };
790
- alerts.push(alert);
791
- const alertKey = `${category}|${name}|${metric}`;
792
- const lastAlertTime = this.lastAlertTimestamps.get(alertKey);
793
- if (!lastAlertTime || now - lastAlertTime >= ALERT_COOLDOWN_MS) {
794
- this.lastAlertTimestamps.set(alertKey, now);
795
- callbackAlerts.push(alert);
796
- }
797
- }
798
- }
799
- }
800
- if (callbackAlerts.length > 0 && this.alertCallback) {
801
- this.alertCallback(callbackAlerts);
802
- }
803
- return alerts;
804
- }
805
- setAlertCallback(callback) {
806
- this.alertCallback = callback;
807
- }
808
- setThreshold(category, metric, value) {
809
- if (!this.thresholds[category]) {
810
- this.thresholds[category] = {};
811
- }
812
- this.thresholds[category][metric] = value;
813
- }
814
- collectSamples(category, name) {
815
- const categoryMap = this.samples.get(category);
816
- if (!categoryMap)
817
- return [];
818
- const entries = name ? [[name, categoryMap.get(name)]] : Array.from(categoryMap.entries());
819
- const samples = [];
820
- for (const [, labelMap] of entries) {
821
- if (!labelMap)
822
- continue;
823
- for (const buffer of labelMap.values()) {
824
- samples.push(...buffer.getValues());
825
- }
826
- }
827
- return samples;
828
- }
829
- resolveMetricValue(metric, name, percentiles) {
830
- if (metric === "p50")
831
- return percentiles.p50;
832
- if (metric === "p95")
833
- return percentiles.p95;
834
- if (metric === "p99")
835
- return percentiles.p99;
836
- if (metric === name)
837
- return percentiles.p95;
838
- return void 0;
839
- }
840
- getCategoryMap(category) {
841
- const existing = this.samples.get(category);
842
- if (existing)
843
- return existing;
844
- const created = /* @__PURE__ */ new Map();
845
- this.samples.set(category, created);
846
- return created;
847
- }
848
- getNameMap(categoryMap, name) {
849
- const existing = categoryMap.get(name);
850
- if (existing)
851
- return existing;
852
- const created = /* @__PURE__ */ new Map();
853
- categoryMap.set(name, created);
854
- return created;
855
- }
856
- };
857
- var defaultMonitor = new PerformanceMonitor();
858
- function recordTiming(category, name, durationMs, labels) {
859
- defaultMonitor.recordTiming(category, name, durationMs, labels);
860
- }
861
-
862
- // ../../packages/core/dist/logging/error-tracker.js
863
- var NoOpErrorTracker = class {
864
- captureError(error, context) {
865
- console.error("Error captured:", error.message, context);
866
- }
867
- captureException(error, context) {
868
- console.error("Exception captured:", error, context);
869
- }
870
- captureMessage(message, level, context) {
871
- console[level === "warning" ? "warn" : level](`Message captured [${level}]:`, message, context);
872
- }
873
- setUser(user) {
874
- console.log("User set:", user);
875
- }
876
- clearUser() {
877
- console.log("User cleared");
878
- }
879
- };
880
- var errorTrackerInstance = new NoOpErrorTracker();
881
-
882
- // ../../packages/db/dist/index.js
883
- __reExport(dist_exports, client_star2);
884
- import * as client_star2 from "@prisma/client";
885
- var prisma2 = client_default.$extends({
886
- query: {
887
- async $allOperations({ args, model, operation, query }) {
888
- const start = Date.now();
889
- try {
890
- return await query(args);
891
- } finally {
892
- const durationMs = Date.now() - start;
893
- const modelLabel = model ?? "raw";
894
- recordTiming("db", operation, durationMs, { model: modelLabel });
895
- dbQueryDuration.observe({ operation }, durationMs / 1e3);
896
- if (durationMs > 1e3) {
897
- dbSlowQueriesTotal.inc({ operation });
898
- }
899
- }
900
- }
901
- }
902
- });
903
-
904
- // ../../packages/auth/dist/api-key.js
905
- var API_KEY_PERMISSION_RANK = {
906
- [ApiKeyPermission.READ]: 1,
907
- [ApiKeyPermission.WRITE]: 2,
908
- [ApiKeyPermission.ADMIN]: 3
909
- };
910
- async function hashApiKey(apiKey) {
911
- const crypto = await import("crypto");
912
- return crypto.createHash("sha256").update(apiKey).digest("hex");
913
- }
914
- async function validateApiKey(apiKey) {
915
- const keyHash = await hashApiKey(apiKey);
916
- const keyRecord = await prisma2.apiKey.findFirst({
917
- where: {
918
- keyHash,
919
- revoked: false
920
- },
921
- include: {
922
- user: {
923
- include: {
924
- organizations: {
925
- take: 1,
926
- include: {
927
- organization: true
928
- }
929
- }
930
- }
931
- }
932
- }
933
- });
934
- if (!keyRecord || keyRecord.expiresAt && keyRecord.expiresAt < /* @__PURE__ */ new Date()) {
935
- return null;
936
- }
937
- await prisma2.apiKey.update({
938
- where: { id: keyRecord.id },
939
- data: { lastUsedAt: /* @__PURE__ */ new Date() }
940
- });
941
- const orgUser = keyRecord.user.organizations?.[0];
942
- return {
943
- user: keyRecord.user,
944
- organization: orgUser?.organization,
945
- apiKey: {
946
- id: keyRecord.id,
947
- name: keyRecord.name,
948
- // Cast Prisma enum to @mtaap/core enum (same values, different types)
949
- permissions: keyRecord.permissions,
950
- expiresAt: keyRecord.expiresAt,
951
- lastUsedAt: keyRecord.lastUsedAt
952
- }
953
- };
954
- }
955
-
956
- // src/version.ts
957
- var VERSION2 = "0.1.3";
958
-
959
- // ../../packages/git/dist/github.js
960
- import { Octokit } from "octokit";
961
- var GitHubProvider = class {
962
- octokit;
963
- constructor(token) {
964
- this.octokit = new Octokit({ auth: token });
965
- }
966
- async createBranch(options) {
967
- try {
968
- const { data: ref } = await this.octokit.rest.git.getRef({
969
- owner: options.owner,
970
- repo: options.repo,
971
- ref: `heads/${options.sourceBranch}`
972
- });
973
- await this.octokit.rest.git.createRef({
974
- owner: options.owner,
975
- repo: options.repo,
976
- ref: `refs/heads/${options.newBranch}`,
977
- sha: ref.object.sha
978
- });
979
- return {
980
- success: true,
981
- branchName: options.newBranch
982
- };
983
- } catch (error) {
984
- return {
985
- success: false,
986
- branchName: options.newBranch,
987
- error: error.message || "Failed to create branch"
988
- };
989
- }
990
- }
991
- async createPR(options) {
992
- try {
993
- const { data: pr } = await this.octokit.rest.pulls.create({
994
- owner: options.owner,
995
- repo: options.repo,
996
- title: options.title,
997
- body: options.body,
998
- head: options.head,
999
- base: options.base
1000
- });
1001
- return {
1002
- success: true,
1003
- prUrl: pr.html_url,
1004
- prNumber: pr.number
1005
- };
1006
- } catch (error) {
1007
- return {
1008
- success: false,
1009
- prUrl: "",
1010
- prNumber: 0,
1011
- error: error.message || "Failed to create pull request"
1012
- };
1013
- }
1014
- }
1015
- async getBranchInfo(options) {
1016
- try {
1017
- const { data: ref } = await this.octokit.rest.git.getRef({
1018
- owner: options.owner,
1019
- repo: options.repo,
1020
- ref: `heads/${options.branch}`
1021
- });
1022
- return ref.object.sha;
1023
- } catch {
1024
- return null;
1025
- }
1026
- }
1027
- async listBranches(owner, repo) {
1028
- try {
1029
- const { data: branches } = await this.octokit.rest.repos.listBranches({
1030
- owner,
1031
- repo,
1032
- per_page: 100
1033
- });
1034
- return branches.map((branch) => ({
1035
- name: branch.name,
1036
- commitSha: branch.commit.sha,
1037
- protected: branch.protected
1038
- }));
1039
- } catch (error) {
1040
- console.error("Failed to list branches:", error);
1041
- return [];
1042
- }
1043
- }
1044
- async setupWebhook(options) {
1045
- try {
1046
- const { data: webhook } = await this.octokit.rest.repos.createWebhook({
1047
- owner: options.owner,
1048
- repo: options.repo,
1049
- name: "web",
1050
- config: {
1051
- url: options.url,
1052
- content_type: "json",
1053
- secret: options.secret
1054
- },
1055
- events: options.events || ["push", "pull_request"],
1056
- active: true
1057
- });
1058
- return {
1059
- success: true,
1060
- webhookId: webhook.id
1061
- };
1062
- } catch (error) {
1063
- return {
1064
- success: false,
1065
- webhookId: 0,
1066
- error: error.message || "Failed to setup webhook"
1067
- };
1068
- }
1069
- }
1070
- async getPRInfo(prNumber, owner, repo) {
1071
- try {
1072
- const { data: pr } = await this.octokit.rest.pulls.get({
1073
- owner,
1074
- repo,
1075
- pull_number: prNumber
1076
- });
1077
- return {
1078
- number: pr.number,
1079
- title: pr.title,
1080
- state: pr.state,
1081
- htmlUrl: pr.html_url,
1082
- mergedAt: pr.merged_at ? new Date(pr.merged_at) : void 0,
1083
- user: pr.user ? {
1084
- login: pr.user.login
1085
- } : void 0
1086
- };
1087
- } catch {
1088
- return null;
1089
- }
1090
- }
1091
- async getRecentCommits(owner, repo, branch, limit = 10) {
1092
- try {
1093
- const { data: commits } = await this.octokit.rest.repos.listCommits({
1094
- owner,
1095
- repo,
1096
- sha: branch,
1097
- per_page: limit
1098
- });
1099
- return commits.map((commit) => ({
1100
- sha: commit.sha,
1101
- message: commit.commit.message,
1102
- author: commit.commit.author?.name && commit.commit.author?.email ? {
1103
- name: commit.commit.author.name,
1104
- email: commit.commit.author.email
1105
- } : void 0,
1106
- date: new Date(commit.commit.author?.date || Date.now())
1107
- }));
1108
- } catch {
1109
- return [];
1110
- }
1111
- }
1112
- async deleteBranch(owner, repo, branch) {
1113
- try {
1114
- await this.octokit.rest.git.deleteRef({
1115
- owner,
1116
- repo,
1117
- ref: `heads/${branch}`
1118
- });
1119
- return true;
1120
- } catch (error) {
1121
- console.error(`Failed to delete branch ${branch}:`, error.message);
1122
- return false;
1123
- }
1124
- }
1125
- async getRepositoryReadme(owner, repo) {
1126
- try {
1127
- const { data } = await this.octokit.rest.repos.getReadme({
1128
- owner,
1129
- repo,
1130
- mediaType: {
1131
- format: "raw"
1132
- }
1133
- });
1134
- return data;
1135
- } catch {
1136
- return null;
1137
- }
1138
- }
1139
- async getRepositoryPackageJson(owner, repo) {
1140
- try {
1141
- const { data } = await this.octokit.rest.repos.getContent({
1142
- owner,
1143
- repo,
1144
- path: "package.json"
1145
- });
1146
- if ("content" in data && data.type === "file") {
1147
- return Buffer.from(data.content, "base64").toString("utf-8");
1148
- }
1149
- return null;
1150
- } catch {
1151
- return null;
1152
- }
1153
- }
1154
- static parseRepositoryUrl(url) {
1155
- try {
1156
- const match = url.match(/github\.com[/:]([^/]+)\/([^/.]+)/);
1157
- if (!match || match.length < 3) {
1158
- return null;
1159
- }
1160
- return {
1161
- owner: match[1],
1162
- repo: match[2].replace(/\.git$/, "")
1163
- };
1164
- } catch {
1165
- return null;
1166
- }
1167
- }
1168
- static async verifyWebhookSignature(payload, signature, secret) {
1169
- const crypto = await import("crypto");
1170
- const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
1171
- const parts = signature.split("=");
1172
- if (parts.length < 2) {
1173
- return false;
1174
- }
1175
- const receivedSignature = parts[1];
1176
- return crypto.timingSafeEqual(Buffer.from(receivedSignature), Buffer.from(expectedSignature));
1177
- }
1178
- async verifyRepositoryAccess(owner, repo) {
1179
- try {
1180
- await this.octokit.rest.repos.get({
1181
- owner,
1182
- repo
1183
- });
1184
- return { success: true };
1185
- } catch (error) {
1186
- if (error.status === 404) {
1187
- return {
1188
- success: false,
1189
- error: "Repository not found or you don't have access"
1190
- };
1191
- }
1192
- if (error.status === 401 || error.status === 403) {
1193
- return {
1194
- success: false,
1195
- error: "Authentication failed. Check your GitHub token permissions"
1196
- };
1197
- }
1198
- return {
1199
- success: false,
1200
- error: error.message || "Failed to verify repository access"
1201
- };
1202
- }
1203
- }
1204
- };
1205
-
1206
- // ../../packages/git/dist/errors.js
1207
- var GitErrorType;
1208
- (function(GitErrorType2) {
1209
- GitErrorType2["BRANCH_NOT_FOUND"] = "BRANCH_NOT_FOUND";
1210
- GitErrorType2["BRANCH_EXISTS"] = "BRANCH_EXISTS";
1211
- GitErrorType2["AUTH_INVALID"] = "AUTH_INVALID";
1212
- GitErrorType2["REPOSITORY_NOT_FOUND"] = "REPOSITORY_NOT_FOUND";
1213
- GitErrorType2["RATE_LIMITED"] = "RATE_LIMITED";
1214
- GitErrorType2["NETWORK_ERROR"] = "NETWORK_ERROR";
1215
- GitErrorType2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
1216
- GitErrorType2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
1217
- })(GitErrorType || (GitErrorType = {}));
1218
-
1219
- // src/permissions.ts
1220
- var PERMISSION_RANK = {
1221
- READ: 1,
1222
- WRITE: 2,
1223
- ADMIN: 3
1224
- };
1225
- function assertApiKeyPermission(apiKey, required, toolName) {
1226
- const actualRank = PERMISSION_RANK[apiKey.permissions] ?? 0;
1227
- const requiredRank = PERMISSION_RANK[required] ?? 0;
1228
- if (actualRank >= requiredRank) {
1229
- return;
1230
- }
1231
- console.warn("API key permission violation", {
1232
- keyId: apiKey.id,
1233
- requiredPermission: required,
1234
- actualPermission: apiKey.permissions,
1235
- tool: toolName
1236
- });
1237
- const error = new Error(
1238
- `API key lacks required permissions (required: ${required})`
1239
- );
1240
- error.status = 403;
1241
- throw error;
1242
- }
1243
-
1244
- // src/index.ts
1245
- async function getAuthenticatedUser(apiKey) {
1246
- const result = await validateApiKey(apiKey);
1247
- if (!result) {
1248
- throw new Error("Invalid API key");
1249
- }
1250
- return {
1251
- userId: result.user.id,
1252
- organizationId: result.organization?.id,
1253
- apiKey: result.apiKey
1254
- };
1255
- }
1256
- async function ensureAccessControl(projectId, userId, organizationId) {
1257
- if (!organizationId) {
1258
- const project = await prisma2.project.findUnique({
1259
- where: { id: projectId },
1260
- include: { owner: true }
1261
- });
1262
- if (project?.ownerId !== userId) {
1263
- throw new Error(
1264
- "Access denied: You do not have permission to access this project"
1265
- );
1266
- }
1267
- } else {
1268
- const project = await prisma2.project.findUnique({
1269
- where: { id: projectId },
1270
- include: { organization: true }
1271
- });
1272
- if (!project || project.organizationId !== organizationId) {
1273
- throw new Error(
1274
- "Access denied: You do not have permission to access this project"
1275
- );
1276
- }
1277
- const userTags = await prisma2.userTag.findMany({
1278
- where: { userId },
1279
- include: { tag: true }
1280
- });
1281
- const projectTags = await prisma2.projectTag.findMany({
1282
- where: { projectId },
1283
- include: { tag: true }
1284
- });
1285
- const userTagNames = new Set(
1286
- userTags.map((ut) => ut.tag.name)
1287
- );
1288
- const projectTagNames = new Set(
1289
- projectTags.map((pt) => pt.tag.name)
1290
- );
1291
- const hasAccess = [...userTagNames].some((tag) => projectTagNames.has(tag));
1292
- if (!hasAccess) {
1293
- throw new Error(
1294
- "Access denied: Your tags do not grant access to this project"
1295
- );
1296
- }
1297
- }
1298
- }
1299
- function getGitHubClient(_organizationId) {
1300
- const githubToken = process.env.GITHUB_TOKEN;
1301
- if (!githubToken) {
1302
- throw new Error("GitHub token not configured");
1303
- }
1304
- return new GitHubProvider(githubToken);
1305
- }
1306
- function slugify(text, maxLength = 50) {
1307
- return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").substring(0, maxLength);
1308
- }
1309
- async function createMCPServer() {
1310
- const server = new McpServer({
1311
- name: "mtaap",
1312
- version: VERSION2
1313
- });
1314
- const apiKey = process.env.MTAAP_API_KEY;
1315
- if (!apiKey) {
1316
- throw new Error("MTAAP_API_KEY environment variable is required");
1317
- }
1318
- const auth = await getAuthenticatedUser(apiKey);
1319
- server.registerTool(
1320
- "list_projects",
1321
- {
1322
- description: "List accessible projects (personal + team via tags)"
1323
- },
1324
- async (args) => {
1325
- assertApiKeyPermission(
1326
- auth.apiKey,
1327
- ApiKeyPermission.READ,
1328
- "list_projects"
1329
- );
1330
- const validated = ListProjectsInputSchema.parse(args);
1331
- const projects = await listProjects(
1332
- auth.userId,
1333
- auth.organizationId,
1334
- validated.workspaceType
1335
- );
1336
- return {
1337
- content: [
1338
- {
1339
- type: "text",
1340
- text: JSON.stringify(projects, null, 2)
1341
- }
1342
- ]
1343
- };
1344
- }
1345
- );
1346
- server.registerTool(
1347
- "list_tasks",
1348
- {
1349
- description: "Returns available tasks (filterable by project, state)"
1350
- },
1351
- async (args) => {
1352
- assertApiKeyPermission(auth.apiKey, ApiKeyPermission.READ, "list_tasks");
1353
- const validated = ListTasksInputSchema.parse(args);
1354
- if (validated.projectId) {
1355
- await ensureAccessControl(
1356
- validated.projectId,
1357
- auth.userId,
1358
- auth.organizationId
1359
- );
1360
- }
1361
- const tasks = await listTasks(
1362
- auth.userId,
1363
- auth.organizationId,
1364
- validated.projectId,
1365
- validated.state,
1366
- validated.assigneeId
1367
- );
1368
- return {
1369
- content: [
1370
- {
1371
- type: "text",
1372
- text: JSON.stringify(tasks, null, 2)
1373
- }
1374
- ]
1375
- };
1376
- }
1377
- );
1378
- server.registerTool(
1379
- "get_task",
1380
- {
1381
- description: "Full task details including acceptance criteria"
1382
- },
1383
- async (args) => {
1384
- assertApiKeyPermission(auth.apiKey, ApiKeyPermission.READ, "get_task");
1385
- const validated = GetTaskInputSchema.parse(args);
1386
- const task = await getTaskWithChecks(
1387
- validated.taskId,
1388
- auth.userId,
1389
- auth.organizationId
1390
- );
1391
- return {
1392
- content: [
1393
- {
1394
- type: "text",
1395
- text: JSON.stringify(task, null, 2)
1396
- }
1397
- ]
1398
- };
1399
- }
1400
- );
1401
- server.registerTool(
1402
- "assign_task",
1403
- {
1404
- description: "Atomic claim \u2192 creates branch. Fails if already taken."
1405
- },
1406
- async (args) => {
1407
- assertApiKeyPermission(
1408
- auth.apiKey,
1409
- ApiKeyPermission.WRITE,
1410
- "assign_task"
1411
- );
1412
- const validated = AssignTaskInputSchema.parse(args);
1413
- const result = await assignTask(
1414
- validated.projectId,
1415
- validated.taskId,
1416
- auth.userId,
1417
- auth.organizationId,
1418
- validated.expectedState
1419
- );
1420
- return {
1421
- content: [
1422
- {
1423
- type: "text",
1424
- text: JSON.stringify(result, null, 2)
1425
- }
1426
- ]
1427
- };
1428
- }
1429
- );
1430
- server.registerTool(
1431
- "update_progress",
1432
- {
1433
- description: "Reports status, updates checkboxes, writes checkpoint"
1434
- },
1435
- async (args) => {
1436
- assertApiKeyPermission(
1437
- auth.apiKey,
1438
- ApiKeyPermission.WRITE,
1439
- "update_progress"
1440
- );
1441
- const validated = UpdateProgressInputSchema.parse(args);
1442
- const result = await updateProgress(
1443
- validated.taskId,
1444
- auth.userId,
1445
- validated.statusMessage,
1446
- validated.completedCheckpointIds,
1447
- validated.currentCheckpointIndex
1448
- );
1449
- return {
1450
- content: [
1451
- {
1452
- type: "text",
1453
- text: JSON.stringify(result, null, 2)
1454
- }
1455
- ]
1456
- };
1457
- }
1458
- );
1459
- server.registerTool(
1460
- "complete_task",
1461
- {
1462
- description: "Marks complete, triggers PR, deletes local state file"
1463
- },
1464
- async (args) => {
1465
- assertApiKeyPermission(
1466
- auth.apiKey,
1467
- ApiKeyPermission.WRITE,
1468
- "complete_task"
1469
- );
1470
- const validated = CompleteTaskInputSchema.parse(args);
1471
- const result = await completeTask(
1472
- validated.projectId,
1473
- validated.taskId,
1474
- auth.userId,
1475
- auth.organizationId,
1476
- validated.pullRequestTitle,
1477
- validated.pullRequestBody
1478
- );
1479
- return {
1480
- content: [
1481
- {
1482
- type: "text",
1483
- text: JSON.stringify(result, null, 2)
1484
- }
1485
- ]
1486
- };
1487
- }
1488
- );
1489
- server.registerTool(
1490
- "check_active_task",
1491
- {
1492
- description: "Check for resumable task in .mtaap/active-task.json"
1493
- },
1494
- async () => {
1495
- assertApiKeyPermission(
1496
- auth.apiKey,
1497
- ApiKeyPermission.READ,
1498
- "check_active_task"
1499
- );
1500
- const result = await checkActiveTask();
1501
- return {
1502
- content: [
1503
- {
1504
- type: "text",
1505
- text: JSON.stringify(result, null, 2)
1506
- }
1507
- ]
1508
- };
1509
- }
1510
- );
1511
- server.registerTool(
1512
- "report_error",
1513
- {
1514
- description: "Report unrecoverable error, displays on task in webapp"
1515
- },
1516
- async (args) => {
1517
- assertApiKeyPermission(
1518
- auth.apiKey,
1519
- ApiKeyPermission.WRITE,
1520
- "report_error"
1521
- );
1522
- const validated = ReportErrorInputSchema.parse(args);
1523
- const result = await reportTaskError(
1524
- validated.taskId,
1525
- auth.userId,
1526
- validated.errorType,
1527
- validated.errorMessage,
1528
- validated.context
1529
- );
1530
- return {
1531
- content: [
1532
- {
1533
- type: "text",
1534
- text: JSON.stringify(result, null, 2)
1535
- }
1536
- ]
1537
- };
1538
- }
1539
- );
1540
- server.registerTool(
1541
- "get_project_context",
1542
- {
1543
- description: "Returns assembled context (README, stack, conventions)"
1544
- },
1545
- async (args) => {
1546
- assertApiKeyPermission(
1547
- auth.apiKey,
1548
- ApiKeyPermission.READ,
1549
- "get_project_context"
1550
- );
1551
- const validated = GetProjectContextInputSchema.parse(args);
1552
- await ensureAccessControl(
1553
- validated.projectId,
1554
- auth.userId,
1555
- auth.organizationId
1556
- );
1557
- const context = await getProjectContext(validated.projectId);
1558
- return {
1559
- content: [
1560
- {
1561
- type: "text",
1562
- text: JSON.stringify(context, null, 2)
1563
- }
1564
- ]
1565
- };
1566
- }
1567
- );
1568
- server.registerTool(
1569
- "add_note",
1570
- {
1571
- description: "Append implementation notes to task"
1572
- },
1573
- async (args) => {
1574
- assertApiKeyPermission(auth.apiKey, ApiKeyPermission.WRITE, "add_note");
1575
- const validated = AddNoteInputSchema.parse(args);
1576
- const result = await addTaskNote(
1577
- validated.taskId,
1578
- auth.userId,
1579
- validated.content
1580
- );
1581
- return {
1582
- content: [
1583
- {
1584
- type: "text",
1585
- text: JSON.stringify(result, null, 2)
1586
- }
1587
- ]
1588
- };
1589
- }
1590
- );
1591
- server.registerTool(
1592
- "abandon_task",
1593
- {
1594
- description: "Unassign from a task and optionally delete the branch"
1595
- },
1596
- async (args) => {
1597
- assertApiKeyPermission(
1598
- auth.apiKey,
1599
- ApiKeyPermission.WRITE,
1600
- "abandon_task"
1601
- );
1602
- const validated = AbandonTaskInputSchema.parse(args);
1603
- await ensureAccessControl(
1604
- validated.projectId,
1605
- auth.userId,
1606
- auth.organizationId || null
1607
- );
1608
- const result = await abandonTask(
1609
- validated.taskId,
1610
- validated.projectId,
1611
- auth.userId,
1612
- validated.deleteBranch
1613
- );
1614
- return {
1615
- content: [
1616
- {
1617
- type: "text",
1618
- text: JSON.stringify(result, null, 2)
1619
- }
1620
- ]
1621
- };
1622
- }
1623
- );
1624
- server.registerTool(
1625
- "create_personal_project",
1626
- {
1627
- description: "Create project in user's personal workspace"
1628
- },
1629
- async (args) => {
1630
- assertApiKeyPermission(
1631
- auth.apiKey,
1632
- ApiKeyPermission.WRITE,
1633
- "create_personal_project"
1634
- );
1635
- const validated = CreatePersonalProjectInputSchema.parse(args);
1636
- const result = await createPersonalProject(
1637
- auth.userId,
1638
- validated.name,
1639
- validated.description,
1640
- validated.repositoryUrl
1641
- );
1642
- return {
1643
- content: [
1644
- {
1645
- type: "text",
1646
- text: JSON.stringify(result, null, 2)
1647
- }
1648
- ]
1649
- };
1650
- }
1651
- );
1652
- server.registerTool(
1653
- "get_version",
1654
- {
1655
- description: "Get the current MTAAP version"
1656
- },
1657
- async () => {
1658
- assertApiKeyPermission(auth.apiKey, ApiKeyPermission.READ, "get_version");
1659
- return {
1660
- content: [
1661
- {
1662
- type: "text",
1663
- text: JSON.stringify(
1664
- {
1665
- version: VERSION2,
1666
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1667
- },
1668
- null,
1669
- 2
1670
- )
1671
- }
1672
- ]
1673
- };
1674
- }
1675
- );
1676
- const transport = new StdioServerTransport();
1677
- await server.connect(transport);
1678
- }
1679
- async function listProjects(userId, organizationId, workspaceType = "ALL") {
1680
- const where = {};
1681
- const include = {};
1682
- if (workspaceType === "PERSONAL" || workspaceType === "ALL") {
1683
- where.ownerId = userId;
1684
- include.owner = true;
1685
- }
1686
- if (organizationId && (workspaceType === "TEAM" || workspaceType === "ALL")) {
1687
- where.OR = [
1688
- { organizationId },
1689
- { type: ProjectType.PERSONAL, ownerId: userId }
1690
- ];
1691
- include.organization = true;
1692
- include.projectTags = {
1693
- include: { tag: true }
1694
- };
1695
- }
1696
- const projects = await prisma2.project.findMany({
1697
- where,
1698
- include,
1699
- orderBy: { updatedAt: "desc" }
1700
- });
1701
- const formattedProjects = projects.map(
1702
- (project) => ({
1703
- id: project.id,
1704
- name: project.name,
1705
- description: project.description,
1706
- type: project.type,
1707
- origin: project.origin,
1708
- repositoryUrl: project.repositoryUrl,
1709
- baseBranch: project.baseBranch,
1710
- tags: project.projectTags?.map((pt) => pt.tag.name) || [],
1711
- createdAt: project.createdAt,
1712
- updatedAt: project.updatedAt
1713
- })
1714
- );
1715
- return formattedProjects;
1716
- }
1717
- async function listTasks(userId, organizationId, projectId, state, assigneeId) {
1718
- const where = { projectId };
1719
- if (organizationId) {
1720
- where.project = {
1721
- organizationId
1722
- };
1723
- }
1724
- if (state) {
1725
- where.state = state;
1726
- }
1727
- if (assigneeId) {
1728
- where.assigneeId = assigneeId;
1729
- }
1730
- const tasks = await prisma2.task.findMany({
1731
- where,
1732
- include: {
1733
- project: true,
1734
- assignee: true,
1735
- creator: true,
1736
- epic: true
1737
- },
1738
- orderBy: { createdAt: "desc" }
1739
- });
1740
- const formattedTasks = await Promise.all(
1741
- tasks.map(async (task) => {
1742
- const acceptanceCriteria = await prisma2.acceptanceCriterion.findMany({
1743
- where: { taskId: task.id },
1744
- orderBy: { order: "asc" }
1745
- });
1746
- return {
1747
- id: task.id,
1748
- projectId: task.projectId,
1749
- projectName: task.project?.name || "Unknown",
1750
- epicId: task.epicId,
1751
- epicName: task.epic?.name || null,
1752
- title: task.title,
1753
- description: task.description,
1754
- state: task.state,
1755
- priority: task.priority,
1756
- assigneeId: task.assigneeId,
1757
- assigneeName: task.assignee?.name || null,
1758
- assigneeEmail: task.assignee?.email || null,
1759
- createdBy: task.createdBy,
1760
- createdByName: task.creator?.name || null,
1761
- assignedAt: task.assignedAt,
1762
- startedAt: task.startedAt,
1763
- completedAt: task.completedAt,
1764
- branchName: task.branchName,
1765
- pullRequestUrl: task.pullRequestUrl,
1766
- pullRequestNumber: task.pullRequestNumber,
1767
- errorType: task.errorType,
1768
- errorMessage: task.errorMessage,
1769
- acceptanceCriteria: acceptanceCriteria.map((ac) => ({
1770
- id: ac.id,
1771
- description: ac.description,
1772
- completed: ac.completed,
1773
- completedAt: ac.completedAt,
1774
- order: ac.order
1775
- })),
1776
- createdAt: task.createdAt,
1777
- updatedAt: task.updatedAt
1778
- };
1779
- })
1780
- );
1781
- return formattedTasks;
1782
- }
1783
- async function getTaskWithChecks(taskId, userId, organizationId) {
1784
- const task = await prisma2.task.findUnique({
1785
- where: { id: taskId },
1786
- include: {
1787
- project: {
1788
- include: {
1789
- organization: true,
1790
- projectTags: {
1791
- include: { tag: true }
1792
- }
1793
- }
1794
- },
1795
- epic: true,
1796
- assignee: true,
1797
- creator: true,
1798
- acceptanceCriteria: {
1799
- orderBy: { order: "asc" }
1800
- },
1801
- progressUpdates: {
1802
- orderBy: { createdAt: "desc" },
1803
- take: 10
1804
- },
1805
- notes: {
1806
- orderBy: { createdAt: "desc" },
1807
- take: 10
1808
- }
1809
- }
1810
- });
1811
- if (!task) {
1812
- throw new Error("Task not found");
1813
- }
1814
- if (organizationId && task.project?.organizationId !== organizationId) {
1815
- const userTags = await prisma2.userTag.findMany({
1816
- where: { userId },
1817
- include: { tag: true }
1818
- });
1819
- const projectTagNames = new Set(
1820
- task.project.projectTags?.map(
1821
- (pt) => pt.tag.name
1822
- ) || []
1823
- );
1824
- const userTagNames = new Set(
1825
- userTags.map((ut) => ut.tag.name)
1826
- );
1827
- const hasAccess = [...userTagNames].some((tag) => projectTagNames.has(tag));
1828
- if (!hasAccess) {
1829
- throw new Error(
1830
- "Access denied: Your tags do not grant access to this project"
1831
- );
1832
- }
1833
- }
1834
- const formattedTask = {
1835
- id: task.id,
1836
- projectId: task.projectId,
1837
- projectName: task.project?.name || "Unknown",
1838
- epicId: task.epicId,
1839
- epicName: task.epic?.name || null,
1840
- title: task.title,
1841
- description: task.description,
1842
- state: task.state,
1843
- priority: task.priority,
1844
- assigneeId: task.assigneeId,
1845
- assigneeName: task.assignee?.name || null,
1846
- assigneeEmail: task.assignee?.email || null,
1847
- createdBy: task.createdBy,
1848
- createdByName: task.creator?.name || null,
1849
- assignedAt: task.assignedAt,
1850
- startedAt: task.startedAt,
1851
- completedAt: task.completedAt,
1852
- branchName: task.branchName,
1853
- pullRequestUrl: task.pullRequestUrl,
1854
- pullRequestNumber: task.pullRequestNumber,
1855
- errorType: task.errorType,
1856
- errorMessage: task.errorMessage,
1857
- acceptanceCriteria: task.acceptanceCriteria.map(
1858
- (ac) => ({
1859
- id: ac.id,
1860
- description: ac.description,
1861
- completed: ac.completed,
1862
- completedAt: ac.completedAt,
1863
- order: ac.order
1864
- })
1865
- ),
1866
- progressUpdates: task.progressUpdates.map(
1867
- (pu) => ({
1868
- id: pu.id,
1869
- message: pu.message,
1870
- checkpoints: pu.checkpoints,
1871
- userId: pu.userId,
1872
- createdAt: pu.createdAt
1873
- })
1874
- ),
1875
- notes: task.notes.map((note) => ({
1876
- id: note.id,
1877
- content: note.content,
1878
- userId: note.userId,
1879
- createdAt: note.createdAt
1880
- })),
1881
- createdAt: task.createdAt,
1882
- updatedAt: task.updatedAt
1883
- };
1884
- return formattedTask;
1885
- }
1886
- async function assignTask(projectId, taskId, userId, organizationId, expectedState = TaskState.READY) {
1887
- await ensureAccessControl(projectId, userId, organizationId);
1888
- const task = await prisma2.task.findUnique({
1889
- where: { id: taskId },
1890
- include: { project: true }
1891
- });
1892
- if (!task) {
1893
- throw new Error("Task not found");
1894
- }
1895
- if (task.state !== expectedState) {
1896
- return {
1897
- success: false,
1898
- taskId,
1899
- currentState: task.state,
1900
- message: `Task is already in state: ${task.state}`
1901
- };
1902
- }
1903
- const repoInfo = GitHubProvider.parseRepositoryUrl(
1904
- task.project?.repositoryUrl || ""
1905
- );
1906
- if (!repoInfo) {
1907
- throw new Error("Invalid repository URL");
1908
- }
1909
- const github = getGitHubClient(task.project?.organizationId || "");
1910
- const branchSuffix = slugify(task.title);
1911
- const branchName = `feature/${taskId}-${branchSuffix}`;
1912
- const createResult = await github.createBranch({
1913
- owner: repoInfo.owner,
1914
- repo: repoInfo.repo,
1915
- sourceBranch: task.project?.baseBranch || "develop",
1916
- newBranch: branchName
1917
- });
1918
- if (!createResult.success) {
1919
- throw new Error(`Failed to create branch: ${createResult.error}`);
1920
- }
1921
- const updatedTask = await prisma2.task.update({
1922
- where: { id: taskId },
1923
- data: {
1924
- state: TaskState.IN_PROGRESS,
1925
- assigneeId: userId,
1926
- assignedAt: /* @__PURE__ */ new Date(),
1927
- branchName,
1928
- startedAt: /* @__PURE__ */ new Date()
1929
- }
1930
- });
1931
- return {
1932
- success: true,
1933
- taskId: updatedTask.id,
1934
- branchName
1935
- };
1936
- }
1937
- async function updateProgress(taskId, userId, statusMessage, completedCheckpointIds, _currentCheckpointIndex) {
1938
- const task = await prisma2.task.findUnique({
1939
- where: { id: taskId }
1940
- });
1941
- if (!task) {
1942
- throw new Error("Task not found");
1943
- }
1944
- if (task.assigneeId !== userId) {
1945
- throw new Error("You are not assigned to this task");
1946
- }
1947
- if (completedCheckpointIds && completedCheckpointIds.length > 0) {
1948
- await prisma2.acceptanceCriterion.updateMany({
1949
- where: {
1950
- id: { in: completedCheckpointIds }
1951
- },
1952
- data: {
1953
- completed: true,
1954
- completedAt: /* @__PURE__ */ new Date()
1955
- }
1956
- });
1957
- }
1958
- if (statusMessage) {
1959
- await prisma2.progressUpdate.create({
1960
- data: {
1961
- taskId,
1962
- userId,
1963
- message: statusMessage,
1964
- checkpoints: []
1965
- }
1966
- });
1967
- }
1968
- const updatedTask = await prisma2.task.update({
1969
- where: { id: taskId },
1970
- data: {
1971
- updatedAt: /* @__PURE__ */ new Date()
1972
- }
1973
- });
1974
- return {
1975
- success: true,
1976
- taskId: updatedTask.id
1977
- };
1978
- }
1979
- async function completeTask(projectId, taskId, userId, organizationId, pullRequestTitle, pullRequestBody) {
1980
- await ensureAccessControl(projectId, userId, organizationId);
1981
- const task = await prisma2.task.findUnique({
1982
- where: { id: taskId },
1983
- include: { project: true }
1984
- });
1985
- if (!task) {
1986
- throw new Error("Task not found");
1987
- }
1988
- if (task.assigneeId !== userId) {
1989
- throw new Error("You are not assigned to this task");
1990
- }
1991
- if (task.state !== TaskState.IN_PROGRESS) {
1992
- throw new Error("Task must be in progress to be completed");
1993
- }
1994
- if (!task.branchName) {
1995
- throw new Error("Task has no associated branch");
1996
- }
1997
- const repoInfo = GitHubProvider.parseRepositoryUrl(
1998
- task.project?.repositoryUrl || ""
1999
- );
2000
- if (!repoInfo) {
2001
- throw new Error("Invalid repository URL");
2002
- }
2003
- const github = getGitHubClient(task.project?.organizationId || "");
2004
- const acceptanceCriteria = await prisma2.acceptanceCriterion.findMany({
2005
- where: { taskId },
2006
- orderBy: { order: "asc" }
2007
- });
2008
- const acceptanceChecklist = acceptanceCriteria.map(
2009
- (ac) => `- [${ac.completed ? "x" : " "}] ${ac.description}`
2010
- ).join("\n");
2011
- const prTitle = pullRequestTitle || `[${taskId}] ${task.title}`;
2012
- const prBody = pullRequestBody || `${task.description}
2013
-
2014
- ### Acceptance Criteria
2015
-
2016
- ${acceptanceChecklist}`;
2017
- const createResult = await github.createPR({
2018
- owner: repoInfo.owner,
2019
- repo: repoInfo.repo,
2020
- title: prTitle,
2021
- body: prBody,
2022
- head: task.branchName,
2023
- base: task.project?.baseBranch || "develop"
2024
- });
2025
- if (!createResult.success) {
2026
- throw new Error(`Failed to create PR: ${createResult.error}`);
2027
- }
2028
- const updatedTask = await prisma2.task.update({
2029
- where: { id: taskId },
2030
- data: {
2031
- state: TaskState.REVIEW,
2032
- completedAt: /* @__PURE__ */ new Date(),
2033
- pullRequestUrl: createResult.prUrl,
2034
- pullRequestNumber: createResult.prNumber
2035
- }
2036
- });
2037
- return {
2038
- success: true,
2039
- taskId: updatedTask.id,
2040
- prUrl: createResult.prUrl,
2041
- prNumber: createResult.prNumber
2042
- };
2043
- }
2044
- async function checkActiveTask() {
2045
- const fs = await import("fs");
2046
- const path = await import("path");
2047
- const activeTaskPath = path.join(process.cwd(), ".mtaap", "active-task.json");
2048
- if (!await fs.promises.access(activeTaskPath).catch(() => false)) {
2049
- return {
2050
- hasActiveTask: false,
2051
- task: null
2052
- };
2053
- }
2054
- const content = await fs.promises.readFile(activeTaskPath, "utf-8");
2055
- const activeTask = JSON.parse(content);
2056
- return {
2057
- hasActiveTask: true,
2058
- task: activeTask
2059
- };
2060
- }
2061
- async function reportTaskError(taskId, userId, errorType, errorMessage, _context) {
2062
- const task = await prisma2.task.findUnique({
2063
- where: { id: taskId }
2064
- });
2065
- if (!task) {
2066
- throw new Error("Task not found");
2067
- }
2068
- if (task.assigneeId !== userId) {
2069
- throw new Error("You are not assigned to this task");
2070
- }
2071
- const updatedTask = await prisma2.task.update({
2072
- where: { id: taskId },
2073
- data: {
2074
- errorType,
2075
- errorMessage
2076
- }
2077
- });
2078
- return {
2079
- success: true,
2080
- taskId: updatedTask.id
2081
- };
2082
- }
2083
- async function getProjectContext(projectId) {
2084
- const project = await prisma2.project.findUnique({
2085
- where: { id: projectId },
2086
- include: {
2087
- organization: {
2088
- include: { settings: true }
2089
- }
2090
- }
2091
- });
2092
- if (!project) {
2093
- throw new Error("Project not found");
2094
- }
2095
- const repoInfo = GitHubProvider.parseRepositoryUrl(project.repositoryUrl);
2096
- let readme = "";
2097
- let stack = [];
2098
- if (repoInfo) {
2099
- const github = getGitHubClient(project.organizationId || "");
2100
- const readmeResult = await github.getRepositoryReadme(
2101
- repoInfo.owner,
2102
- repoInfo.repo
2103
- );
2104
- readme = readmeResult || "No README found";
2105
- const packageJsonResult = await github.getRepositoryPackageJson(
2106
- repoInfo.owner,
2107
- repoInfo.repo
2108
- );
2109
- if (packageJsonResult) {
2110
- const packageJson = JSON.parse(packageJsonResult);
2111
- const deps = {
2112
- ...packageJson.dependencies,
2113
- ...packageJson.devDependencies
2114
- };
2115
- stack = Object.keys(deps).slice(0, 20);
2116
- }
2117
- }
2118
- const recentCompletedTasks = await prisma2.task.findMany({
2119
- where: {
2120
- project: {
2121
- id: projectId
2122
- },
2123
- state: TaskState.DONE
2124
- },
2125
- orderBy: { completedAt: "desc" },
2126
- take: 10,
2127
- include: {
2128
- creator: {
2129
- select: { id: true, name: true }
2130
- }
2131
- }
2132
- });
2133
- const conventions = {
2134
- branchPrefix: "feature/",
2135
- commitFormat: project.organization?.settings?.enforceConventionalCommits ? "conventional" : "none",
2136
- testCommand: "npm test",
2137
- baseBranch: project.baseBranch || "develop",
2138
- notes: project.organization?.settings?.maxPersonalProjectsPerUser?.toString() || ""
2139
- };
2140
- return {
2141
- readme: readme.substring(0, 2e3),
2142
- stack,
2143
- recentCompleted: recentCompletedTasks.map(
2144
- (task) => ({
2145
- id: task.id,
2146
- title: task.title,
2147
- completedAt: task.completedAt
2148
- })
2149
- ),
2150
- conventions
2151
- };
2152
- }
2153
- async function addTaskNote(taskId, userId, content) {
2154
- const task = await prisma2.task.findUnique({
2155
- where: { id: taskId }
2156
- });
2157
- if (!task) {
2158
- throw new Error("Task not found");
2159
- }
2160
- if (task.assigneeId !== userId) {
2161
- throw new Error("You are not assigned to this task");
2162
- }
2163
- const note = await prisma2.taskNote.create({
2164
- data: {
2165
- taskId,
2166
- userId,
2167
- content
2168
- }
2169
- });
2170
- return {
2171
- success: true,
2172
- noteId: note.id
2173
- };
2174
- }
2175
- async function abandonTask(taskId, projectId, userId, deleteBranch) {
2176
- const task = await prisma2.task.findUnique({
2177
- where: { id: taskId },
2178
- include: { project: true }
2179
- });
2180
- if (!task) {
2181
- throw new Error("Task not found");
2182
- }
2183
- if (task.projectId !== projectId) {
2184
- throw new Error("Task does not belong to the specified project");
2185
- }
2186
- if (task.assigneeId !== userId) {
2187
- throw new Error("You can only abandon tasks you are assigned to");
2188
- }
2189
- const repositoryUrl = task.project?.repositoryUrl;
2190
- const repoInfo = repositoryUrl ? GitHubProvider.parseRepositoryUrl(repositoryUrl) : void 0;
2191
- if (deleteBranch && repoInfo && task.branchName) {
2192
- const github = getGitHubClient(task.project?.organizationId || "");
2193
- try {
2194
- await github.deleteBranch(repoInfo.owner, repoInfo.repo, task.branchName);
2195
- } catch (error) {
2196
- console.error("Failed to delete GitHub branch when abandoning task", {
2197
- taskId,
2198
- projectId: task.projectId,
2199
- organizationId: task.project?.organizationId,
2200
- repositoryOwner: repoInfo.owner,
2201
- repositoryName: repoInfo.repo,
2202
- branchName: task.branchName,
2203
- error
2204
- });
2205
- throw new Error("Failed to delete branch");
2206
- }
2207
- }
2208
- const newState = task.state === TaskState.IN_PROGRESS ? TaskState.READY : task.state;
2209
- const updatedTask = await prisma2.task.update({
2210
- where: { id: taskId },
2211
- data: {
2212
- state: newState,
2213
- assigneeId: null,
2214
- assignedAt: null,
2215
- startedAt: null,
2216
- updatedAt: /* @__PURE__ */ new Date()
2217
- }
2218
- });
2219
- return {
2220
- success: true,
2221
- taskId: updatedTask.id,
2222
- state: updatedTask.state,
2223
- branchDeleted: deleteBranch ? !!repoInfo && !!task.branchName : false
2224
- };
2225
- }
2226
- async function createPersonalProject(userId, name, description, repositoryUrl) {
2227
- const user = await prisma2.user.findUnique({
2228
- where: { id: userId },
2229
- include: { organizations: true }
2230
- });
2231
- if (!user) {
2232
- throw new Error("User not found");
2233
- }
2234
- const repoInfo = GitHubProvider.parseRepositoryUrl(repositoryUrl);
2235
- if (!repoInfo) {
2236
- throw new Error("Invalid repository URL");
2237
- }
2238
- const github = getGitHubClient(user.organizations[0]?.organizationId || "");
2239
- const branchInfo = await github.getBranchInfo({
2240
- owner: repoInfo.owner,
2241
- repo: repoInfo.repo,
2242
- branch: "main"
2243
- });
2244
- if (!branchInfo) {
2245
- throw new Error("Could not get repository branch info");
2246
- }
2247
- const project = await prisma2.project.create({
2248
- data: {
2249
- name,
2250
- description,
2251
- type: ProjectType.PERSONAL,
2252
- origin: ProjectOrigin.CREATED,
2253
- ownerId: userId,
2254
- organizationId: null,
2255
- repositoryUrl,
2256
- baseBranch: "main"
2257
- }
2258
- });
2259
- return {
2260
- success: true,
2261
- projectId: project.id
2262
- };
2263
- }
2264
-
2265
- export {
2266
- createMCPServer
2267
- };
2268
- //# sourceMappingURL=chunk-7YL3QGGO.js.map