@chorus-aidlc/chorus-openclaw-plugin 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,14 @@
1
1
  import type { ChorusMcpClient } from "../mcp-client.js";
2
2
 
3
+ function toolResult(result: unknown) {
4
+ return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], details: result };
5
+ }
6
+
3
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
8
  export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
5
9
  api.registerTool({
6
10
  name: "chorus_checkin",
11
+ label: "Check-in",
7
12
  description: "Agent check-in. Returns persona, roles, and pending assignments. Recommended at session start.",
8
13
  parameters: {
9
14
  type: "object",
@@ -12,12 +17,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
12
17
  },
13
18
  async execute() {
14
19
  const result = await mcpClient.callTool("chorus_checkin", {});
15
- return JSON.stringify(result, null, 2);
20
+ return toolResult(result);
16
21
  },
17
22
  });
18
23
 
19
24
  api.registerTool({
20
25
  name: "chorus_get_notifications",
26
+ label: "Get Notifications",
21
27
  description: "Get notifications. By default fetches unread and auto-marks them as read.",
22
28
  parameters: {
23
29
  type: "object",
@@ -32,12 +38,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
32
38
  if (status) args.status = status;
33
39
  if (autoMarkRead !== undefined) args.autoMarkRead = autoMarkRead;
34
40
  const result = await mcpClient.callTool("chorus_get_notifications", args);
35
- return JSON.stringify(result, null, 2);
41
+ return toolResult(result);
36
42
  },
37
43
  });
38
44
 
39
45
  api.registerTool({
40
46
  name: "chorus_get_project",
47
+ label: "Get Project",
41
48
  description: "Get project details and context",
42
49
  parameters: {
43
50
  type: "object",
@@ -49,12 +56,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
49
56
  },
50
57
  async execute(_id: string, { projectUuid }: { projectUuid: string }) {
51
58
  const result = await mcpClient.callTool("chorus_get_project", { projectUuid });
52
- return JSON.stringify(result, null, 2);
59
+ return toolResult(result);
53
60
  },
54
61
  });
55
62
 
56
63
  api.registerTool({
57
64
  name: "chorus_get_task",
65
+ label: "Get Task",
58
66
  description: "Get detailed information and context for a single task",
59
67
  parameters: {
60
68
  type: "object",
@@ -66,12 +74,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
66
74
  },
67
75
  async execute(_id: string, { taskUuid }: { taskUuid: string }) {
68
76
  const result = await mcpClient.callTool("chorus_get_task", { taskUuid });
69
- return JSON.stringify(result, null, 2);
77
+ return toolResult(result);
70
78
  },
71
79
  });
72
80
 
73
81
  api.registerTool({
74
82
  name: "chorus_get_idea",
83
+ label: "Get Idea",
75
84
  description: "Get detailed information for a single idea",
76
85
  parameters: {
77
86
  type: "object",
@@ -83,12 +92,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
83
92
  },
84
93
  async execute(_id: string, { ideaUuid }: { ideaUuid: string }) {
85
94
  const result = await mcpClient.callTool("chorus_get_idea", { ideaUuid });
86
- return JSON.stringify(result, null, 2);
95
+ return toolResult(result);
87
96
  },
88
97
  });
89
98
 
90
99
  api.registerTool({
91
100
  name: "chorus_get_available_tasks",
101
+ label: "Available Tasks",
92
102
  description: "Get tasks available to claim in a project (status=open). Optionally filter by proposal UUIDs.",
93
103
  parameters: {
94
104
  type: "object",
@@ -103,12 +113,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
103
113
  const args: Record<string, unknown> = { projectUuid };
104
114
  if (proposalUuids && proposalUuids.length > 0) args.proposalUuids = proposalUuids;
105
115
  const result = await mcpClient.callTool("chorus_get_available_tasks", args);
106
- return JSON.stringify(result, null, 2);
116
+ return toolResult(result);
107
117
  },
108
118
  });
109
119
 
