tododdle-mcp 2.8.0 → 3.0.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.
package/dist/server.js CHANGED
@@ -186,7 +186,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
186
186
  [
187
187
  'archive_project',
188
188
  true,
189
- 'Archive a project without deleting its tasks. Requires explicit approval.',
189
+ 'Archive a project without deleting its tickets. Requires explicit approval.',
190
190
  true,
191
191
  ],
192
192
  ['restore_project', false, 'Restore an archived project.', false],
@@ -205,8 +205,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
205
205
  },
206
206
  }, async ({ projectId, expectedUpdatedAt }) => toolResult(await api.put(`/api/external/projects/${projectId}`, { archived, expectedUpdatedAt })));
207
207
  }
208
- server.registerTool('list_plans', {
209
- description: 'List bounded active or archived plans in a project.',
208
+ server.registerTool('list_boards', {
209
+ description: 'List bounded active or archived boards in a project.',
210
210
  inputSchema: z.object({
211
211
  projectId: z.string().min(1),
212
212
  search: z.string().optional(),
@@ -221,8 +221,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
221
221
  openWorldHint: false,
222
222
  },
223
223
  }, async ({ projectId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/plans`, query)));
224
- server.registerTool('get_plan', {
225
- description: 'Get one plan in a project.',
224
+ server.registerTool('get_board', {
225
+ description: 'Get one board in a project.',
226
226
  inputSchema: z.object({ projectId: z.string().min(1), planId: z.string().min(1) }),
227
227
  annotations: {
228
228
  readOnlyHint: true,
@@ -231,8 +231,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
231
231
  openWorldHint: false,
232
232
  },
233
233
  }, async ({ projectId, planId }) => toolResult(await api.get(`/api/external/projects/${projectId}/plans/${planId}`)));
234
- server.registerTool('create_plan', {
235
- description: 'Create a plan in a project.',
234
+ server.registerTool('create_board', {
235
+ description: 'Create a board in a project.',
236
236
  inputSchema: z.object({
237
237
  projectId: z.string().min(1),
238
238
  name: z.string().min(1).max(500),
@@ -248,8 +248,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
248
248
  openWorldHint: false,
249
249
  },
250
250
  }, async ({ projectId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/plans`, body, idempotencyKey)));
251
- server.registerTool('update_plan', {
252
- description: 'Update plan details using optimistic concurrency.',
251
+ server.registerTool('update_board', {
252
+ description: 'Update board details using optimistic concurrency.',
253
253
  inputSchema: z.object({
254
254
  projectId: z.string().min(1),
255
255
  planId: z.string().min(1),
@@ -266,8 +266,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
266
266
  openWorldHint: false,
267
267
  },
268
268
  }, async ({ projectId, planId, ...body }) => toolResult(await api.put(`/api/external/projects/${projectId}/plans/${planId}`, body)));
269
- server.registerTool('move_plan', {
270
- description: 'Reorder a plan within its project using optimistic concurrency.',
269
+ server.registerTool('move_board', {
270
+ description: 'Reorder a board within its project using optimistic concurrency.',
271
271
  inputSchema: z.object({
272
272
  projectId: z.string().min(1),
273
273
  planId: z.string().min(1),
@@ -283,12 +283,12 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
283
283
  }, async ({ projectId, planId, ...body }) => toolResult(await api.put(`/api/external/projects/${projectId}/plans/${planId}`, body)));
284
284
  for (const [name, archived, description, destructiveHint] of [
285
285
  [
286
- 'archive_plan',
286
+ 'archive_board',
287
287
  true,
288
- 'Archive a plan without changing its tasks. Requires explicit approval.',
288
+ 'Archive a board without changing its tickets. Requires explicit approval.',
289
289
  true,
290
290
  ],
291
- ['restore_plan', false, 'Restore an archived plan.', false],
291
+ ['restore_board', false, 'Restore an archived board.', false],
292
292
  ]) {
293
293
  server.registerTool(name, {
294
294
  description,
@@ -308,8 +308,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
308
308
  expectedUpdatedAt,
309
309
  })));
310
310
  }
311
- server.registerTool('list_sections', {
312
- description: 'List bounded sections and entry automations in a plan.',
311
+ server.registerTool('list_lanes', {
312
+ description: 'List bounded lanes and entry automations in a board.',
313
313
  inputSchema: z.object({
314
314
  projectId: z.string().min(1),
315
315
  planId: z.string().min(1),
@@ -325,8 +325,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
325
325
  openWorldHint: false,
326
326
  },
327
327
  }, async ({ projectId, planId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/plans/${planId}/sections`, query)));
328
- server.registerTool('get_section', {
329
- description: 'Get one plan section and its entry automations.',
328
+ server.registerTool('get_lane', {
329
+ description: 'Get one board lane and its entry automations.',
330
330
  inputSchema: z.object({
331
331
  projectId: z.string().min(1),
332
332
  planId: z.string().min(1),
@@ -339,8 +339,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
339
339
  openWorldHint: false,
340
340
  },
341
341
  }, async ({ projectId, planId, sectionId }) => toolResult(await api.get(`/api/external/projects/${projectId}/plans/${planId}/sections/${sectionId}`)));
342
- server.registerTool('create_section', {
343
- description: 'Create a section with optional typed entry automations.',
342
+ server.registerTool('create_lane', {
343
+ description: 'Create a lane with optional typed entry automations.',
344
344
  inputSchema: z.object({
345
345
  projectId: z.string().min(1),
346
346
  planId: z.string().min(1),
@@ -360,8 +360,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
360
360
  openWorldHint: false,
361
361
  },
362
362
  }, async ({ projectId, planId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/plans/${planId}/sections`, body, idempotencyKey)));
363
- server.registerTool('update_section', {
364
- description: 'Update a section and its entry automations using optimistic concurrency.',
363
+ server.registerTool('update_lane', {
364
+ description: 'Update a lane and its entry automations using optimistic concurrency.',
365
365
  inputSchema: z.object({
366
366
  projectId: z.string().min(1),
367
367
  planId: z.string().min(1),
@@ -382,8 +382,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
382
382
  openWorldHint: false,
383
383
  },
384
384
  }, async ({ projectId, planId, sectionId, ...body }) => toolResult(await api.put(`/api/external/projects/${projectId}/plans/${planId}/sections/${sectionId}`, body)));
385
- server.registerTool('move_section', {
386
- description: 'Reorder a section within its plan using optimistic concurrency.',
385
+ server.registerTool('move_lane', {
386
+ description: 'Reorder a lane within its board using optimistic concurrency.',
387
387
  inputSchema: z.object({
388
388
  projectId: z.string().min(1),
389
389
  planId: z.string().min(1),
@@ -400,12 +400,12 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
400
400
  }, async ({ projectId, planId, sectionId, ...body }) => toolResult(await api.put(`/api/external/projects/${projectId}/plans/${planId}/sections/${sectionId}`, body)));
401
401
  for (const [name, archived, description, destructiveHint] of [
402
402
  [
403
- 'archive_section',
403
+ 'archive_lane',
404
404
  true,
405
- 'Archive a section without changing its tasks. Requires explicit approval.',
405
+ 'Archive a lane without changing its tickets. Requires explicit approval.',
406
406
  true,
407
407
  ],
408
- ['restore_section', false, 'Restore an archived section.', false],
408
+ ['restore_lane', false, 'Restore an archived lane.', false],
409
409
  ]) {
410
410
  server.registerTool(name, {
411
411
  description,
@@ -540,7 +540,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
540
540
  },
541
541
  }, async ({ noteId, expectedUpdatedAt }) => toolResult(await api.delete(`/api/external/notes/${noteId}`, { expectedUpdatedAt })));
542
542
  server.registerTool('get_project_context', {
543
- description: 'Get bounded project-plan and section context for task planning.',
543
+ description: 'Get bounded board and lane context for ticket planning.',
544
544
  inputSchema: z.object({ projectId: z.string().min(1) }),
545
545
  annotations: {
546
546
  readOnlyHint: true,
@@ -559,8 +559,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
559
559
  openWorldHint: true,
560
560
  },
561
561
  }, async (input) => toolResult(await uploadDocument(api, options, input)));
562
- server.registerTool('attach_file_to_task', {
563
- description: 'Upload an approved local file or HTTPS URL and attach it to a task in the same project.',
562
+ server.registerTool('attach_file_to_ticket', {
563
+ description: 'Upload an approved local file or HTTPS URL and attach it to a ticket in the same project.',
564
564
  inputSchema: taskUploadInputSchema,
565
565
  annotations: {
566
566
  readOnlyHint: false,
@@ -587,7 +587,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
587
587
  },
588
588
  }, async (input) => toolResult(await api.get('/api/external/work-queue', input)));
589
589
  server.registerTool('list_available_work', {
590
- description: 'List bounded, unblocked, currently unclaimed tasks eligible for an Agent Connection in one project, ordered by priority, due date, and project position.',
590
+ description: 'List bounded, unblocked, currently unclaimed tickets eligible for an Agent Connection in one project, ordered by priority, due date, and project position.',
591
591
  inputSchema: z.object({
592
592
  projectId: z.string().min(1),
593
593
  status: z.enum(['TODO', 'IN_PROGRESS']).default('TODO'),
@@ -603,8 +603,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
603
603
  openWorldHint: false,
604
604
  },
605
605
  }, async (input) => toolResult(await api.get('/api/external/work-queue/available', input)));
606
- server.registerTool('claim_next_task', {
607
- description: 'Atomically claim the highest-ranked eligible task in one project. Reuse a unique stable runId to replay the same live claim safely.',
606
+ server.registerTool('claim_next_ticket', {
607
+ description: 'Atomically claim the highest-ranked eligible ticket in one project. Reuse a unique stable runId to replay the same live claim safely.',
608
608
  inputSchema: z.object({
609
609
  projectId: z.string().min(1),
610
610
  runId: z.string().min(1).max(200),
@@ -622,7 +622,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
622
622
  },
623
623
  }, async (body) => toolResult(await api.post('/api/external/work-queue/available', body)));
624
624
  server.registerTool('get_focus_list', {
625
- description: 'List the current user’s deliberately curated Focus tasks.',
625
+ description: 'List the current user’s deliberately curated Focus tickets.',
626
626
  inputSchema: z.object({
627
627
  projectId: z.string().optional(),
628
628
  status: statusSchema.optional(),
@@ -638,8 +638,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
638
638
  openWorldHint: false,
639
639
  },
640
640
  }, async (input) => toolResult(await api.get('/api/external/focus', input)));
641
- server.registerTool('add_task_to_focus', {
642
- description: 'Add an accessible active task to Focus. Repeated additions are idempotent.',
641
+ server.registerTool('add_ticket_to_focus', {
642
+ description: 'Add an accessible active ticket to Focus. Repeated additions are idempotent.',
643
643
  inputSchema: z.object({
644
644
  taskId: z.string().min(1),
645
645
  bucket: focusBucketSchema.default('NEXT'),
@@ -652,8 +652,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
652
652
  openWorldHint: false,
653
653
  },
654
654
  }, async ({ idempotencyKey, ...body }) => toolResult(await api.post('/api/external/focus', body, idempotencyKey || randomUUID())));
655
- server.registerTool('move_focus_task', {
656
- description: 'Move or reorder a Focus task using optimistic concurrency.',
655
+ server.registerTool('move_focus_ticket', {
656
+ description: 'Move or reorder a Focus ticket using optimistic concurrency.',
657
657
  inputSchema: z.object({
658
658
  taskId: z.string().min(1),
659
659
  bucket: focusBucketSchema,
@@ -667,8 +667,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
667
667
  openWorldHint: false,
668
668
  },
669
669
  }, async ({ taskId, ...body }) => toolResult(await api.patch(`/api/external/focus/${taskId}`, body)));
670
- server.registerTool('remove_task_from_focus', {
671
- description: 'Remove personal Focus metadata without changing the underlying task.',
670
+ server.registerTool('remove_ticket_from_focus', {
671
+ description: 'Remove personal Focus metadata without changing the underlying ticket.',
672
672
  inputSchema: z.object({ taskId: z.string().min(1) }),
673
673
  annotations: {
674
674
  readOnlyHint: false,
@@ -677,8 +677,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
677
677
  openWorldHint: false,
678
678
  },
679
679
  }, async ({ taskId }) => toolResult(await api.delete(`/api/external/focus/${taskId}`, {})));
680
- server.registerTool('list_tasks', {
681
- description: 'List bounded tasks with optional project, plan, section, assignee, status, priority, search, and archive filters.',
680
+ server.registerTool('list_tickets', {
681
+ description: 'List bounded tickets with optional project, board, lane, assignee, status, priority, search, and archive filters. The stable planId and sectionId fields identify the board and lane.',
682
682
  inputSchema: z.object({
683
683
  projectId: z.string().min(1).optional(),
684
684
  planId: z.string().min(1).optional(),
@@ -698,8 +698,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
698
698
  openWorldHint: false,
699
699
  },
700
700
  }, async (input) => toolResult(await api.get('/api/external/tasks', input)));
701
- server.registerTool('get_task', {
702
- description: 'Get complete task context including comments and blocker information.',
701
+ server.registerTool('get_ticket', {
702
+ description: 'Get complete ticket context including comments and blocker information.',
703
703
  inputSchema: z.object({ taskId: z.string().min(1) }),
704
704
  annotations: {
705
705
  readOnlyHint: true,
@@ -708,8 +708,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
708
708
  openWorldHint: false,
709
709
  },
710
710
  }, async ({ taskId }) => toolResult(await api.get(`/api/external/tasks/${taskId}`)));
711
- server.registerTool('claim_task', {
712
- description: 'Claim or refresh a task for the current Agent Connection without changing its human assignee. Reuse a stable runId and refresh before the lease expires.',
711
+ server.registerTool('claim_ticket', {
712
+ description: 'Claim or refresh a ticket for the current Agent Connection without changing its human assignee. Reuse a stable runId and refresh before the lease expires.',
713
713
  inputSchema: z.object({
714
714
  taskId: z.string().min(1),
715
715
  runId: z.string().min(1).max(200),
@@ -723,8 +723,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
723
723
  openWorldHint: false,
724
724
  },
725
725
  }, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}/claim`, body)));
726
- server.registerTool('renew_task_claim', {
727
- description: 'Renew the current Agent Connection lease for a specific task and stable runId before it expires.',
726
+ server.registerTool('renew_ticket_claim', {
727
+ description: 'Renew the current Agent Connection lease for a specific ticket and stable runId before it expires.',
728
728
  inputSchema: z.object({
729
729
  taskId: z.string().min(1),
730
730
  runId: z.string().min(1).max(200),
@@ -738,8 +738,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
738
738
  openWorldHint: false,
739
739
  },
740
740
  }, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}/claim`, body)));
741
- server.registerTool('release_task', {
742
- description: 'Release the current Agent Connection work claim without changing task status or human assignment.',
741
+ server.registerTool('release_ticket', {
742
+ description: 'Release the current Agent Connection work claim without changing ticket status or human assignment.',
743
743
  inputSchema: z.object({
744
744
  taskId: z.string().min(1),
745
745
  runId: z.string().min(1).max(200),
@@ -751,8 +751,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
751
751
  openWorldHint: false,
752
752
  },
753
753
  }, async ({ taskId, ...body }) => toolResult(await api.delete(`/api/external/tasks/${taskId}/claim`, body)));
754
- server.registerTool('create_task', {
755
- description: 'Create a task in an active project plan section.',
754
+ server.registerTool('create_ticket', {
755
+ description: 'Create a ticket in an active board lane. The stable planId and sectionId fields identify the board and lane.',
756
756
  inputSchema: z.object({
757
757
  projectId: z.string().min(1),
758
758
  planId: z.string().min(1),
@@ -774,8 +774,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
774
774
  openWorldHint: false,
775
775
  },
776
776
  }, async ({ idempotencyKey, ...body }) => toolResult(await api.post('/api/external/tasks', body, idempotencyKey || randomUUID())));
777
- server.registerTool('update_task', {
778
- description: 'Update editable task fields. Requires the latest updatedAt value to prevent overwriting newer changes.',
777
+ server.registerTool('update_ticket', {
778
+ description: 'Update editable ticket fields. Requires the latest updatedAt value to prevent overwriting newer changes.',
779
779
  inputSchema: z.object({
780
780
  taskId: z.string().min(1),
781
781
  expectedUpdatedAt: expectedUpdatedAtSchema,
@@ -794,8 +794,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
794
794
  openWorldHint: false,
795
795
  },
796
796
  }, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}`, body)));
797
- server.registerTool('transition_task', {
798
- description: 'Transition a task to a canonical status.',
797
+ server.registerTool('transition_ticket', {
798
+ description: 'Transition a ticket to a canonical status.',
799
799
  inputSchema: z.object({
800
800
  taskId: z.string().min(1),
801
801
  status: statusSchema,
@@ -808,8 +808,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
808
808
  openWorldHint: false,
809
809
  },
810
810
  }, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}`, body)));
811
- server.registerTool('move_task', {
812
- description: 'Move a task to an active section, optionally in another plan in the same project. Preview first because section actions may archive the task.',
811
+ server.registerTool('move_ticket', {
812
+ description: 'Move a ticket to an active lane, optionally on another board in the same project. Preview first because lane actions may archive the ticket.',
813
813
  inputSchema: z.object({
814
814
  taskId: z.string().min(1),
815
815
  planId: z.string().min(1).optional(),
@@ -824,8 +824,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
824
824
  openWorldHint: false,
825
825
  },
826
826
  }, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}/move`, body)));
827
- server.registerTool('preview_task_move', {
828
- description: 'Preview destination section actions, warnings, destructive effects, and hierarchy blockers before moving a task.',
827
+ server.registerTool('preview_ticket_move', {
828
+ description: 'Preview destination lane actions, warnings, destructive effects, and hierarchy blockers before moving a ticket.',
829
829
  inputSchema: z.object({
830
830
  taskId: z.string().min(1),
831
831
  planId: z.string().min(1).optional(),
@@ -839,8 +839,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
839
839
  openWorldHint: false,
840
840
  },
841
841
  }, async ({ taskId, ...body }) => toolResult(await api.post(`/api/external/tasks/${taskId}/move/preview`, body)));
842
- server.registerTool('set_task_blocker', {
843
- description: 'Set or clear the active same-project task blocking this task.',
842
+ server.registerTool('set_ticket_blocker', {
843
+ description: 'Set or clear the active same-project ticket blocking this ticket.',
844
844
  inputSchema: z.object({
845
845
  taskId: z.string().min(1),
846
846
  blockedByTaskId: z.string().nullable(),
@@ -853,8 +853,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
853
853
  openWorldHint: false,
854
854
  },
855
855
  }, async ({ taskId, ...body }) => toolResult(await api.put(`/api/external/tasks/${taskId}`, body)));
856
- server.registerTool('add_task_comment', {
857
- description: 'Add an implementation note, finding, decision, or completion evidence to a task.',
856
+ server.registerTool('add_ticket_comment', {
857
+ description: 'Add an implementation note, finding, decision, or completion evidence to a ticket.',
858
858
  inputSchema: z.object({
859
859
  taskId: z.string().min(1),
860
860
  content: z.string().min(1),
@@ -893,8 +893,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
893
893
  openWorldHint: false,
894
894
  },
895
895
  }, async ({ commentId }) => toolResult(await api.post(`/api/external/agent-inbox/${commentId}/acknowledge`, {})));
896
- server.registerTool('archive_task', {
897
- description: 'Archive a task and clear dependent blocker relationships. Requires explicit human approval.',
896
+ server.registerTool('archive_ticket', {
897
+ description: 'Archive a ticket and clear dependent blocker relationships. Requires explicit human approval.',
898
898
  inputSchema: z.object({
899
899
  taskId: z.string().min(1),
900
900
  expectedUpdatedAt: expectedUpdatedAtSchema,
@@ -939,8 +939,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
939
939
  openWorldHint: false,
940
940
  },
941
941
  }, async ({ projectId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/time-entries`, query)));
942
- server.registerTool('list_task_time', {
943
- description: 'List bounded time entries and totals for one task.',
942
+ server.registerTool('list_ticket_time', {
943
+ description: 'List bounded time entries and totals for one ticket.',
944
944
  inputSchema: z.object({
945
945
  projectId: z.string().min(1),
946
946
  taskId: z.string().min(1),
@@ -954,8 +954,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
954
954
  openWorldHint: false,
955
955
  },
956
956
  }, async ({ projectId, taskId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries`, query)));
957
- server.registerTool('start_task_timer', {
958
- description: 'Start a live timer on an active task. A task allows one active timer; different tasks may run concurrently.',
957
+ server.registerTool('start_ticket_timer', {
958
+ description: 'Start a live timer on an active ticket. A ticket allows one active timer; different tickets may run concurrently.',
959
959
  inputSchema: z.object({
960
960
  projectId: z.string().min(1),
961
961
  taskId: z.string().min(1),
@@ -971,8 +971,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
971
971
  openWorldHint: false,
972
972
  },
973
973
  }, async ({ projectId, taskId, idempotencyKey, startedAt, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries`, { ...body, startedAt: startedAt ?? new Date().toISOString() }, idempotencyKey || randomUUID())));
974
- server.registerTool('stop_task_timer', {
975
- description: 'Stop an active task timer using optimistic concurrency.',
974
+ server.registerTool('stop_ticket_timer', {
975
+ description: 'Stop an active ticket timer using optimistic concurrency.',
976
976
  inputSchema: z.object({
977
977
  projectId: z.string().min(1),
978
978
  taskId: z.string().min(1),
@@ -987,8 +987,8 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
987
987
  openWorldHint: false,
988
988
  },
989
989
  }, async ({ projectId, taskId, timeEntryId, endedAt, expectedUpdatedAt }) => toolResult(await api.post(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries/${timeEntryId}/stop`, { ...(endedAt ? { endedAt } : {}), expectedUpdatedAt })));
990
- server.registerTool('log_task_time', {
991
- description: 'Log a completed historical interval against a task.',
990
+ server.registerTool('log_ticket_time', {
991
+ description: 'Log a completed historical interval against a ticket.',
992
992
  inputSchema: z.object({
993
993
  projectId: z.string().min(1),
994
994
  taskId: z.string().min(1),
@@ -1040,7 +1040,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
1040
1040
  },
1041
1041
  }, async ({ projectId, taskId, timeEntryId, expectedUpdatedAt }) => toolResult(await api.delete(`/api/external/projects/${projectId}/tasks/${taskId}/time-entries/${timeEntryId}`, { expectedUpdatedAt })));
1042
1042
  server.registerTool('get_project_brief', {
1043
- description: 'Read the canonical project brief before planning or changing work.',
1043
+ description: 'Read the canonical project brief before planning or changing tickets.',
1044
1044
  inputSchema: z.object({ projectId: z.string().min(1) }),
1045
1045
  annotations: {
1046
1046
  readOnlyHint: true,
@@ -1067,7 +1067,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
1067
1067
  },
1068
1068
  }, async ({ projectId, ...query }) => toolResult(await api.get(`/api/external/projects/${projectId}/artifacts`, query)));
1069
1069
  server.registerTool('get_project_artifact', {
1070
- description: 'Get complete Markdown, relationships, comments, and task links for one project artifact.',
1070
+ description: 'Get complete Markdown, relationships, comments, and ticket links for one project artifact.',
1071
1071
  inputSchema: z.object({ projectId: z.string().min(1), artifactId: z.string().min(1) }),
1072
1072
  annotations: {
1073
1073
  readOnlyHint: true,
@@ -1158,7 +1158,7 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
1158
1158
  openWorldHint: false,
1159
1159
  },
1160
1160
  }, async ({ projectId, artifactId, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/artifacts/${artifactId}/transition`, body)));
1161
- server.registerTool('link_artifact_task', {
1161
+ server.registerTool('link_artifact_ticket', {
1162
1162
  description: 'Link same-project execution work to the context it implements, informs, evidences, or came from.',
1163
1163
  inputSchema: z.object({
1164
1164
  projectId: z.string().min(1),
@@ -1193,22 +1193,22 @@ export function createToDoddleMcpServer(api, serverOptions = {}) {
1193
1193
  openWorldHint: false,
1194
1194
  },
1195
1195
  }, async ({ projectId, artifactId, idempotencyKey, ...body }) => toolResult(await api.post(`/api/external/projects/${projectId}/artifacts/${artifactId}/comments`, body, idempotencyKey || randomUUID())));
1196
- server.registerResource('task', new ResourceTemplate('tododdle://tasks/{taskId}', { list: undefined }), {
1197
- title: 'ToDoddle task',
1198
- description: 'Complete task context by ID.',
1196
+ server.registerResource('ticket', new ResourceTemplate('tododdle://tickets/{ticketId}', { list: undefined }), {
1197
+ title: 'ToDoddle ticket',
1198
+ description: 'Complete ticket context by ID.',
1199
1199
  mimeType: 'application/json',
1200
1200
  }, async (uri, variables) => ({
1201
1201
  contents: [
1202
1202
  {
1203
1203
  uri: uri.href,
1204
1204
  mimeType: 'application/json',
1205
- text: JSON.stringify(await api.get(`/api/external/tasks/${String(variables.taskId)}`), null, 2),
1205
+ text: JSON.stringify(await api.get(`/api/external/tasks/${String(variables.ticketId)}`), null, 2),
1206
1206
  },
1207
1207
  ],
1208
1208
  }));
1209
1209
  server.registerResource('project', new ResourceTemplate('tododdle://projects/{projectId}', { list: undefined }), {
1210
1210
  title: 'ToDoddle project context',
1211
- description: 'Bounded project-plan and section context by project ID.',
1211
+ description: 'Bounded project board and lane context by project ID.',
1212
1212
  mimeType: 'application/json',
1213
1213
  }, async (uri, variables) => ({
1214
1214
  contents: [