@mtaap/mcp 0.2.5 → 0.2.7

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,7 +28,7 @@ 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.5";
31
+ var VERSION = "0.2.7";
32
32
 
33
33
  // src/index.ts
34
34
  var import_zod3 = require("zod");
@@ -36,12 +36,20 @@ var import_zod3 = require("zod");
36
36
  // ../../packages/core/dist/constants/enums.js
37
37
  var TaskState;
38
38
  (function(TaskState2) {
39
+ TaskState2["DRAFT"] = "DRAFT";
40
+ TaskState2["TODO"] = "TODO";
39
41
  TaskState2["BACKLOG"] = "BACKLOG";
40
42
  TaskState2["READY"] = "READY";
41
43
  TaskState2["IN_PROGRESS"] = "IN_PROGRESS";
42
44
  TaskState2["REVIEW"] = "REVIEW";
43
45
  TaskState2["DONE"] = "DONE";
44
46
  })(TaskState || (TaskState = {}));
47
+ var VerificationStatus;
48
+ (function(VerificationStatus2) {
49
+ VerificationStatus2["PENDING"] = "PENDING";
50
+ VerificationStatus2["PASSED"] = "PASSED";
51
+ VerificationStatus2["NEEDS_REVISION"] = "NEEDS_REVISION";
52
+ })(VerificationStatus || (VerificationStatus = {}));
45
53
  var UserRole;
46
54
  (function(UserRole2) {
47
55
  UserRole2["ADMIN"] = "ADMIN";
@@ -106,6 +114,8 @@ var WebSocketEventType;
106
114
  WebSocketEventType2["TASK_COMPLETED"] = "task.completed";
107
115
  WebSocketEventType2["TASK_ERROR"] = "task.error";
108
116
  WebSocketEventType2["TASK_STATE_CHANGED"] = "task.state_changed";
117
+ WebSocketEventType2["TASK_UPDATED"] = "task.updated";
118
+ WebSocketEventType2["TASK_DELETED"] = "task.deleted";
109
119
  WebSocketEventType2["MEMBER_JOINED"] = "member.joined";
110
120
  })(WebSocketEventType || (WebSocketEventType = {}));
111
121
  var AuthProvider;
@@ -132,16 +142,20 @@ var EventType;
132
142
 
133
143
  // ../../packages/core/dist/constants/state-machine.js