110
120
  api.registerTool({
111
121
  name: "chorus_get_available_ideas",
122
+ label: "Available Ideas",
112
123
  description: "Get ideas available to claim in a project (status=open)",
113
124
  parameters: {
114
125
  type: "object",
@@ -120,7 +131,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
120
131
  },
121
132
  async execute(_id: string, { projectUuid }: { projectUuid: string }) {
122
133
  const result = await mcpClient.callTool("chorus_get_available_ideas", { projectUuid });
123
- return JSON.stringify(result, null, 2);
134
+ return toolResult(result);
124
135
  },
125
136
  });
126
137
 
@@ -128,6 +139,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
128
139
 
129
140
  api.registerTool({
130
141
  name: "chorus_list_projects",
142
+ label: "List Projects",
131
143
  description: "List all projects for the current company. Returns projects with counts of ideas, documents, tasks, and proposals.",
132
144
  parameters: {
133
145
  type: "object",
@@ -142,12 +154,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
142
154
  if (page !== undefined) args.page = page;
143
155
  if (pageSize !== undefined) args.pageSize = pageSize;
144
156
  const result = await mcpClient.callTool("chorus_list_projects", args);
145
- return JSON.stringify(result, null, 2);
157
+ return toolResult(result);
146
158
  },
147
159
  });
148
160
 
149
161
  api.registerTool({
150
162
  name: "chorus_list_tasks",
163
+ label: "List Tasks",
151
164
  description: "List tasks for a project. Can filter by status, priority, and proposal UUIDs.",
152
165
  parameters: {
153
166
  type: "object",
@@ -170,12 +183,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
170
183
  if (page !== undefined) args.page = page;
171
184
  if (pageSize !== undefined) args.pageSize = pageSize;
172
185
  const result = await mcpClient.callTool("chorus_list_tasks", args);
173
- return JSON.stringify(result, null, 2);
186
+ return toolResult(result);
174
187
  },
175
188
  });
176
189
 
177
190
  api.registerTool({
178
191
  name: "chorus_get_ideas",
192
+ label: "List Ideas",
179
193
  description: "List ideas for a project. Can filter by status.",
180
194
  parameters: {
181
195
  type: "object",
@@ -194,12 +208,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
194
208
  if (page !== undefined) args.page = page;
195
209
  if (pageSize !== undefined) args.pageSize = pageSize;
196
210
  const result = await mcpClient.callTool("chorus_get_ideas", args);
197
- return JSON.stringify(result, null, 2);
211
+ return toolResult(result);
198
212
  },
199
213
  });
200
214
 
201
215
  api.registerTool({
202
216
  name: "chorus_get_proposals",
217
+ label: "List Proposals",
203
218
  description: "List proposals for a project. Can filter by status.",
204
219
  parameters: {
205
220
  type: "object",
@@ -218,12 +233,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
218
233
  if (page !== undefined) args.page = page;
219
234
  if (pageSize !== undefined) args.pageSize = pageSize;
220
235
  const result = await mcpClient.callTool("chorus_get_proposals", args);
221
- return JSON.stringify(result, null, 2);
236
+ return toolResult(result);
222
237
  },
223
238
  });
224
239
 
225
240
  api.registerTool({
226
241
  name: "chorus_get_documents",
242
+ label: "List Documents",
227
243
  description: "List documents for a project. Can filter by type.",
228
244
  parameters: {
229
245
  type: "object",
@@ -242,12 +258,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
242
258
  if (page !== undefined) args.page = page;
243
259
  if (pageSize !== undefined) args.pageSize = pageSize;
244
260
  const result = await mcpClient.callTool("chorus_get_documents", args);
245
- return JSON.stringify(result, null, 2);
261
+ return toolResult(result);
246
262
  },
247
263
  });
248
264
 
249
265
  api.registerTool({
250
266
  name: "chorus_get_document",
267
+ label: "Get Document",
251
268
  description: "Get the detailed content of a single document.",
252
269
  parameters: {
253
270
  type: "object",
@@ -259,12 +276,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
259
276
  },
260
277
  async execute(_id: string, { documentUuid }: { documentUuid: string }) {
261
278
  const result = await mcpClient.callTool("chorus_get_document", { documentUuid });
262
- return JSON.stringify(result, null, 2);
279
+ return toolResult(result);
263
280
  },
264
281
  });
