@mtaap/mcp 0.2.1 → 0.2.3

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/dist/cli.js CHANGED
@@ -28,16 +28,19 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
28
28
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
29
29
 
30
30
  // src/version.ts
31
- var VERSION = "0.2.1";
31
+ var VERSION = "0.2.3";
32
+
33
+ // src/index.ts
34
+ var import_zod3 = require("zod");
32
35
 
33
36
  // ../../packages/core/dist/constants/enums.js
34
37
  var TaskState;
35
- (function(TaskState3) {
36
- TaskState3["BACKLOG"] = "BACKLOG";
37
- TaskState3["READY"] = "READY";
38
- TaskState3["IN_PROGRESS"] = "IN_PROGRESS";
39
- TaskState3["REVIEW"] = "REVIEW";
40
- TaskState3["DONE"] = "DONE";
38
+ (function(TaskState2) {
39
+ TaskState2["BACKLOG"] = "BACKLOG";
40
+ TaskState2["READY"] = "READY";
41
+ TaskState2["IN_PROGRESS"] = "IN_PROGRESS";
42
+ TaskState2["REVIEW"] = "REVIEW";
43
+ TaskState2["DONE"] = "DONE";
41
44
  })(TaskState || (TaskState = {}));
42
45
  var UserRole;
43
46
  (function(UserRole2) {
@@ -401,56 +404,78 @@ var ListTasksInputSchema = import_zod2.z.object({
401
404
  state: import_zod2.z.nativeEnum(TaskState).optional(),
402
405
  assigneeId: import_zod2.z.string().optional()
403
406
  });
407
+ var cuidOrPrefixedId = import_zod2.z.string().regex(/^([a-z0-9]+|[a-z]+_[a-zA-Z0-9]+)$/);
404
408
  var GetTaskInputSchema = import_zod2.z.object({
405
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/)
409
+ taskId: cuidOrPrefixedId
406
410
  });
407
411
  var AssignTaskInputSchema = import_zod2.z.object({
408
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
409
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
412
+ projectId: cuidOrPrefixedId,
413
+ taskId: cuidOrPrefixedId,
410
414
  expectedState: import_zod2.z.nativeEnum(TaskState).default(TaskState.READY)
411
415
  });
412
416
  var UpdateProgressInputSchema = import_zod2.z.object({
413
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
417
+ taskId: cuidOrPrefixedId,
414
418
  statusMessage: import_zod2.z.string().max(1e3).optional(),
415
419
  completedCheckpointIds: import_zod2.z.array(import_zod2.z.string()).optional(),
416
420
  currentCheckpointIndex: import_zod2.z.number().int().optional()
417
421
  });
418
422
  var CompleteTaskInputSchema = import_zod2.z.object({
419
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
420
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
423
+ projectId: cuidOrPrefixedId,
424
+ taskId: cuidOrPrefixedId,
421
425
  pullRequestTitle: import_zod2.z.string().min(1).max(300).optional(),
422
426
  pullRequestBody: import_zod2.z.string().max(1e4).optional()
423
427
  });
424
428
  var ReportErrorInputSchema = import_zod2.z.object({
425
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
429
+ taskId: cuidOrPrefixedId,
426
430
  errorType: import_zod2.z.nativeEnum(ErrorType),
427
431
  errorMessage: import_zod2.z.string().min(1).max(1e3),
428
432
  context: import_zod2.z.string().max(2e3).optional()
429
433
  });
430
434
  var GetProjectContextInputSchema = import_zod2.z.object({
431
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/)
435
+ projectId: cuidOrPrefixedId
432
436
  });
433
437
  var AddNoteInputSchema = import_zod2.z.object({
434
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
438
+ taskId: cuidOrPrefixedId,
435
439
  content: import_zod2.z.string().min(1).max(500)
436
440
  });
437
441
  var AbandonTaskInputSchema = import_zod2.z.object({
438
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
439
- taskId: import_zod2.z.string().regex(/^tsk_[a-zA-Z0-9]+$/),
442
+ projectId: cuidOrPrefixedId,
443
+ taskId: cuidOrPrefixedId,
440
444
  deleteBranch: import_zod2.z.boolean().optional()
441
445
  });
446
+ var RequestChangesInputSchema = import_zod2.z.object({
447
+ projectId: cuidOrPrefixedId,
448
+ taskId: cuidOrPrefixedId,
449
+ reviewComments: import_zod2.z.string().min(1).max(5e3),
450
+ requestedChanges: import_zod2.z.array(import_zod2.z.string().min(1).max(500)).optional()
451
+ });
452
+ var ApproveTaskInputSchema = import_zod2.z.object({
453
+ projectId: cuidOrPrefixedId,
454
+ taskId: cuidOrPrefixedId,
455
+ reviewComments: import_zod2.z.string().max(2e3).optional()
456
+ });
442
457
  var CreatePersonalProjectInputSchema = import_zod2.z.object({
443
458
  name: import_zod2.z.string().min(1).max(100),
444
459
  description: import_zod2.z.string().max(500).optional(),
445
460
  repositoryUrl: import_zod2.z.string().url()
446
461
  });
447
462
  var CheckActiveTaskInputSchema = import_zod2.z.object({});
463
+ var CreateTaskMCPInputSchema = import_zod2.z.object({
464
+ projectId: cuidOrPrefixedId,
465
+ epicId: cuidOrPrefixedId.nullable().optional(),
466
+ title: import_zod2.z.string().min(1).max(200),
467
+ description: import_zod2.z.string().max(5e3),
468
+ priority: import_zod2.z.nativeEnum(TaskPriority).default(TaskPriority.MEDIUM),
469
+ acceptanceCriteria: import_zod2.z.array(import_zod2.z.object({
470
+ description: import_zod2.z.string().min(1).max(500)
471
+ })).min(1)
472
+ });
448
473
  var CreateOrganizationInputSchema = import_zod2.z.object({
449
474
  name: import_zod2.z.string().min(1).max(255),
450
475
  slug: import_zod2.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
451
476
  });
452
477
  var UpdateOrganizationInputSchema = import_zod2.z.object({
453
- organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
478
+ organizationId: cuidOrPrefixedId,
454
479
  name: import_zod2.z.string().min(1).max(255).optional(),
455
480
  logoUrl: import_zod2.z.string().url().nullable().optional(),
456
481
  accentColor: import_zod2.z.string().regex(/^#[0-9A-Fa-f]{6}$/, "Invalid hex color format. Expected #RRGGBB").nullable().optional(),
@@ -473,7 +498,7 @@ var UpdateProjectInputSchema = import_zod2.z.object({
473
498
  tags: import_zod2.z.array(import_zod2.z.string()).optional()
474
499
  });
475
500
  var CreateEpicInputSchema = import_zod2.z.object({
476
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
501
+ projectId: cuidOrPrefixedId,
477
502
  name: import_zod2.z.string().min(1).max(200),
478
503
  description: import_zod2.z.string().max(2e3).optional()
479
504
  });
@@ -505,14 +530,14 @@ var AssignTaskWebappInputSchema = import_zod2.z.object({
505
530
  userId: import_zod2.z.string().min(1)
506
531
  });
507
532
  var CreateTagInputSchema = import_zod2.z.object({
508
- organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
533
+ organizationId: cuidOrPrefixedId,
509
534
  name: import_zod2.z.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
510
535
  });
511
536
  var UpdateTagInputSchema = import_zod2.z.object({
512
537
  name: import_zod2.z.string().min(1).max(50).regex(/^[a-zA-Z0-9\s-]+$/)
513
538
  });
514
539
  var UpdateOrganizationSettingsInputSchema = import_zod2.z.object({
515
- organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
540
+ organizationId: cuidOrPrefixedId,
516
541
  ldapEnabled: import_zod2.z.boolean().optional(),
517
542
  ldapUrl: import_zod2.z.string().url().nullable().optional(),
518
543
  ldapBindDN: import_zod2.z.string().nullable().optional(),
@@ -525,21 +550,21 @@ var UpdateOrganizationSettingsInputSchema = import_zod2.z.object({
525
550
  tenantName: import_zod2.z.string().max(255).nullable().optional()
526
551
  });
527
552
  var InviteUserInputSchema = import_zod2.z.object({
528
- organizationId: import_zod2.z.string().regex(/^org_[a-zA-Z0-9]+$/),
553
+ organizationId: cuidOrPrefixedId,
529
554
  email: import_zod2.z.string().email(),
530
555
  role: import_zod2.z.nativeEnum(UserRole).default(UserRole.MEMBER),
531
556
  tags: import_zod2.z.array(import_zod2.z.string()).default([])
532
557
  });
533
558
  var AssignUserTagsInputSchema = import_zod2.z.object({
534
- userId: import_zod2.z.string().regex(/^usr_[a-zA-Z0-9]+$/),
559
+ userId: cuidOrPrefixedId,
535
560
  tags: import_zod2.z.array(import_zod2.z.string()).min(0)
536
561
  });
537
562
  var InviteCollaboratorInputSchema = import_zod2.z.object({
538
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
563
+ projectId: cuidOrPrefixedId,
539
564
  email: import_zod2.z.string().email()
540
565
  });
541
566
  var PublishProjectInputSchema = import_zod2.z.object({
542
- projectId: import_zod2.z.string().regex(/^prj_[a-zA-Z0-9]+$/),
567
+ projectId: cuidOrPrefixedId,
543
568
  transferOwnership: import_zod2.z.boolean().default(false),
544
569
  tags: import_zod2.z.array(import_zod2.z.string()).min(1)
545
570
  });
@@ -549,7 +574,7 @@ var GenerateApiKeyInputSchema = import_zod2.z.object({
549
574
  permissions: import_zod2.z.nativeEnum(ApiKeyPermission).default(ApiKeyPermission.WRITE)
550
575
  });
551
576
  var RevokeApiKeyInputSchema = import_zod2.z.object({
552
- keyId: import_zod2.z.string().regex(/^key_[a-zA-Z0-9]+$/)
577
+ keyId: cuidOrPrefixedId
553
578
  });
554
579
  var LoginInputSchema = import_zod2.z.object({
555
580
  email: import_zod2.z.string().email(),
@@ -982,6 +1007,12 @@ var MCPApiClient = class {
982
1007
  { name, description, repositoryUrl }
983
1008
  );
984
1009
  }
1010
+ /**
1011
+ * Create a task in a project
1012
+ */
1013
+ async createTask(input) {
1014
+ return this.request("POST", "/api/mcp/tasks", input);
1015
+ }
985
1016
  /**
986
1017
  * List tasks with optional filters
987
1018
  */
@@ -1050,6 +1081,25 @@ var MCPApiClient = class {
1050
1081
  async addNote(taskId, content) {
1051
1082
  return this.request("POST", `/api/mcp/tasks/${taskId}/notes`, { content });
1052
1083
  }
1084
+ /**
1085
+ * Request changes on a task in review
1086
+ */
1087
+ async requestChanges(taskId, projectId, reviewComments, requestedChanges) {
1088
+ return this.request("POST", `/api/mcp/tasks/${taskId}/request-changes`, {
1089
+ projectId,
1090
+ reviewComments,
1091
+ requestedChanges
1092
+ });
1093
+ }
1094
+ /**
1095
+ * Approve a task in review and mark as DONE
1096
+ */
1097
+ async approveTask(taskId, projectId, reviewComments) {
1098
+ return this.request("POST", `/api/mcp/tasks/${taskId}/approve`, {
1099
+ projectId,
1100
+ reviewComments
1101
+ });
1102
+ }
1053
1103
  /**
1054
1104
  * Get GitHub token
1055
1105
  */
@@ -1121,7 +1171,10 @@ async function createMCPServer() {
1121
1171
  server.registerTool(
1122
1172
  "list_projects",
1123
1173
  {
1124
- description: "List accessible projects (personal + team via tags)"
1174
+ description: "List accessible projects (personal + team via tags)",
1175
+ inputSchema: {
1176
+ workspaceType: import_zod3.z.enum(["TEAM", "PERSONAL", "ALL"]).optional().describe("Filter by workspace type")
1177
+ }
1125
1178
  },
1126
1179
  async (args) => {
1127
1180
  assertApiKeyPermission(
@@ -1148,7 +1201,12 @@ async function createMCPServer() {
1148
1201
  server.registerTool(
1149
1202
  "list_tasks",
1150
1203
  {
1151
- description: "Returns available tasks (filterable by project, state)"
1204
+ description: "Returns available tasks (filterable by project, state)",
1205
+ inputSchema: {
1206
+ projectId: import_zod3.z.string().optional().describe("Filter by project ID"),
1207
+ state: import_zod3.z.nativeEnum(TaskState).optional().describe("Filter by task state"),
1208
+ assigneeId: import_zod3.z.string().optional().describe("Filter by assignee ID")
1209
+ }
1152
1210
  },
1153
1211
  async (args) => {
1154
1212
  assertApiKeyPermission(mockApiKey, ApiKeyPermission.READ, "list_tasks");
@@ -1175,7 +1233,10 @@ async function createMCPServer() {
1175
1233
  server.registerTool(
1176
1234
  "get_task",
1177
1235
  {
1178
- description: "Full task details including acceptance criteria"
1236
+ description: "Full task details including acceptance criteria",
1237
+ inputSchema: {
1238
+ taskId: import_zod3.z.string().describe("The task ID to retrieve")
1239
+ }
1179
1240
  },
1180
1241
  async (args) => {
1181
1242
  assertApiKeyPermission(mockApiKey, ApiKeyPermission.READ, "get_task");
@@ -1198,7 +1259,12 @@ async function createMCPServer() {
1198
1259
  server.registerTool(
1199
1260
  "assign_task",
1200
1261
  {
1201
- description: "Atomic claim - creates branch. Fails if already taken."
1262
+ description: "Atomic claim - creates branch. Fails if already taken.",
1263
+ inputSchema: {
1264
+ projectId: import_zod3.z.string().describe("The project ID"),
1265
+ taskId: import_zod3.z.string().describe("The task ID to assign"),
1266
+ expectedState: import_zod3.z.nativeEnum(TaskState).optional().describe("Expected task state (default: READY)")
1267
+ }
1202
1268
  },
1203
1269
  async (args) => {
1204
1270
  assertApiKeyPermission(
@@ -1229,7 +1295,13 @@ async function createMCPServer() {
1229
1295
  server.registerTool(
1230
1296
  "update_progress",
1231
1297
  {
1232
- description: "Reports status, updates checkboxes, writes checkpoint"
1298
+ description: "Reports status, updates checkboxes, writes checkpoint",
1299
+ inputSchema: {
1300
+ taskId: import_zod3.z.string().describe("The task ID to update"),
1301
+ statusMessage: import_zod3.z.string().optional().describe("Status message (max 1000 chars)"),
1302
+ completedCheckpointIds: import_zod3.z.array(import_zod3.z.string()).optional().describe("Array of completed checkpoint IDs"),
1303
+ currentCheckpointIndex: import_zod3.z.number().optional().describe("Current checkpoint index")
1304
+ }
1233
1305
  },
1234
1306
  async (args) => {
1235
1307
  assertApiKeyPermission(
@@ -1260,7 +1332,13 @@ async function createMCPServer() {
1260
1332
  server.registerTool(
1261
1333
  "complete_task",
1262
1334
  {
1263
- description: "Marks complete, triggers PR, deletes local state file"
1335
+ description: "Marks complete, triggers PR, deletes local state file",
1336
+ inputSchema: {
1337
+ projectId: import_zod3.z.string().describe("The project ID"),
1338
+ taskId: import_zod3.z.string().describe("The task ID to complete"),
1339
+ pullRequestTitle: import_zod3.z.string().optional().describe("PR title (max 300 chars)"),
1340
+ pullRequestBody: import_zod3.z.string().optional().describe("PR body/description (max 10000 chars)")
1341
+ }
1264
1342
  },
1265
1343
  async (args) => {
1266
1344
  assertApiKeyPermission(
@@ -1314,7 +1392,13 @@ async function createMCPServer() {
1314
1392
  server.registerTool(
1315
1393
  "report_error",
1316
1394
  {
1317
- description: "Report unrecoverable error, displays on task in webapp"
1395
+ description: "Report unrecoverable error, displays on task in webapp",
1396
+ inputSchema: {
1397
+ taskId: import_zod3.z.string().describe("The task ID"),
1398
+ errorType: import_zod3.z.nativeEnum(ErrorType).describe("Error type: BUILD_FAILURE, TEST_FAILURE, CONFLICT, AUTH_ERROR, OTHER"),
1399
+ errorMessage: import_zod3.z.string().describe("Error message (max 1000 chars)"),
1400
+ context: import_zod3.z.string().optional().describe("Additional context (max 2000 chars)")
1401
+ }
1318
1402
  },
1319
1403
  async (args) => {
1320
1404
  assertApiKeyPermission(
@@ -1346,7 +1430,10 @@ async function createMCPServer() {
1346
1430
  server.registerTool(
1347
1431
  "get_project_context",
1348
1432
  {
1349
- description: "Returns assembled context (README, stack, conventions)"
1433
+ description: "Returns assembled context (README, stack, conventions)",
1434
+ inputSchema: {
1435
+ projectId: import_zod3.z.string().describe("The project ID")
1436
+ }
1350
1437
  },
1351
1438
  async (args) => {
1352
1439
  assertApiKeyPermission(
@@ -1373,7 +1460,11 @@ async function createMCPServer() {
1373
1460
  server.registerTool(
1374
1461
  "add_note",
1375
1462
  {
1376
- description: "Append implementation notes to task"
1463
+ description: "Append implementation notes to task",
1464
+ inputSchema: {
1465
+ taskId: import_zod3.z.string().describe("The task ID"),
1466
+ content: import_zod3.z.string().describe("Note content (max 500 chars)")
1467
+ }
1377
1468
  },
1378
1469
  async (args) => {
1379
1470
  assertApiKeyPermission(mockApiKey, ApiKeyPermission.WRITE, "add_note");
@@ -1399,7 +1490,12 @@ async function createMCPServer() {
1399
1490
  server.registerTool(
1400
1491
  "abandon_task",
1401
1492
  {
1402
- description: "Unassign from a task and optionally delete the branch"
1493
+ description: "Unassign from a task and optionally delete the branch",
1494
+ inputSchema: {
1495
+ projectId: import_zod3.z.string().describe("The project ID"),
1496
+ taskId: import_zod3.z.string().describe("The task ID to abandon"),
1497
+ deleteBranch: import_zod3.z.boolean().optional().describe("Whether to delete the associated branch")
1498
+ }
1403
1499
  },
1404
1500
  async (args) => {
1405
1501
  assertApiKeyPermission(
@@ -1430,7 +1526,12 @@ async function createMCPServer() {
1430
1526
  server.registerTool(
1431
1527
  "create_personal_project",
1432
1528
  {
1433
- description: "Create project in user's personal workspace"
1529
+ description: "Create project in user's personal workspace",
1530
+ inputSchema: {
1531
+ name: import_zod3.z.string().describe("Project name (max 100 chars)"),
1532
+ description: import_zod3.z.string().optional().describe("Project description (max 500 chars)"),
1533
+ repositoryUrl: import_zod3.z.string().describe("GitHub repository URL")
1534
+ }
1434
1535
  },
1435
1536
  async (args) => {
1436
1537
  assertApiKeyPermission(
@@ -1458,6 +1559,126 @@ async function createMCPServer() {
1458
1559
  }
1459
1560
  }
1460
1561
  );
1562
+ server.registerTool(
1563
+ "create_task",
1564
+ {
1565
+ description: "Create a new task in a project. Requires WRITE permission and project access.",
1566
+ inputSchema: {
1567
+ projectId: import_zod3.z.string().describe("The project ID to create the task in"),
1568
+ epicId: import_zod3.z.string().nullable().optional().describe("Optional epic ID to associate the task with"),
1569
+ title: import_zod3.z.string().describe("Task title (max 200 chars)"),
1570
+ description: import_zod3.z.string().describe("Task description (max 5000 chars)"),
1571
+ priority: import_zod3.z.nativeEnum(TaskPriority).optional().describe("Task priority: LOW, MEDIUM, HIGH, CRITICAL (default: MEDIUM)"),
1572
+ acceptanceCriteria: import_zod3.z.array(
1573
+ import_zod3.z.object({
1574
+ description: import_zod3.z.string().describe("Acceptance criterion description (max 500 chars)")
1575
+ })
1576
+ ).describe("Array of acceptance criteria (at least 1 required)")
1577
+ }
1578
+ },
1579
+ async (args) => {
1580
+ assertApiKeyPermission(
1581
+ mockApiKey,
1582
+ ApiKeyPermission.WRITE,
1583
+ "create_task"
1584
+ );
1585
+ const validated = CreateTaskMCPInputSchema.parse(args);
1586
+ try {
1587
+ const result = await apiClient.createTask({
1588
+ projectId: validated.projectId,
1589
+ epicId: validated.epicId,
1590
+ title: validated.title,
1591
+ description: validated.description,
1592
+ priority: validated.priority,
1593
+ acceptanceCriteria: validated.acceptanceCriteria
1594
+ });
1595
+ return {
1596
+ content: [
1597
+ {
1598
+ type: "text",
1599
+ text: JSON.stringify(result, null, 2)
1600
+ }
1601
+ ]
1602
+ };
1603
+ } catch (error) {
1604
+ return handleApiError(error);
1605
+ }
1606
+ }
1607
+ );
1608
+ server.registerTool(
1609
+ "request_changes",
1610
+ {
1611
+ description: "Submit review comments requesting changes on a task in REVIEW state",
1612
+ inputSchema: {
1613
+ projectId: import_zod3.z.string().describe("The project ID"),
1614
+ taskId: import_zod3.z.string().describe("The task ID to review"),
1615
+ reviewComments: import_zod3.z.string().describe("Review comments explaining requested changes (max 5000 chars)"),
1616
+ requestedChanges: import_zod3.z.array(import_zod3.z.string()).optional().describe("List of specific changes requested")
1617
+ }
1618
+ },
1619
+ async (args) => {
1620
+ assertApiKeyPermission(
1621
+ mockApiKey,
1622
+ ApiKeyPermission.WRITE,
1623
+ "request_changes"
1624
+ );
1625
+ const validated = RequestChangesInputSchema.parse(args);
1626
+ try {
1627
+ const result = await apiClient.requestChanges(
1628
+ validated.taskId,
1629
+ validated.projectId,
1630
+ validated.reviewComments,
1631
+ validated.requestedChanges
1632
+ );
1633
+ return {
1634
+ content: [
1635
+ {
1636
+ type: "text",
1637
+ text: JSON.stringify(result, null, 2)
1638
+ }
1639
+ ]
1640
+ };
1641
+ } catch (error) {
1642
+ return handleApiError(error);
1643
+ }
1644
+ }
1645
+ );
1646
+ server.registerTool(
1647
+ "approve_task",
1648
+ {
1649
+ description: "Approve a task in REVIEW state and mark it as DONE",
1650
+ inputSchema: {
1651
+ projectId: import_zod3.z.string().describe("The project ID"),
1652
+ taskId: import_zod3.z.string().describe("The task ID to approve"),
1653
+ reviewComments: import_zod3.z.string().optional().describe("Optional approval comments (max 2000 chars)")
1654
+ }
1655
+ },
1656
+ async (args) => {
1657
+ assertApiKeyPermission(
1658
+ mockApiKey,
1659
+ ApiKeyPermission.WRITE,
1660
+ "approve_task"
1661
+ );
1662
+ const validated = ApproveTaskInputSchema.parse(args);
1663
+ try {
1664
+ const result = await apiClient.approveTask(
1665
+ validated.taskId,
1666
+ validated.projectId,
1667
+ validated.reviewComments
1668
+ );
1669
+ return {
1670
+ content: [
1671
+ {
1672
+ type: "text",
1673
+ text: JSON.stringify(result, null, 2)
1674
+ }
1675
+ ]
1676
+ };
1677
+ } catch (error) {
1678
+ return handleApiError(error);
1679
+ }
1680
+ }
1681
+ );
1461
1682
  server.registerTool(
1462
1683
  "get_version",
1463
1684
  {
@@ -1538,6 +1759,44 @@ async function checkActiveTask() {
1538
1759
  }
1539
1760
 
1540
1761
  // src/cli.ts
1762
+ function handleCliFlags() {
1763
+ const args = process.argv.slice(2);
1764
+ if (args.includes("--version") || args.includes("-v")) {
1765
+ console.log(`mtaap-mcp v${VERSION}`);
1766
+ process.exit(0);
1767
+ }
1768
+ if (args.includes("--help") || args.includes("-h")) {
1769
+ console.log(`mtaap-mcp v${VERSION}
1770
+
1771
+ MTAAP MCP Server - Model Context Protocol server for MTAAP
1772
+
1773
+ Usage:
1774
+ mtaap-mcp [options]
1775
+
1776
+ Options:
1777
+ -v, --version Show version number
1778
+ -h, --help Show this help message
1779
+
1780
+ Environment Variables:
1781
+ MTAAP_API_KEY Your MTAAP API key (required)
1782
+ MTAAP_BASE_URL MTAAP webapp URL (required)
1783
+
1784
+ Example mcp.json configuration:
1785
+ {
1786
+ "mcpServers": {
1787
+ "mtaap": {
1788
+ "command": "npx",
1789
+ "args": ["@mtaap/mcp"],
1790
+ "env": {
1791
+ "MTAAP_API_KEY": "usr_your_api_key_here",
1792
+ "MTAAP_BASE_URL": "https://collab.mtaap.de"
1793
+ }
1794
+ }
1795
+ }
1796
+ }`);
1797
+ process.exit(0);
1798
+ }
1799
+ }
1541
1800
  function validateEnvironment() {
1542
1801
  const errors = [];
1543
1802
  if (!process.env.MTAAP_API_KEY) {
@@ -1612,6 +1871,7 @@ async function checkConnectivity() {
1612
1871
  }
1613
1872
  }
1614
1873
  async function main() {
1874
+ handleCliFlags();
1615
1875
  console.error("[mtaap-mcp] Starting MTAAP MCP server...");
1616
1876
  validateEnvironment();
1617
1877
  await checkConnectivity();