134
144
  var VALID_TRANSITIONS = {
135
- [TaskState.BACKLOG]: [TaskState.READY],
136
- [TaskState.READY]: [TaskState.BACKLOG, TaskState.IN_PROGRESS],
145
+ [TaskState.DRAFT]: [TaskState.TODO],
146
+ [TaskState.TODO]: [TaskState.DRAFT, TaskState.IN_PROGRESS],
147
+ // Deprecated: BACKLOG transitions to DRAFT (its replacement)
148
+ [TaskState.BACKLOG]: [TaskState.DRAFT, TaskState.TODO],
149
+ // Deprecated: READY transitions to TODO (its replacement)
150
+ [TaskState.READY]: [TaskState.TODO, TaskState.IN_PROGRESS],
137
151
  [TaskState.IN_PROGRESS]: [
138
- TaskState.BACKLOG,
139
- TaskState.READY,
152
+ TaskState.DRAFT,
153
+ TaskState.TODO,
140
154
  TaskState.REVIEW
141
155
  ],
142
156
  [TaskState.REVIEW]: [
143
- TaskState.BACKLOG,
144
- TaskState.READY,
157
+ TaskState.DRAFT,
158
+ TaskState.TODO,
145
159
  TaskState.IN_PROGRESS,
146
160
  TaskState.DONE
147
161
  ],
@@ -412,7 +426,7 @@ var GetTaskInputSchema = import_zod2.z.object({
412
426
  var AssignTaskInputSchema = import_zod2.z.object({
413
427
  projectId: cuidOrPrefixedId,
414
428
  taskId: cuidOrPrefixedId,
415
- expectedState: import_zod2.z.nativeEnum(TaskState).default(TaskState.READY)
429
+ expectedState: import_zod2.z.nativeEnum(TaskState).default(TaskState.TODO)
416
430
  });
417
431
  var UpdateProgressInputSchema = import_zod2.z.object({
418
432
  taskId: cuidOrPrefixedId,
@@ -596,6 +610,38 @@ var RegisterInputSchema = import_zod2.z.object({
596
610
  name: import_zod2.z.string().min(1).max(255),
597
611
  organizationSlug: import_zod2.z.string().min(1).max(100).regex(/^[a-z0-9-]+$/).optional()
598
612
  });
613
+ var VerifyTaskInputSchema = import_zod2.z.object({
614
+ projectId: cuidOrPrefixedId,
615
+ taskId: cuidOrPrefixedId,
616
+ approved: import_zod2.z.boolean(),
617
+ feedback: import_zod2.z.string().max(5e3).optional()
618
+ });
619
+ var GetTaskPromptInputSchema = import_zod2.z.object({
620
+ projectId: cuidOrPrefixedId,
621
+ taskId: cuidOrPrefixedId
622
+ });
623
+ var UpdateTaskMCPInputSchema = import_zod2.z.object({
624
+ projectId: cuidOrPrefixedId,
625
+ taskId: cuidOrPrefixedId,
626
+ title: import_zod2.z.string().min(1).max(200).optional(),
627
+ description: import_zod2.z.string().max(5e3).optional(),
628
+ priority: import_zod2.z.nativeEnum(TaskPriority).optional(),
629
+ acceptanceCriteria: import_zod2.z.array(import_zod2.z.object({
630
+ id: import_zod2.z.string().optional(),
631
+ description: import_zod2.z.string().min(1).max(500)
632
+ })).optional()
633
+ });
634
+ var ReportBranchInputSchema = import_zod2.z.object({
635
+ projectId: cuidOrPrefixedId,
636
+ taskId: cuidOrPrefixedId,
637
+ branchName: import_zod2.z.string().min(1).max(100)
638
+ });
639
+ var ReportPRInputSchema = import_zod2.z.object({
640
+ projectId: cuidOrPrefixedId,
641
+ taskId: cuidOrPrefixedId,
642
+ pullRequestUrl: import_zod2.z.string().url(),
643
+ pullRequestNumber: import_zod2.z.number().int().positive()
644
+ });
599
645
 
600
646
  // ../../packages/core/dist/logging/metrics.js
601
647
  var metrics = /* @__PURE__ */ new Map();
@@ -1045,7 +1091,7 @@ var MCPApiClient = class {
1045
1091
  /**
1046
1092
  * Assign task to current user and create branch
1047
1093
  */
1048
- async assignTask(taskId, projectId, expectedState = TaskState.READY) {
1094
+ async assignTask(taskId, projectId, expectedState = TaskState.TODO) {
1049
1095
  return this.request("POST", `/api/mcp/tasks/${taskId}/assign`, {
1050
1096
  projectId,
1051
1097
  expectedState
@@ -1058,7 +1104,8 @@ var MCPApiClient = class {
1058
1104
  return this.request("POST", `/api/mcp/tasks/${taskId}/progress`, data);
1059
1105
  }
1060
1106
  /**
1061
- * Complete task and create PR
1107
+ * Complete task and prepare for PR creation.
1108
+ * Returns PR suggestions for the agent to use when creating the PR locally.
1062
1109
  */
1063
1110
  async completeTask(taskId, projectId, pullRequestTitle, pullRequestBody) {
1064
1111
  return this.request("POST", `/api/mcp/tasks/${taskId}/complete`, {
@@ -1128,11 +1175,51 @@ var MCPApiClient = class {
1128
1175
  });
1129
1176
  }
1130
1177
  /**
1131
- * Get GitHub token
1178
+ * Report branch created by agent
1132
1179
  */
1133
- async getGitHubToken(organizationId) {
1134
- const path = organizationId ? `/api/mcp/github-token?organizationId=${encodeURIComponent(organizationId)}` : "/api/mcp/github-token";
1135
- return this.request("GET", path);
1180
+ async reportBranch(taskId, projectId, branchName) {
1181
+ return this.request("POST", `/api/mcp/tasks/${taskId}/branch`, {
1182
+ projectId,
1183
+ branchName
1184
+ });
1185
+ }
1186
+ /**
1187
+ * Report PR created by agent
1188
+ */
1189
+ async reportPR(taskId, projectId, pullRequestUrl, pullRequestNumber) {
1190
+ return this.request("POST", `/api/mcp/tasks/${taskId}/pr`, {
1191
+ projectId,
1192
+ pullRequestUrl,
1193
+ pullRequestNumber
1194
+ });
1195
+ }
1196
+ /**
1197
+ * Verify a DRAFT task to move it to TODO state
1198
+ */
1199
+ async verifyTask(taskId, projectId, approved, feedback) {
1200
+ return this.request("POST", `/api/mcp/tasks/${taskId}/verify`, {
1201
+ projectId,
1202
+ approved,
1203
+ feedback
1204
+ });
1205
+ }
1206
+ /**
1207
+ * Get state-appropriate prompt for a task
1208
+ */
1209
+ async getTaskPrompt(taskId, projectId) {
1210
+ return this.request(
1211
+ "GET",
1212
+ `/api/mcp/tasks/${taskId}/prompt?projectId=${encodeURIComponent(projectId)}`
1213
+ );
1214
+ }
1215
+ /**
1216
+ * Update task details (DRAFT/TODO states only)
1217
+ */
1218
+ async updateTask(taskId, projectId, data) {
1219
+ return this.request("PATCH", `/api/mcp/tasks/${taskId}`, {
1220
+ projectId,
1221
+ ...data
1222
+ });
1136
1223
  }
1137
1224
  };
1138
1225
  function createApiClientFromEnv() {
@@ -1185,44 +1272,76 @@ TOOL CATEGORIES:
1185
1272
  - list_projects, get_project_context, get_version
1186
1273
 
1187
1274
  2. Task Management (READ/WRITE):
1188
- - list_tasks, get_task, create_task, archive_task, unarchive_task
1275
+ - list_tasks, get_task, create_task, update_task, archive_task, unarchive_task
1276
+
1277
+ 3. Task Verification (WRITE):
1278
+ - verify_task, get_task_prompt
1189
1279
 
1190
- 3. Task Execution (WRITE):
1280
+ 4. Task Execution (WRITE):
1191
1281
  - assign_task, update_progress, add_note, complete_task, abandon_task, report_error
1192
1282
 
1193
- 4. Code Review (WRITE):
1283
+ 5. Git Operations (WRITE):
1284
+ - report_branch, report_pr
1285
+
1286
+ 6. Code Review (WRITE):
1194
1287
  - request_changes, approve_task
1195
1288
 
1196
- 5. Session Management (READ):
1289
+ 7. Session Management (READ):
1197
1290
  - check_active_task
1198
1291
 
1199
1292
  WORKFLOWS:
1200
1293
 
1294
+ Task Creation & Verification:
1295
+ create_task -> get_task_prompt (DRAFT) -> verify_task(approved=true) -> task moves to TODO
1296
+
1201
1297
  Standard Task Workflow:
1202
- list_projects -> get_project_context -> list_tasks(state=READY) -> get_task -> assign_task -> [update_progress...] -> complete_task
1298
+ list_projects -> get_project_context -> list_tasks(state=TODO) -> get_task -> get_task_prompt (TODO)
1299
+ -> assign_task (returns suggested branch name)
1300
+ -> git checkout -b <branchName> (local git command)
1301
+ -> git push -u origin <branchName> (local git command)
1302
+ -> report_branch (tell server about the branch)
1303
+ -> [update_progress...]
1304
+ -> complete_task (returns PR suggestions)
1305
+ -> gh pr create (local gh command)
1306
+ -> report_pr (tell server about the PR)
1203
1307
 
1204
1308
  Resume Workflow:
1205
- check_active_task -> (if active) get_task -> update_progress -> complete_task
1309
+ check_active_task -> (if active) get_task -> get_task_prompt (IN_PROGRESS) -> update_progress -> complete_task
1206
1310
 
1207
1311
  Review Workflow:
1208
1312
  list_tasks(state=REVIEW) -> get_task -> approve_task OR request_changes
1209
1313
 
1314
+ Task Editing:
1315
+ update_task (DRAFT/TODO only) -> if was TODO, reverts to DRAFT -> verify_task again
1316
+
1210
1317
  Error Recovery:
1211
- report_error -> abandon_task(deleteBranch=false) -> list_tasks -> assign_task (retry or pick different task)
1212
- (abandon_task returns IN_PROGRESS tasks to READY state)
1318
+ report_error -> abandon_task -> list_tasks -> assign_task (retry or pick different task)
1319
+ (abandon_task returns IN_PROGRESS tasks to TODO state)
1320
+
1321
+ GIT OPERATIONS NOTE:
1322
+ The agent handles all git operations locally. After assign_task returns a suggested branch name,
1323
+ the agent creates the branch with git, pushes it, and reports it via report_branch.
1324
+ After complete_task returns PR suggestions, the agent creates the PR with gh, and reports it via report_pr.
1325
+ This eliminates the need for GitHub tokens on the server.
1213
1326
 
1214
1327
  TASK STATE FLOW:
1215
- BACKLOG -> READY -> IN_PROGRESS -> REVIEW -> DONE
1328
+ DRAFT -> TODO -> IN_PROGRESS -> REVIEW -> DONE
1329
+ (verify_task: DRAFT -> TODO)
1330
+ (update_task on TODO: reverts to DRAFT)
1216
1331
  (request_changes: REVIEW -> IN_PROGRESS)
1217
- (abandon_task: IN_PROGRESS -> READY)
1332
+ (abandon_task: IN_PROGRESS -> TODO)
1218
1333
 
1219
1334
  CONSTRAINTS:
1335
+ - DRAFT tasks must be verified before assignment
1336
+ - verify_task requires programmatic validation (title 10+ chars, description 50+ chars, criteria 20+ chars each)
1337
+ - update_task only works on DRAFT and TODO states
1220
1338
  - assign_task is atomic - fails if already claimed
1221
- - Only READY tasks can be assigned
1339
+ - Only TODO tasks can be assigned
1222
1340
  - complete_task requires IN_PROGRESS state
1223
1341
  - request_changes/approve_task require REVIEW state
1224
1342
  - Always check_active_task before starting new work
1225
- - Call update_progress frequently to checkpoint`;
1343
+ - Call update_progress frequently to checkpoint
1344
+ - Agent must have git/gh CLI configured for local git operations`;
1226
1345
  async function createMCPServer() {
1227
1346
  const server = new import_mcp.McpServer(
1228
1347
  {
@@ -1279,7 +1398,7 @@ async function createMCPServer() {
1279
1398
  server.registerTool(
1280
1399
  "list_tasks",
1281
1400
  {
1282
- description: "Query tasks with filters. Use state=READY for assignable tasks, state=REVIEW for pending reviews.",
1401
+ description: "Query tasks with filters. Use state=TODO for assignable tasks, state=REVIEW for pending reviews.",
1283
1402
  inputSchema: {
1284
1403
  projectId: import_zod3.z.string().optional().describe("Filter by project ID"),
1285
1404
  state: import_zod3.z.nativeEnum(TaskState).optional().describe("Filter by task state"),
@@ -1339,11 +1458,11 @@ async function createMCPServer() {
1339
1458
  server.registerTool(
1340
1459
  "assign_task",
1341
1460
  {
1342
- description: "Atomically claim a task and create git branch. Race-safe - fails if already assigned. Task must be READY.",
1461
+ description: "Atomically claim a task and create git branch. Race-safe - fails if already assigned. Task must be TODO.",
1343
1462
  inputSchema: {
1344
1463
  projectId: import_zod3.z.string().describe("The project ID"),
1345
1464
  taskId: import_zod3.z.string().describe("The task ID to assign"),
1346
- expectedState: import_zod3.z.nativeEnum(TaskState).optional().describe("Expected task state (default: READY)")
1465
+ expectedState: import_zod3.z.nativeEnum(TaskState).optional().describe("Expected task state (default: TODO)")
1347
1466
  }
1348
1467
  },
1349
1468
  async (args) => {
@@ -1412,7 +1531,7 @@ async function createMCPServer() {
1412
1531
  server.registerTool(
1413
1532
  "complete_task",
1414
1533
  {
1415
- description: "Finish task and create pull request. Moves task to REVIEW. Requires IN_PROGRESS state.",
1534
+ description: "Prepare task for PR creation. Returns PR suggestions. After creating PR locally, call report_pr to transition to REVIEW. Requires IN_PROGRESS state.",
1416
1535
  inputSchema: {
1417
1536
  projectId: import_zod3.z.string().describe("The project ID"),
1418
1537
  taskId: import_zod3.z.string().describe("The task ID to complete"),
@@ -1570,7 +1689,7 @@ async function createMCPServer() {
1570
1689
  server.registerTool(
1571
1690
  "abandon_task",
1572
1691
  {
1573
- description: "Release task assignment and optionally clean up branch. Task returns to READY. Use after errors.",
1692
+ description: "Release task assignment and optionally clean up branch. Task returns to TODO. Use after errors.",
1574
1693
  inputSchema: {
1575
1694
  projectId: import_zod3.z.string().describe("The project ID"),
1576
1695
  taskId: import_zod3.z.string().describe("The task ID to abandon"),
@@ -1603,6 +1722,80 @@ async function createMCPServer() {
1603
1722
  }
1604
1723
  }
1605
1724
  );
1725
+ server.registerTool(
1726
+ "report_branch",
1727
+ {
1728
+ description: "Report a branch created by the agent. Call after using git to create and push a branch. Task must be IN_PROGRESS.",
1729
+ inputSchema: {
1730
+ projectId: import_zod3.z.string().describe("The project ID"),
1731
+ taskId: import_zod3.z.string().describe("The task ID"),
1732
+ branchName: import_zod3.z.string().describe("Name of the branch created (e.g., feature/TASK-123-fix-login)")
1733
+ }
1734
+ },
1735
+ async (args) => {
1736
+ assertApiKeyPermission(
1737
+ mockApiKey,
1738
+ ApiKeyPermission.WRITE,
1739
+ "report_branch"
1740
+ );
1741
+ const validated = ReportBranchInputSchema.parse(args);
1742
+ try {
1743
+ const result = await apiClient.reportBranch(
1744
+ validated.taskId,
1745
+ validated.projectId,
1746
+ validated.branchName
1747
+ );
1748
+ return {
1749
+ content: [
1750
+ {
1751
+ type: "text",
1752
+ text: JSON.stringify(result, null, 2)
1753
+ }
1754
+ ]
1755
+ };
1756
+ } catch (error) {
1757
+ return handleApiError(error);
1758
+ }
1759
+ }
1760
+ );
1761
+ server.registerTool(
1762
+ "report_pr",
1763
+ {
1764
+ description: "Report a PR created by the agent. Call after using gh pr create. Transitions task to REVIEW state.",
1765
+ inputSchema: {
1766
+ projectId: import_zod3.z.string().describe("The project ID"),
1767
+ taskId: import_zod3.z.string().describe("The task ID"),
1768
+ pullRequestUrl: import_zod3.z.string().describe("Full URL of the created PR (e.g., https://github.com/owner/repo/pull/123)"),
1769
+ pullRequestNumber: import_zod3.z.number().describe("PR number (e.g., 123)")
1770
+ }
1771
+ },
1772
+ async (args) => {
1773
+ assertApiKeyPermission(
1774
+ mockApiKey,
1775
+ ApiKeyPermission.WRITE,
1776
+ "report_pr"
1777
+ );
1778
+ const validated = ReportPRInputSchema.parse(args);
1779
+ try {
1780
+ const result = await apiClient.reportPR(
1781
+ validated.taskId,
1782
+ validated.projectId,
1783
+ validated.pullRequestUrl,
1784
+ validated.pullRequestNumber
1785
+ );
1786
+ return {
1787
+ content: [
1788
+ {
1789
+ type: "text",
1790
+ text: JSON.stringify(result, null, 2)
1791
+ }
1792
+ ]
1793
+ };
1794
+ } catch (error) {
1795
+ return handleApiError(error);
1796
+ }
1797
+ }
1798
+ );
1606
1799
  server.registerTool(
1607
1800
  "archive_task",
1608
1801
  {
@@ -1710,7 +1903,7 @@ async function createMCPServer() {
1710
1903
  server.registerTool(
1711
1904
  "create_task",
1712
1905
  {
1713
- description: "Create task with title, description, acceptance criteria. Starts in BACKLOG. Priority: LOW/MEDIUM/HIGH/CRITICAL.",
1906
+ description: "Create task with title, description, acceptance criteria. Starts in DRAFT. Priority: LOW/MEDIUM/HIGH/CRITICAL.",
1714
1907
  inputSchema: {
1715
1908
  projectId: import_zod3.z.string().describe("The project ID to create the task in"),
1716
1909
  epicId: import_zod3.z.string().nullable().optional().describe("Optional epic ID to associate the task with"),
@@ -1827,6 +2020,119 @@ async function createMCPServer() {
1827
2020
  }
1828
2021
  }
1829
2022
  );
2023
+ server.registerTool(
2024
+ "verify_task",
2025
+ {
2026
+ description: "Verify a DRAFT task and move it to TODO state. Requires task to pass programmatic validation (title 10+ chars, description 50+ chars, each criterion 20+ chars). If approved=false, stores feedback with NEEDS_REVISION status.",
2027
+ inputSchema: {
2028
+ projectId: import_zod3.z.string().describe("The project ID"),
2029
+ taskId: import_zod3.z.string().describe("The task ID to verify"),
2030
+ approved: import_zod3.z.boolean().describe("Whether to approve the task"),
2031
+ feedback: import_zod3.z.string().optional().describe("Feedback for the task (required if not approved)")
2032
+ }
2033
+ },
2034
+ async (args) => {
2035
+ assertApiKeyPermission(mockApiKey, ApiKeyPermission.WRITE, "verify_task");
2036
+ const validated = VerifyTaskInputSchema.parse(args);
2037
+ try {
2038
+ const result = await apiClient.verifyTask(
2039
+ validated.taskId,
2040
+ validated.projectId,
2041
+ validated.approved,
2042
+ validated.feedback
2043
+ );
2044
+ return {
2045
+ content: [
2046
+ {
2047
+ type: "text",
2048
+ text: JSON.stringify(result, null, 2)
2049
+ }
2050
+ ]
2051
+ };
2052
+ } catch (error) {
2053
+ return handleApiError(error);
2054
+ }
2055
+ }
2056
+ );
2057
+ server.registerTool(
2058
+ "get_task_prompt",
2059
+ {
2060
+ description: "Get state-appropriate prompt for a task. Returns verify prompt for DRAFT, assignment prompt for TODO, or continue prompt for IN_PROGRESS tasks.",
2061
+ inputSchema: {
2062
+ projectId: import_zod3.z.string().describe("The project ID"),
2063
+ taskId: import_zod3.z.string().describe("The task ID")
2064
+ }
2065
+ },
2066
+ async (args) => {
2067
+ assertApiKeyPermission(
2068
+ mockApiKey,
2069
+ ApiKeyPermission.READ,
2070
+ "get_task_prompt"
2071
+ );
2072
+ const validated = GetTaskPromptInputSchema.parse(args);
2073
+ try {
2074
+ const result = await apiClient.getTaskPrompt(
2075
+ validated.taskId,
2076
+ validated.projectId
2077
+ );
2078
+ return {
2079
+ content: [
2080
+ {
2081
+ type: "text",
2082
+ text: JSON.stringify(result, null, 2)
2083
+ }
2084
+ ]
2085
+ };
2086
+ } catch (error) {
2087
+ return handleApiError(error);
2088
+ }
2089
+ }
2090
+ );
2091
+ server.registerTool(
2092
+ "update_task",
2093
+ {
2094
+ description: "Update task details (title, description, priority, acceptanceCriteria). Only works for DRAFT and TODO states. If task is in TODO state, it reverts to DRAFT and requires re-verification.",
2095
+ inputSchema: {
2096
+ projectId: import_zod3.z.string().describe("The project ID"),
2097
+ taskId: import_zod3.z.string().describe("The task ID to update"),
2098
+ title: import_zod3.z.string().optional().describe("New task title"),
2099
+ description: import_zod3.z.string().optional().describe("New task description"),
2100
+ priority: import_zod3.z.nativeEnum(TaskPriority).optional().describe("New task priority"),
2101
+ acceptanceCriteria: import_zod3.z.array(
2102
+ import_zod3.z.object({
2103
+ id: import_zod3.z.string().optional().describe("Existing criterion ID (for updates)"),
2104
+ description: import_zod3.z.string().describe("Criterion description")
2105
+ })
2106
+ ).optional().describe("New acceptance criteria (replaces existing)")
2107
+ }
2108
+ },
2109
+ async (args) => {
2110
+ assertApiKeyPermission(mockApiKey, ApiKeyPermission.WRITE, "update_task");
2111
+ const validated = UpdateTaskMCPInputSchema.parse(args);
2112
+ try {
2113
+ const result = await apiClient.updateTask(
2114
+ validated.taskId,
2115
+ validated.projectId,
2116
+ {
2117
+ title: validated.title,
2118
+ description: validated.description,
2119
+ priority: validated.priority,
2120
+ acceptanceCriteria: validated.acceptanceCriteria
2121
+ }
2122
+ );
2123
+ return {
2124
+ content: [
2125
+ {
2126
+ type: "text",
2127
+ text: JSON.stringify(result, null, 2)
2128
+ }
2129
+ ]
2130
+ };
2131
+ } catch (error) {
2132
+ return handleApiError(error);
2133
+ }
2134
+ }
2135
+ );
1830
2136
  server.registerTool(
1831
2137
  "get_version",
1832
2138
  {