265
282
 
266
283
  api.registerTool({
267
284
  name: "chorus_get_unblocked_tasks",
285
+ label: "Unblocked Tasks",
268
286
  description: "Get tasks that are ready to start — status is open/assigned and all dependencies are resolved (done/closed). Optionally filter by proposal UUIDs. Note: to_verify is NOT considered resolved.",
269
287
  parameters: {
270
288
  type: "object",
@@ -279,12 +297,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
279
297
  const args: Record<string, unknown> = { projectUuid };
280
298
  if (proposalUuids && proposalUuids.length > 0) args.proposalUuids = proposalUuids;
281
299
  const result = await mcpClient.callTool("chorus_get_unblocked_tasks", args);
282
- return JSON.stringify(result, null, 2);
300
+ return toolResult(result);
283
301
  },
284
302
  });
285
303
 
286
304
  api.registerTool({
287
305
  name: "chorus_get_activity",
306
+ label: "Activity Stream",
288
307
  description: "Get the activity stream for a project. Shows all actions taken by agents and users.",
289
308
  parameters: {
290
309
  type: "object",
@@ -301,12 +320,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
301
320
  if (page !== undefined) args.page = page;
302
321
  if (pageSize !== undefined) args.pageSize = pageSize;
303
322
  const result = await mcpClient.callTool("chorus_get_activity", args);
304
- return JSON.stringify(result, null, 2);
323
+ return toolResult(result);
305
324
  },
306
325
  });
307
326
 
308
327
  api.registerTool({
309
328
  name: "chorus_get_comments",
329
+ label: "Get Comments",
310
330
  description: "Get comments for an Idea, Proposal, Task, or Document. Useful for understanding context, decisions, and feedback.",
311
331
  parameters: {
312
332
  type: "object",
@@ -324,12 +344,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
324
344
  if (page !== undefined) args.page = page;
325
345
  if (pageSize !== undefined) args.pageSize = pageSize;
326
346
  const result = await mcpClient.callTool("chorus_get_comments", args);
327
- return JSON.stringify(result, null, 2);
347
+ return toolResult(result);
328
348
  },
329
349
  });
330
350
 
331
351
  api.registerTool({
332
352
  name: "chorus_get_elaboration",
353
+ label: "Get Elaboration",
333
354
  description: "Get the full elaboration state for an Idea, including all rounds, questions, answers, and progress summary.",
334
355
  parameters: {
335
356
  type: "object",
@@ -341,12 +362,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
341
362
  },
342
363
  async execute(_id: string, { ideaUuid }: { ideaUuid: string }) {
343
364
  const result = await mcpClient.callTool("chorus_get_elaboration", { ideaUuid });
344
- return JSON.stringify(result, null, 2);
365
+ return toolResult(result);
345
366
  },
346
367
  });
347
368
 
348
369
  api.registerTool({
349
370
  name: "chorus_get_my_assignments",
371
+ label: "My Assignments",
350
372
  description: "Get all Ideas and Tasks currently assigned to you.",
351
373
  parameters: {
352
374
  type: "object",
@@ -355,7 +377,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
355
377
  },
356
378
  async execute() {
357
379
  const result = await mcpClient.callTool("chorus_get_my_assignments", {});
358
- return JSON.stringify(result, null, 2);
380
+ return toolResult(result);
359
381
  },
360
382
  });
361
383
 
@@ -363,6 +385,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
363
385
 
364
386
  api.registerTool({
365
387
  name: "chorus_get_project_groups",
388
+ label: "List Groups",
366
389
  description: "List all project groups. Returns groups with project counts and completion rates.",
367
390
  parameters: {
368
391
  type: "object",
@@ -371,12 +394,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
371
394
  },
372
395
  async execute() {
373
396
  const result = await mcpClient.callTool("chorus_get_project_groups", {});
374
- return JSON.stringify(result, null, 2);
397
+ return toolResult(result);
375
398
  },
376
399
  });
377
400
 
378
401
  api.registerTool({
379
402
  name: "chorus_get_project_group",
403
+ label: "Get Group",
380
404
  description: "Get a single project group with its projects and stats.",
381
405
  parameters: {
382
406
  type: "object",
@@ -388,7 +412,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
388
412
  },
389
413
  async execute(_id: string, { groupUuid }: { groupUuid: string }) {
390
414
  const result = await mcpClient.callTool("chorus_get_project_group", { groupUuid });
391
- return JSON.stringify(result, null, 2);
415
+ return toolResult(result);
392
416
  },
393
417
  });
394
418
 
@@ -396,6 +420,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
396
420
 
397
421
  api.registerTool({
398
422
  name: "chorus_add_comment",
423
+ label: "Add Comment",
399
424
  description: "Add a comment to an Idea, Proposal, Task, or Document",
400
425
  parameters: {
401
426
  type: "object",
@@ -409,12 +434,13 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
409
434
  },
410
435
  async execute(_id: string, { targetType, targetUuid, content }: { targetType: string; targetUuid: string; content: string }) {
411
436
  const result = await mcpClient.callTool("chorus_add_comment", { targetType, targetUuid, content });
412
- return JSON.stringify(result, null, 2);
437
+ return toolResult(result);
413
438
  },
414
439
  });
415
440
 
416
441
  api.registerTool({
417
442
  name: "chorus_search_mentionables",
443
+ label: "Search Mentionables",
418
444
  description: "Search for users and agents that can be @mentioned. Returns name, type, and UUID. Use the UUID to write mentions as @[Name](type:uuid) in comment text.",
419
445
  parameters: {
420
446
  type: "object",
@@ -429,12 +455,102 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
429
455
  const args: Record<string, unknown> = { query };
430
456
  if (limit !== undefined) args.limit = limit;
431
457
  const result = await mcpClient.callTool("chorus_search_mentionables", args);
432
- return JSON.stringify(result, null, 2);
458
+ return toolResult(result);
459
+ },
460
+ });
461
+
462
+ // ===== Task Creation & Editing (available to all roles) =====
463
+
464
+ api.registerTool({
465
+ name: "chorus_create_tasks",
466
+ label: "Create Tasks",
467
+ description:
468
+ "Batch create tasks in a project. Two modes:\n\n" +
469
+ "**Quick Task** (skip Idea→Proposal): omit proposalUuid. Ideal for bug fixes, small features, post-delivery patches.\n" +
470
+ "Flow: create → chorus_claim_task → execute → chorus_report_work → chorus_submit_for_verify → done.\n\n" +
471
+ "**Proposal-linked** (traditional AI-DLC): pass proposalUuid to associate with an approved proposal.\n\n" +
472
+ "Supports batch creation with intra-batch dependencies (draftUuid + dependsOnDraftUuids) and dependencies on existing tasks (dependsOnTaskUuids).",
473
+ parameters: {
474
+ type: "object",
475
+ properties: {
476
+ projectUuid: { type: "string", description: "Project UUID" },
477
+ proposalUuid: { type: "string", description: "Associated Proposal UUID (optional — omit for Quick Task mode)" },
478
+ tasks: {
479
+ type: "array",
480
+ description: "Task list. Each: { title, description?, priority?, storyPoints?, acceptanceCriteriaItems?, draftUuid?, dependsOnDraftUuids?, dependsOnTaskUuids? }",
481
+ items: {
482
+ type: "object",
483
+ properties: {
484
+ title: { type: "string", description: "Task title" },
485
+ description: { type: "string", description: "Task description" },
486
+ priority: { type: "string", description: 'Priority: "low", "medium", or "high"' },
487
+ storyPoints: { type: "number", description: "Effort estimate in agent hours" },
488
+ acceptanceCriteriaItems: { type: "array", description: "Structured acceptance criteria: [{ description, required? }]", items: { type: "object", properties: { description: { type: "string" }, required: { type: "boolean" } }, required: ["description"] } },
489
+ draftUuid: { type: "string", description: "Temporary UUID for intra-batch dependency references" },
490
+ dependsOnDraftUuids: { type: "array", description: "Dependent draftUuid list within this batch", items: { type: "string" } },
491
+ dependsOnTaskUuids: { type: "array", description: "Dependent existing Task UUID list", items: { type: "string" } },
492
+ },
493
+ required: ["title"],
494
+ },
495
+ },
496
+ },
497
+ required: ["projectUuid", "tasks"],
498
+ additionalProperties: false,
499
+ },
500
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
501
+ async execute(_id: string, { projectUuid, proposalUuid, tasks }: any) {
502
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
503
+ const args: Record<string, any> = { projectUuid, tasks };
504
+ if (proposalUuid !== undefined) args.proposalUuid = proposalUuid;
505
+ const result = await mcpClient.callTool("chorus_create_tasks", args);
506
+ return toolResult(result);
507
+ },
508
+ });
509
+
510
+ api.registerTool({
511
+ name: "chorus_update_task",
512
+ label: "Update Task",
513
+ description:
514
+ "Update a task — edit fields, manage dependencies, or change status.\n\n" +
515
+ "**Field editing** (any role): title, description, priority, storyPoints, addDependsOn/removeDependsOn (incremental dependency management).\n\n" +
516
+ "**Status update** (assignee only): in_progress (requires all dependencies resolved), to_verify.\n\n" +
517
+ "For Quick Tasks: create → claim → edit details → execute → verify → done.",
518
+ parameters: {
519
+ type: "object",
520
+ properties: {
521
+ taskUuid: { type: "string", description: "Task UUID" },
522
+ status: { type: "string", description: "New status: in_progress | to_verify (assignee only)" },
523
+ sessionUuid: { type: "string", description: "Session UUID for sub-agent identification" },
524
+ title: { type: "string", description: "New task title" },
525
+ description: { type: "string", description: "New task description (supports @mentions)" },
526
+ priority: { type: "string", description: 'New priority: "low", "medium", or "high"' },
527
+ storyPoints: { type: "number", description: "New effort estimate (agent hours)" },
528
+ addDependsOn: { type: "array", description: "Task UUIDs to add as dependencies", items: { type: "string" } },
529
+ removeDependsOn: { type: "array", description: "Task UUIDs to remove from dependencies", items: { type: "string" } },
530
+ },
531
+ required: ["taskUuid"],
532
+ additionalProperties: false,
533
+ },
534
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
535
+ async execute(_id: string, { taskUuid, status, sessionUuid, title, description, priority, storyPoints, addDependsOn, removeDependsOn }: any) {
536
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
537
+ const args: Record<string, any> = { taskUuid };
538
+ if (status !== undefined) args.status = status;
539
+ if (sessionUuid !== undefined) args.sessionUuid = sessionUuid;
540
+ if (title !== undefined) args.title = title;
541
+ if (description !== undefined) args.description = description;
542
+ if (priority !== undefined) args.priority = priority;
543
+ if (storyPoints !== undefined) args.storyPoints = storyPoints;
544
+ if (addDependsOn !== undefined) args.addDependsOn = addDependsOn;
545
+ if (removeDependsOn !== undefined) args.removeDependsOn = removeDependsOn;
546
+ const result = await mcpClient.callTool("chorus_update_task", args);
547
+ return toolResult(result);
433
548
  },
434
549
  });
435
550
 
436
551
  api.registerTool({
437
552
  name: "chorus_search",
553
+ label: "Search",
438
554
  description: "Search across tasks, ideas, proposals, documents, projects, and project groups.",
439
555
  parameters: {
440
556
  type: "object",
@@ -453,7 +569,7 @@ export function registerCommonTools(api: any, mcpClient: ChorusMcpClient) {
453
569
  if (scopeUuid) args.scopeUuid = scopeUuid;
454
570
  if (entityTypes) args.entityTypes = entityTypes;
455
571
  const result = await mcpClient.callTool("chorus_search", args);
456
- return JSON.stringify(result, null, 2);
572
+ return toolResult(result);
457
573
  },
458
574
  });
459
575
  }
@@ -1,9 +1,14 @@
1
1
  import type { ChorusMcpClient } from "../mcp-client.js";
2
2
 
3
+ function toolResult(result: unknown) {
4
+ return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], details: result };
5
+ }
6
+
3
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
8
  export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
5
9
  api.registerTool({
6
10
  name: "chorus_claim_task",
11
+ label: "Claim Task",
7
12
  description: "Claim an open task (open -> assigned)",
8
13
  parameters: {
9
14
  type: "object",
@@ -15,33 +20,15 @@ export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
15
20
  },
16
21
  async execute(_id: string, { taskUuid }: { taskUuid: string }) {
17
22
  const result = await mcpClient.callTool("chorus_claim_task", { taskUuid });
18
- return JSON.stringify(result, null, 2);
23
+ return toolResult(result);
19
24
  },
20
25
  });
21
26
 
22
- api.registerTool({
23
- name: "chorus_update_task",
24
- description: "Update task status (only the assignee can operate). Moving to in_progress requires all dependsOn tasks to be done or closed — otherwise the request is rejected with blocker details. Use chorus_get_unblocked_tasks to find tasks ready to start.",
25
- parameters: {
26
- type: "object",
27
- properties: {
28
- taskUuid: { type: "string", description: "Task UUID" },
29
- status: { type: "string", description: "New status: in_progress | to_verify" },
30
- sessionUuid: { type: "string", description: "Session UUID for sub-agent identification" },
31
- },
32
- required: ["taskUuid", "status"],
33
- additionalProperties: false,
34
- },
35
- async execute(_id: string, { taskUuid, status, sessionUuid }: { taskUuid: string; status: string; sessionUuid?: string }) {
36
- const args: Record<string, unknown> = { taskUuid, status };
37
- if (sessionUuid) args.sessionUuid = sessionUuid;
38
- const result = await mcpClient.callTool("chorus_update_task", args);
39
- return JSON.stringify(result, null, 2);
40
- },
41
- });
27
+ // chorus_update_task — migrated to common-tools.ts (available to all roles, enhanced with field editing)
42
28
 
43
29
  api.registerTool({
44
30
  name: "chorus_report_work",
31
+ label: "Report Work",
45
32
  description: "Report work progress or completion on a task",
46
33
  parameters: {
47
34
  type: "object",
@@ -59,12 +46,13 @@ export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
59
46
  if (status) args.status = status;
60
47
  if (sessionUuid) args.sessionUuid = sessionUuid;
61
48
  const result = await mcpClient.callTool("chorus_report_work", args);
62
- return JSON.stringify(result, null, 2);
49
+ return toolResult(result);
63
50
  },
64
51
  });
65
52
 
66
53
  api.registerTool({
67
54
  name: "chorus_submit_for_verify",
55
+ label: "Submit for Verify",
68
56
  description: "Submit task for human verification (in_progress -> to_verify)",
69
57
  parameters: {
70
58
  type: "object",
@@ -79,12 +67,13 @@ export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
79
67
  const args: Record<string, unknown> = { taskUuid };
80
68
  if (summary) args.summary = summary;
81
69
  const result = await mcpClient.callTool("chorus_submit_for_verify", args);
82
- return JSON.stringify(result, null, 2);
70
+ return toolResult(result);
83
71
  },
84
72
  });
85
73
 
86
74
  api.registerTool({
87
75
  name: "chorus_report_criteria_self_check",
76
+ label: "Self-Check AC",
88
77
  description: "Report self-check results on acceptance criteria for a task you're working on. For required criteria, keep working until all pass. Only mark optional criteria as failed if out of scope.",
89
78
  parameters: {
90
79
  type: "object",
@@ -109,7 +98,7 @@ export function registerDevTools(api: any, mcpClient: ChorusMcpClient) {
109
98
  },
110
99
  async execute(_id: string, { taskUuid, criteria }: { taskUuid: string; criteria: Array<{ uuid: string; devStatus: string; devEvidence?: string }> }) {
111
100
  const result = await mcpClient.callTool("chorus_report_criteria_self_check", { taskUuid, criteria });
112
- return JSON.stringify(result, null, 2);
101
+ return toolResult(result);
113
102
  },
114
103
  });
115
104