@shortcut/mcp 0.10.1 → 0.10.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/index.js +219 -93
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -53,11 +53,21 @@ var ShortcutClientWrapper = class {
|
|
|
53
53
|
userCache;
|
|
54
54
|
teamCache;
|
|
55
55
|
workflowCache;
|
|
56
|
+
customFieldCache;
|
|
56
57
|
constructor(client$1) {
|
|
57
58
|
this.client = client$1;
|
|
58
59
|
this.userCache = new Cache();
|
|
59
60
|
this.teamCache = new Cache();
|
|
60
61
|
this.workflowCache = new Cache();
|
|
62
|
+
this.customFieldCache = new Cache();
|
|
63
|
+
}
|
|
64
|
+
getNextPageToken(next) {
|
|
65
|
+
let next_page_token = null;
|
|
66
|
+
if (next) try {
|
|
67
|
+
const [, t] = /next=(.+)(?:&|$)/.exec(next) || [];
|
|
68
|
+
if (t) next_page_token = t;
|
|
69
|
+
} catch {}
|
|
70
|
+
return next_page_token;
|
|
61
71
|
}
|
|
62
72
|
async loadMembers() {
|
|
63
73
|
if (this.userCache.isStale) {
|
|
@@ -80,6 +90,13 @@ var ShortcutClientWrapper = class {
|
|
|
80
90
|
if (workflows) this.workflowCache.setMany(workflows.map((workflow) => [workflow.id, workflow]));
|
|
81
91
|
}
|
|
82
92
|
}
|
|
93
|
+
async loadCustomFields() {
|
|
94
|
+
if (this.customFieldCache.isStale) {
|
|
95
|
+
const response = await this.client.listCustomFields();
|
|
96
|
+
const customFields = response?.data ?? null;
|
|
97
|
+
if (customFields) this.customFieldCache.setMany(customFields.map((customField) => [customField.id, customField]));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
83
100
|
async getCurrentUser() {
|
|
84
101
|
if (this.currentUser) return this.currentUser;
|
|
85
102
|
const response = await this.client.getCurrentMemberInfo();
|
|
@@ -172,38 +189,46 @@ var ShortcutClientWrapper = class {
|
|
|
172
189
|
if (!milestone) return null;
|
|
173
190
|
return milestone;
|
|
174
191
|
}
|
|
175
|
-
async searchStories(query) {
|
|
192
|
+
async searchStories(query, nextToken) {
|
|
176
193
|
const response = await this.client.searchStories({
|
|
177
194
|
query,
|
|
178
195
|
page_size: 25,
|
|
179
|
-
detail: "full"
|
|
196
|
+
detail: "full",
|
|
197
|
+
next: nextToken
|
|
180
198
|
});
|
|
181
199
|
const stories = response?.data?.data;
|
|
182
200
|
const total = response?.data?.total;
|
|
201
|
+
const next = response?.data?.next;
|
|
183
202
|
if (!stories) return {
|
|
184
203
|
stories: null,
|
|
185
|
-
total: null
|
|
204
|
+
total: null,
|
|
205
|
+
next_page_token: null
|
|
186
206
|
};
|
|
187
207
|
return {
|
|
188
208
|
stories,
|
|
189
|
-
total
|
|
209
|
+
total,
|
|
210
|
+
next_page_token: this.getNextPageToken(next)
|
|
190
211
|
};
|
|
191
212
|
}
|
|
192
|
-
async searchIterations(query) {
|
|
213
|
+
async searchIterations(query, nextToken) {
|
|
193
214
|
const response = await this.client.searchIterations({
|
|
194
215
|
query,
|
|
195
216
|
page_size: 25,
|
|
196
|
-
detail: "full"
|
|
217
|
+
detail: "full",
|
|
218
|
+
next: nextToken
|
|
197
219
|
});
|
|
198
220
|
const iterations = response?.data?.data;
|
|
199
221
|
const total = response?.data?.total;
|
|
222
|
+
const next = response?.data?.next;
|
|
200
223
|
if (!iterations) return {
|
|
201
224
|
iterations: null,
|
|
202
|
-
total: null
|
|
225
|
+
total: null,
|
|
226
|
+
next_page_token: null
|
|
203
227
|
};
|
|
204
228
|
return {
|
|
205
229
|
iterations,
|
|
206
|
-
total
|
|
230
|
+
total,
|
|
231
|
+
next_page_token: this.getNextPageToken(next)
|
|
207
232
|
};
|
|
208
233
|
}
|
|
209
234
|
async getActiveIteration(teamIds) {
|
|
@@ -250,38 +275,46 @@ var ShortcutClientWrapper = class {
|
|
|
250
275
|
}, /* @__PURE__ */ new Map());
|
|
251
276
|
return upcomingIterationByTeam;
|
|
252
277
|
}
|
|
253
|
-
async searchEpics(query) {
|
|
278
|
+
async searchEpics(query, nextToken) {
|
|
254
279
|
const response = await this.client.searchEpics({
|
|
255
280
|
query,
|
|
256
281
|
page_size: 25,
|
|
257
|
-
detail: "full"
|
|
282
|
+
detail: "full",
|
|
283
|
+
next: nextToken
|
|
258
284
|
});
|
|
259
285
|
const epics = response?.data?.data;
|
|
260
286
|
const total = response?.data?.total;
|
|
287
|
+
const next = response?.data?.next;
|
|
261
288
|
if (!epics) return {
|
|
262
289
|
epics: null,
|
|
263
|
-
total: null
|
|
290
|
+
total: null,
|
|
291
|
+
next_page_token: null
|
|
264
292
|
};
|
|
265
293
|
return {
|
|
266
294
|
epics,
|
|
267
|
-
total
|
|
295
|
+
total,
|
|
296
|
+
next_page_token: this.getNextPageToken(next)
|
|
268
297
|
};
|
|
269
298
|
}
|
|
270
|
-
async searchMilestones(query) {
|
|
299
|
+
async searchMilestones(query, nextToken) {
|
|
271
300
|
const response = await this.client.searchMilestones({
|
|
272
301
|
query,
|
|
273
302
|
page_size: 25,
|
|
274
|
-
detail: "full"
|
|
303
|
+
detail: "full",
|
|
304
|
+
next: nextToken
|
|
275
305
|
});
|
|
276
306
|
const milestones = response?.data?.data;
|
|
277
307
|
const total = response?.data?.total;
|
|
308
|
+
const next = response?.data?.next;
|
|
278
309
|
if (!milestones) return {
|
|
279
310
|
milestones: null,
|
|
280
|
-
total: null
|
|
311
|
+
total: null,
|
|
312
|
+
next_page_token: null
|
|
281
313
|
};
|
|
282
314
|
return {
|
|
283
315
|
milestones,
|
|
284
|
-
total
|
|
316
|
+
total,
|
|
317
|
+
next_page_token: this.getNextPageToken(next)
|
|
285
318
|
};
|
|
286
319
|
}
|
|
287
320
|
async listIterationStories(iterationPublicId, includeDescription = false) {
|
|
@@ -389,12 +422,20 @@ var ShortcutClientWrapper = class {
|
|
|
389
422
|
if (!doc) throw new Error(`Failed to create the document: ${response.status}`);
|
|
390
423
|
return doc;
|
|
391
424
|
}
|
|
425
|
+
async getCustomFieldMap(customFieldIds) {
|
|
426
|
+
await this.loadCustomFields();
|
|
427
|
+
return new Map(customFieldIds.map((id) => [id, this.customFieldCache.get(id)]).filter((customField) => customField[1] !== null));
|
|
428
|
+
}
|
|
429
|
+
async getCustomFields() {
|
|
430
|
+
await this.loadCustomFields();
|
|
431
|
+
return Array.from(this.customFieldCache.values());
|
|
432
|
+
}
|
|
392
433
|
};
|
|
393
434
|
|
|
394
435
|
//#endregion
|
|
395
436
|
//#region package.json
|
|
396
437
|
var name = "@shortcut/mcp";
|
|
397
|
-
var version = "0.10.
|
|
438
|
+
var version = "0.10.3";
|
|
398
439
|
|
|
399
440
|
//#endregion
|
|
400
441
|
//#region src/tools/base.ts
|
|
@@ -448,9 +489,33 @@ var BaseTools = class {
|
|
|
448
489
|
is_owner
|
|
449
490
|
};
|
|
450
491
|
}
|
|
451
|
-
getSimplifiedStory(entity) {
|
|
492
|
+
getSimplifiedStory(entity, kind) {
|
|
452
493
|
if (!entity) return null;
|
|
453
|
-
const { id, name: name$1, app_url, archived, group_id, epic_id, iteration_id, workflow_id, workflow_state_id, owner_ids, requested_by_id } = entity;
|
|
494
|
+
const { id, name: name$1, app_url, archived, group_id, epic_id, iteration_id, workflow_id, workflow_state_id, owner_ids, requested_by_id, estimate, labels, comments, description, external_links, story_links, pull_requests, formatted_vcs_branch_name, branches, parent_story_id, sub_task_story_ids, tasks, custom_fields, blocked, blocker } = entity;
|
|
495
|
+
const additionalFields = {};
|
|
496
|
+
if (kind === "simple") {
|
|
497
|
+
additionalFields.description = description;
|
|
498
|
+
additionalFields.estimate = estimate ?? null;
|
|
499
|
+
additionalFields.comments = (comments || []).filter((c) => !c.deleted).map(({ id: id$1, author_id, text }) => ({
|
|
500
|
+
id: id$1,
|
|
501
|
+
author_id: author_id ?? null,
|
|
502
|
+
text: text ?? ""
|
|
503
|
+
}));
|
|
504
|
+
additionalFields.labels = (labels || []).map((l) => l.name);
|
|
505
|
+
additionalFields.external_links = external_links || [];
|
|
506
|
+
additionalFields.suggested_branch_name = formatted_vcs_branch_name ?? null;
|
|
507
|
+
additionalFields.pull_requests = (pull_requests || []).map((pr) => pr.url);
|
|
508
|
+
additionalFields.branches = (branches || []).map((b) => b.name);
|
|
509
|
+
additionalFields.related_stories = (story_links || []).map((sl) => sl.type === "object" ? sl.subject_id : sl.object_id);
|
|
510
|
+
additionalFields.tasks = (tasks || []).map((t) => ({
|
|
511
|
+
id: t.id,
|
|
512
|
+
description: t.description,
|
|
513
|
+
complete: t.complete
|
|
514
|
+
}));
|
|
515
|
+
additionalFields.custom_fields = (custom_fields || []).map((field) => field.value_id);
|
|
516
|
+
additionalFields.blocked = blocked;
|
|
517
|
+
additionalFields.blocker = blocker;
|
|
518
|
+
}
|
|
454
519
|
return {
|
|
455
520
|
id,
|
|
456
521
|
name: name$1,
|
|
@@ -462,7 +527,10 @@ var BaseTools = class {
|
|
|
462
527
|
workflow_id,
|
|
463
528
|
workflow_state_id,
|
|
464
529
|
owner_ids,
|
|
465
|
-
requested_by_id
|
|
530
|
+
requested_by_id,
|
|
531
|
+
parent_story_id: parent_story_id ?? null,
|
|
532
|
+
sub_task_ids: sub_task_story_ids ?? [],
|
|
533
|
+
...additionalFields
|
|
466
534
|
};
|
|
467
535
|
}
|
|
468
536
|
getSimplifiedWorkflow(entity) {
|
|
@@ -502,9 +570,19 @@ var BaseTools = class {
|
|
|
502
570
|
categories: categories.map((cat) => cat.name)
|
|
503
571
|
};
|
|
504
572
|
}
|
|
505
|
-
getSimplifiedEpic(entity) {
|
|
573
|
+
getSimplifiedEpic(entity, kind) {
|
|
506
574
|
if (!entity) return null;
|
|
507
|
-
const { id, name: name$1, app_url, archived, group_id, state, milestone_id } = entity;
|
|
575
|
+
const { id, name: name$1, app_url, archived, group_id, state, milestone_id, comments, description, deadline, owner_ids } = entity;
|
|
576
|
+
const additionalFields = {};
|
|
577
|
+
if (kind === "simple") {
|
|
578
|
+
additionalFields.comments = (comments || []).filter((comment) => !comment.deleted).map(({ id: id$1, author_id, text }) => ({
|
|
579
|
+
id: id$1,
|
|
580
|
+
author_id,
|
|
581
|
+
text
|
|
582
|
+
}));
|
|
583
|
+
additionalFields.description = description;
|
|
584
|
+
additionalFields.deadline = deadline ?? null;
|
|
585
|
+
}
|
|
508
586
|
return {
|
|
509
587
|
id,
|
|
510
588
|
name: name$1,
|
|
@@ -512,7 +590,9 @@ var BaseTools = class {
|
|
|
512
590
|
archived,
|
|
513
591
|
state,
|
|
514
592
|
team_id: group_id || null,
|
|
515
|
-
objective_id: milestone_id || null
|
|
593
|
+
objective_id: milestone_id || null,
|
|
594
|
+
owner_ids,
|
|
595
|
+
...additionalFields
|
|
516
596
|
};
|
|
517
597
|
}
|
|
518
598
|
getSimplifiedIteration(entity) {
|
|
@@ -534,8 +614,7 @@ var BaseTools = class {
|
|
|
534
614
|
workflows: {}
|
|
535
615
|
};
|
|
536
616
|
const { member_ids, workflow_ids } = entity;
|
|
537
|
-
const users = await this.client.getUserMap(member_ids);
|
|
538
|
-
const workflows = await this.client.getWorkflowMap(workflow_ids);
|
|
617
|
+
const [users, workflows] = await Promise.all([this.client.getUserMap(member_ids), this.client.getWorkflowMap(workflow_ids)]);
|
|
539
618
|
return {
|
|
540
619
|
users: Object.fromEntries(member_ids.map((id) => this.getSimplifiedMember(users.get(id))).filter((member) => member !== null).map((member) => [member.id, member])),
|
|
541
620
|
workflows: Object.fromEntries(workflow_ids.map((id) => this.getSimplifiedWorkflow(workflows.get(id))).filter((workflow) => workflow !== null).map((workflow) => [workflow.id, workflow]))
|
|
@@ -564,17 +643,21 @@ var BaseTools = class {
|
|
|
564
643
|
teams: {},
|
|
565
644
|
objectives: {}
|
|
566
645
|
};
|
|
567
|
-
const { group_id, owner_ids, milestone_id, requested_by_id, follower_ids } = entity;
|
|
568
|
-
const usersForEpicMap = await
|
|
569
|
-
...
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
646
|
+
const { group_id, owner_ids, milestone_id, requested_by_id, follower_ids, comments } = entity;
|
|
647
|
+
const [usersForEpicMap, teams, fullMilestone] = await Promise.all([
|
|
648
|
+
this.client.getUserMap([...new Set([
|
|
649
|
+
...owner_ids || [],
|
|
650
|
+
requested_by_id,
|
|
651
|
+
...follower_ids || [],
|
|
652
|
+
...(comments || []).map((comment) => comment.author_id)
|
|
653
|
+
].filter(Boolean))]),
|
|
654
|
+
this.client.getTeamMap(group_id ? [group_id] : []),
|
|
655
|
+
milestone_id ? this.client.getMilestone(milestone_id) : null
|
|
656
|
+
]);
|
|
573
657
|
const usersForEpic = Object.fromEntries([...usersForEpicMap.entries()].filter(([_, user$1]) => !!user$1).map(([id, user$1]) => [id, this.getSimplifiedMember(user$1)]));
|
|
574
|
-
const teams = await this.client.getTeamMap(group_id ? [group_id] : []);
|
|
575
658
|
const team = this.getSimplifiedTeam(teams.get(group_id || ""));
|
|
576
659
|
const { users, workflows } = await this.getRelatedEntitiesForTeam(teams.get(group_id || ""));
|
|
577
|
-
const milestone = this.getSimplifiedObjective(
|
|
660
|
+
const milestone = this.getSimplifiedObjective(fullMilestone);
|
|
578
661
|
return {
|
|
579
662
|
users: this.mergeRelatedEntities([usersForEpic, users]),
|
|
580
663
|
teams: team ? { [team.id]: team } : {},
|
|
@@ -582,20 +665,23 @@ var BaseTools = class {
|
|
|
582
665
|
workflows
|
|
583
666
|
};
|
|
584
667
|
}
|
|
585
|
-
async getRelatedEntitiesForStory(entity) {
|
|
586
|
-
const { group_id, iteration_id, epic_id, owner_ids, requested_by_id, follower_ids, workflow_id } = entity;
|
|
587
|
-
const fullUsersForStory = await
|
|
588
|
-
...
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
668
|
+
async getRelatedEntitiesForStory(entity, kind) {
|
|
669
|
+
const { group_id, iteration_id, epic_id, owner_ids, requested_by_id, follower_ids, workflow_id, comments, custom_fields } = entity;
|
|
670
|
+
const [fullUsersForStory, teamsForStory, workflowsForStory, iteration, epic] = await Promise.all([
|
|
671
|
+
this.client.getUserMap([...new Set([
|
|
672
|
+
...owner_ids || [],
|
|
673
|
+
requested_by_id,
|
|
674
|
+
...follower_ids || [],
|
|
675
|
+
...(comments || []).map((comment) => comment.author_id || "")
|
|
676
|
+
].filter(Boolean))]),
|
|
677
|
+
this.client.getTeamMap(group_id ? [group_id] : []),
|
|
678
|
+
this.client.getWorkflowMap(workflow_id ? [workflow_id] : []),
|
|
679
|
+
iteration_id ? this.client.getIteration(iteration_id) : null,
|
|
680
|
+
epic_id ? this.client.getEpic(epic_id) : null
|
|
681
|
+
]);
|
|
592
682
|
const usersForStory = Object.fromEntries([...fullUsersForStory.entries()].filter(([_, user$1]) => !!user$1).map(([id, user$1]) => [id, this.getSimplifiedMember(user$1)]));
|
|
593
|
-
const teamsForStory = await this.client.getTeamMap(group_id ? [group_id] : []);
|
|
594
|
-
const workflowsForStory = await this.client.getWorkflowMap(workflow_id ? [workflow_id] : []);
|
|
595
|
-
const iteration = iteration_id ? await this.client.getIteration(iteration_id) : null;
|
|
596
683
|
const simplifiedIteration = this.getSimplifiedIteration(iteration);
|
|
597
|
-
const
|
|
598
|
-
const simplifiedEpic = this.getSimplifiedEpic(epic);
|
|
684
|
+
const simplifiedEpic = this.getSimplifiedEpic(epic, kind);
|
|
599
685
|
const teamForStory = teamsForStory.get(group_id || "");
|
|
600
686
|
const workflowForStory = this.getSimplifiedWorkflow(workflowsForStory.get(workflow_id));
|
|
601
687
|
const { users: usersForTeam, workflows: workflowsForTeam } = await this.getRelatedEntitiesForTeam(teamForStory);
|
|
@@ -620,49 +706,67 @@ var BaseTools = class {
|
|
|
620
706
|
]);
|
|
621
707
|
const epics = simplifiedEpic ? { [simplifiedEpic.id]: simplifiedEpic } : {};
|
|
622
708
|
const iterations = simplifiedIteration ? { [simplifiedIteration.id]: simplifiedIteration } : {};
|
|
709
|
+
const relatedCustomFields = {};
|
|
710
|
+
if (custom_fields?.length) {
|
|
711
|
+
const customFieldMap = await this.client.getCustomFieldMap(custom_fields.map((cf) => cf.field_id));
|
|
712
|
+
custom_fields.forEach((cf) => {
|
|
713
|
+
const field = customFieldMap.get(cf.field_id);
|
|
714
|
+
if (!field) return;
|
|
715
|
+
const value = field.values?.find((v) => v.id === cf.value_id);
|
|
716
|
+
if (!value) return;
|
|
717
|
+
relatedCustomFields[cf.value_id] = {
|
|
718
|
+
field_id: cf.field_id,
|
|
719
|
+
value_id: cf.value_id,
|
|
720
|
+
field_name: field.name,
|
|
721
|
+
value_name: value.value
|
|
722
|
+
};
|
|
723
|
+
});
|
|
724
|
+
}
|
|
623
725
|
return {
|
|
624
726
|
users,
|
|
625
727
|
epics,
|
|
626
728
|
iterations,
|
|
627
729
|
workflows,
|
|
628
730
|
teams,
|
|
629
|
-
objectives
|
|
731
|
+
objectives,
|
|
732
|
+
custom_fields: relatedCustomFields
|
|
630
733
|
};
|
|
631
734
|
}
|
|
632
|
-
async getRelatedEntities(entity) {
|
|
735
|
+
async getRelatedEntities(entity, kind) {
|
|
633
736
|
if (entity.entity_type === "group") return this.getRelatedEntitiesForTeam(entity);
|
|
634
737
|
if (entity.entity_type === "iteration") return this.getRelatedEntitiesForIteration(entity);
|
|
635
738
|
if (entity.entity_type === "epic") return this.getRelatedEntitiesForEpic(entity);
|
|
636
|
-
if (entity.entity_type === "story") return this.getRelatedEntitiesForStory(entity);
|
|
739
|
+
if (entity.entity_type === "story") return this.getRelatedEntitiesForStory(entity, kind);
|
|
637
740
|
return {};
|
|
638
741
|
}
|
|
639
|
-
getSimplifiedEntity(entity) {
|
|
742
|
+
getSimplifiedEntity(entity, kind) {
|
|
640
743
|
if (entity.entity_type === "group") return this.getSimplifiedTeam(entity);
|
|
641
744
|
if (entity.entity_type === "iteration") return this.getSimplifiedIteration(entity);
|
|
642
|
-
if (entity.entity_type === "epic") return this.getSimplifiedEpic(entity);
|
|
643
|
-
if (entity.entity_type === "story") return this.getSimplifiedStory(entity);
|
|
745
|
+
if (entity.entity_type === "epic") return this.getSimplifiedEpic(entity, kind);
|
|
746
|
+
if (entity.entity_type === "story") return this.getSimplifiedStory(entity, kind);
|
|
644
747
|
if (entity.entity_type === "milestone") return this.getSimplifiedObjective(entity);
|
|
645
748
|
if (entity.entity_type === "workflow") return this.getSimplifiedWorkflow(entity);
|
|
646
749
|
return entity;
|
|
647
750
|
}
|
|
648
|
-
async entityWithRelatedEntities(entity, entityType = "entity") {
|
|
649
|
-
const
|
|
751
|
+
async entityWithRelatedEntities(entity, entityType = "entity", full = false) {
|
|
752
|
+
const finalEntity = full ? entity : this.getSimplifiedEntity(entity, "simple");
|
|
753
|
+
const relatedEntities = await this.getRelatedEntities(entity, full ? "full" : "simple");
|
|
650
754
|
return {
|
|
651
|
-
[entityType]: this.renameEntityProps(
|
|
755
|
+
[entityType]: this.renameEntityProps(finalEntity),
|
|
652
756
|
relatedEntities
|
|
653
757
|
};
|
|
654
758
|
}
|
|
655
759
|
async entitiesWithRelatedEntities(entities, entityType = "entities") {
|
|
656
|
-
const relatedEntities = await Promise.all(entities.map((entity) => this.getRelatedEntities(entity)));
|
|
760
|
+
const relatedEntities = await Promise.all(entities.map((entity) => this.getRelatedEntities(entity, "list")));
|
|
657
761
|
return {
|
|
658
|
-
[entityType]: entities.map((entity) => this.getSimplifiedEntity(entity)),
|
|
762
|
+
[entityType]: entities.map((entity) => this.getSimplifiedEntity(entity, "list")),
|
|
659
763
|
relatedEntities: this.mergeRelatedEntities(relatedEntities)
|
|
660
764
|
};
|
|
661
765
|
}
|
|
662
|
-
toResult(message, data) {
|
|
766
|
+
toResult(message, data, paginationToken) {
|
|
663
767
|
return { content: [{
|
|
664
768
|
type: "text",
|
|
665
|
-
text: `${message}${data !== void 0 ? `\n\n${JSON.stringify(data, null, 2)}` : ""}`
|
|
769
|
+
text: `${message}${data !== void 0 ? `\n\n<json>\n${JSON.stringify(data, null, 2)}\n</json>${paginationToken ? `\n\n<next-page-token>${paginationToken}</next-page-token>` : ""}` : ""}`
|
|
666
770
|
}] };
|
|
667
771
|
}
|
|
668
772
|
};
|
|
@@ -755,8 +859,12 @@ const user = (field) => z.string().optional().describe(`Find entities where the
|
|
|
755
859
|
var EpicTools = class EpicTools extends BaseTools {
|
|
756
860
|
static create(client$1, server$1) {
|
|
757
861
|
const tools = new EpicTools(client$1);
|
|
758
|
-
server$1.tool("get-epic", "Get a Shortcut epic by public ID", {
|
|
862
|
+
server$1.tool("get-epic", "Get a Shortcut epic by public ID", {
|
|
863
|
+
epicPublicId: z.number().positive().describe("The public ID of the epic to get"),
|
|
864
|
+
full: z.boolean().optional().default(false).describe("True to return all epic fields from the API. False to return a slim version that excludes uncommon fields")
|
|
865
|
+
}, async ({ epicPublicId, full }) => await tools.getEpic(epicPublicId, full));
|
|
759
866
|
server$1.tool("search-epics", "Find Shortcut epics.", {
|
|
867
|
+
nextPageToken: z.string().optional().describe("If a next_page_token was returned from the search result, pass it in to get the next page of results. Should be combined with the original search parameters."),
|
|
760
868
|
id: z.number().optional().describe("Find only epics with the specified public ID"),
|
|
761
869
|
name: z.string().optional().describe("Find only epics matching the specified name"),
|
|
762
870
|
description: z.string().optional().describe("Find only epics matching the specified description"),
|
|
@@ -783,7 +891,7 @@ var EpicTools = class EpicTools extends BaseTools {
|
|
|
783
891
|
updated: date(),
|
|
784
892
|
completed: date(),
|
|
785
893
|
due: date()
|
|
786
|
-
}, async (params) => await tools.searchEpics(params));
|
|
894
|
+
}, async ({ nextPageToken,...params }) => await tools.searchEpics(params, nextPageToken));
|
|
787
895
|
server$1.tool("create-epic", "Create a new Shortcut epic.", {
|
|
788
896
|
name: z.string().describe("The name of the epic"),
|
|
789
897
|
owner: z.string().optional().describe("The user ID of the owner of the epic"),
|
|
@@ -792,18 +900,18 @@ var EpicTools = class EpicTools extends BaseTools {
|
|
|
792
900
|
}, async (params) => await tools.createEpic(params));
|
|
793
901
|
return tools;
|
|
794
902
|
}
|
|
795
|
-
async searchEpics(params) {
|
|
903
|
+
async searchEpics(params, nextToken) {
|
|
796
904
|
const currentUser = await this.client.getCurrentUser();
|
|
797
905
|
const query = await buildSearchQuery(params, currentUser);
|
|
798
|
-
const { epics, total } = await this.client.searchEpics(query);
|
|
906
|
+
const { epics, total, next_page_token } = await this.client.searchEpics(query, nextToken);
|
|
799
907
|
if (!epics) throw new Error(`Failed to search for epics matching your query: "${query}"`);
|
|
800
908
|
if (!epics.length) return this.toResult(`Result: No epics found.`);
|
|
801
|
-
return this.toResult(`Result (
|
|
909
|
+
return this.toResult(`Result (${epics.length} shown of ${total} total epics found):`, await this.entitiesWithRelatedEntities(epics, "epics"), next_page_token);
|
|
802
910
|
}
|
|
803
|
-
async getEpic(epicPublicId) {
|
|
911
|
+
async getEpic(epicPublicId, full = false) {
|
|
804
912
|
const epic = await this.client.getEpic(epicPublicId);
|
|
805
913
|
if (!epic) throw new Error(`Failed to retrieve Shortcut epic with public ID: ${epicPublicId}`);
|
|
806
|
-
return this.toResult(`Epic: ${epicPublicId}`, await this.entityWithRelatedEntities(epic, "epic"));
|
|
914
|
+
return this.toResult(`Epic: ${epicPublicId}`, await this.entityWithRelatedEntities(epic, "epic", full));
|
|
807
915
|
}
|
|
808
916
|
async createEpic({ name: name$1, owner, teamId: group_id, description }) {
|
|
809
917
|
const epic = await this.client.createEpic({
|
|
@@ -825,8 +933,12 @@ var IterationTools = class IterationTools extends BaseTools {
|
|
|
825
933
|
iterationPublicId: z.number().positive().describe("The public ID of the iteration"),
|
|
826
934
|
includeStoryDescriptions: z.boolean().optional().default(false).describe("Indicate whether story descriptions should be included. Including descriptions may take longer and will increase the size of the response.")
|
|
827
935
|
}, async ({ iterationPublicId, includeStoryDescriptions }) => await tools.getIterationStories(iterationPublicId, includeStoryDescriptions));
|
|
828
|
-
server$1.tool("get-iteration", "Get a Shortcut iteration by public ID", {
|
|
936
|
+
server$1.tool("get-iteration", "Get a Shortcut iteration by public ID", {
|
|
937
|
+
iterationPublicId: z.number().positive().describe("The public ID of the iteration to get"),
|
|
938
|
+
full: z.boolean().optional().default(false).describe("True to return all iteration fields from the API. False to return a slim version that excludes uncommon fields")
|
|
939
|
+
}, async ({ iterationPublicId, full }) => await tools.getIteration(iterationPublicId, full));
|
|
829
940
|
server$1.tool("search-iterations", "Find Shortcut iterations.", {
|
|
941
|
+
nextPageToken: z.string().optional().describe("If a next_page_token was returned from the search result, pass it in to get the next page of results. Should be combined with the original search parameters."),
|
|
830
942
|
id: z.number().optional().describe("Find only iterations with the specified public ID"),
|
|
831
943
|
name: z.string().optional().describe("Find only iterations matching the specified name"),
|
|
832
944
|
description: z.string().optional().describe("Find only iterations matching the specified description"),
|
|
@@ -840,7 +952,7 @@ var IterationTools = class IterationTools extends BaseTools {
|
|
|
840
952
|
updated: date(),
|
|
841
953
|
startDate: date(),
|
|
842
954
|
endDate: date()
|
|
843
|
-
}, async (params) => await tools.searchIterations(params));
|
|
955
|
+
}, async ({ nextPageToken,...params }) => await tools.searchIterations(params, nextPageToken));
|
|
844
956
|
server$1.tool("create-iteration", "Create a new Shortcut iteration", {
|
|
845
957
|
name: z.string().describe("The name of the iteration"),
|
|
846
958
|
startDate: z.string().describe("The start date of the iteration in YYYY-MM-DD format"),
|
|
@@ -857,18 +969,18 @@ var IterationTools = class IterationTools extends BaseTools {
|
|
|
857
969
|
if (!stories) throw new Error(`Failed to retrieve Shortcut stories in iteration with public ID: ${iterationPublicId}.`);
|
|
858
970
|
return this.toResult(`Result (${stories.length} stories found):`, await this.entitiesWithRelatedEntities(stories, "stories"));
|
|
859
971
|
}
|
|
860
|
-
async searchIterations(params) {
|
|
972
|
+
async searchIterations(params, nextToken) {
|
|
861
973
|
const currentUser = await this.client.getCurrentUser();
|
|
862
974
|
const query = await buildSearchQuery(params, currentUser);
|
|
863
|
-
const { iterations, total } = await this.client.searchIterations(query);
|
|
975
|
+
const { iterations, total, next_page_token } = await this.client.searchIterations(query, nextToken);
|
|
864
976
|
if (!iterations) throw new Error(`Failed to search for iterations matching your query: "${query}".`);
|
|
865
977
|
if (!iterations.length) return this.toResult(`Result: No iterations found.`);
|
|
866
|
-
return this.toResult(`Result (
|
|
978
|
+
return this.toResult(`Result (${iterations.length} shown of ${total} total iterations found):`, await this.entitiesWithRelatedEntities(iterations, "iterations"), next_page_token);
|
|
867
979
|
}
|
|
868
|
-
async getIteration(iterationPublicId) {
|
|
980
|
+
async getIteration(iterationPublicId, full = false) {
|
|
869
981
|
const iteration = await this.client.getIteration(iterationPublicId);
|
|
870
982
|
if (!iteration) throw new Error(`Failed to retrieve Shortcut iteration with public ID: ${iterationPublicId}.`);
|
|
871
|
-
return this.toResult(`Iteration: ${iterationPublicId}`, await this.entityWithRelatedEntities(iteration, "iteration"));
|
|
983
|
+
return this.toResult(`Iteration: ${iterationPublicId}`, await this.entityWithRelatedEntities(iteration, "iteration", full));
|
|
872
984
|
}
|
|
873
985
|
async createIteration({ name: name$1, startDate, endDate, teamId, description }) {
|
|
874
986
|
const iteration = await this.client.createIteration({
|
|
@@ -928,8 +1040,12 @@ var IterationTools = class IterationTools extends BaseTools {
|
|
|
928
1040
|
var ObjectiveTools = class ObjectiveTools extends BaseTools {
|
|
929
1041
|
static create(client$1, server$1) {
|
|
930
1042
|
const tools = new ObjectiveTools(client$1);
|
|
931
|
-
server$1.tool("get-objective", "Get a Shortcut objective by public ID", {
|
|
1043
|
+
server$1.tool("get-objective", "Get a Shortcut objective by public ID", {
|
|
1044
|
+
objectivePublicId: z.number().positive().describe("The public ID of the objective to get"),
|
|
1045
|
+
full: z.boolean().optional().default(false).describe("True to return all objective fields from the API. False to return a slim version that excludes uncommon fields")
|
|
1046
|
+
}, async ({ objectivePublicId, full }) => await tools.getObjective(objectivePublicId, full));
|
|
932
1047
|
server$1.tool("search-objectives", "Find Shortcut objectives.", {
|
|
1048
|
+
nextPageToken: z.string().optional().describe("If a next_page_token was returned from the search result, pass it in to get the next page of results. Should be combined with the original search parameters."),
|
|
933
1049
|
id: z.number().optional().describe("Find objectives matching the specified id"),
|
|
934
1050
|
name: z.string().optional().describe("Find objectives matching the specified name"),
|
|
935
1051
|
description: z.string().optional().describe("Find objectives matching the specified description"),
|
|
@@ -949,21 +1065,21 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
|
|
|
949
1065
|
created: date(),
|
|
950
1066
|
updated: date(),
|
|
951
1067
|
completed: date()
|
|
952
|
-
}, async (params) => await tools.searchObjectives(params));
|
|
1068
|
+
}, async ({ nextPageToken,...params }) => await tools.searchObjectives(params, nextPageToken));
|
|
953
1069
|
return tools;
|
|
954
1070
|
}
|
|
955
|
-
async searchObjectives(params) {
|
|
1071
|
+
async searchObjectives(params, nextToken) {
|
|
956
1072
|
const currentUser = await this.client.getCurrentUser();
|
|
957
1073
|
const query = await buildSearchQuery(params, currentUser);
|
|
958
|
-
const { milestones, total } = await this.client.searchMilestones(query);
|
|
1074
|
+
const { milestones, total, next_page_token } = await this.client.searchMilestones(query, nextToken);
|
|
959
1075
|
if (!milestones) throw new Error(`Failed to search for milestones matching your query: "${query}"`);
|
|
960
1076
|
if (!milestones.length) return this.toResult(`Result: No milestones found.`);
|
|
961
|
-
return this.toResult(`Result (
|
|
1077
|
+
return this.toResult(`Result (${milestones.length} shown of ${total} total milestones found):`, await this.entitiesWithRelatedEntities(milestones, "objectives"), next_page_token);
|
|
962
1078
|
}
|
|
963
|
-
async getObjective(objectivePublicId) {
|
|
1079
|
+
async getObjective(objectivePublicId, full = false) {
|
|
964
1080
|
const objective = await this.client.getMilestone(objectivePublicId);
|
|
965
1081
|
if (!objective) throw new Error(`Failed to retrieve Shortcut objective with public ID: ${objectivePublicId}`);
|
|
966
|
-
return this.toResult(`Objective: ${objectivePublicId}`, await this.entityWithRelatedEntities(objective, "objective"));
|
|
1082
|
+
return this.toResult(`Objective: ${objectivePublicId}`, await this.entityWithRelatedEntities(objective, "objective", full));
|
|
967
1083
|
}
|
|
968
1084
|
};
|
|
969
1085
|
|
|
@@ -972,9 +1088,12 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
|
|
|
972
1088
|
var StoryTools = class StoryTools extends BaseTools {
|
|
973
1089
|
static create(client$1, server$1) {
|
|
974
1090
|
const tools = new StoryTools(client$1);
|
|
975
|
-
server$1.tool("get-story
|
|
976
|
-
|
|
1091
|
+
server$1.tool("get-story", "Get a Shortcut story by public ID", {
|
|
1092
|
+
storyPublicId: z.number().positive().describe("The public ID of the story to get"),
|
|
1093
|
+
full: z.boolean().optional().default(false).describe("True to return all story fields from the API. False to return a slim version that excludes uncommon fields")
|
|
1094
|
+
}, async ({ storyPublicId, full }) => await tools.getStory(storyPublicId, full));
|
|
977
1095
|
server$1.tool("search-stories", "Find Shortcut stories.", {
|
|
1096
|
+
nextPageToken: z.string().optional().describe("If a next_page_token was returned from the search result, pass it in to get the next page of results. Should be combined with the original search parameters."),
|
|
978
1097
|
id: z.number().optional().describe("Find only stories with the specified public ID"),
|
|
979
1098
|
name: z.string().optional().describe("Find only stories matching the specified name"),
|
|
980
1099
|
description: z.string().optional().describe("Find only stories matching the specified description"),
|
|
@@ -1023,7 +1142,8 @@ var StoryTools = class StoryTools extends BaseTools {
|
|
|
1023
1142
|
updated: date(),
|
|
1024
1143
|
completed: date(),
|
|
1025
1144
|
due: date()
|
|
1026
|
-
}, async (params) => await tools.searchStories(params));
|
|
1145
|
+
}, async ({ nextPageToken,...params }) => await tools.searchStories(params, nextPageToken));
|
|
1146
|
+
server$1.tool("get-story-branch-name", "Get a valid branch name for a specific story.", { storyPublicId: z.number().positive().describe("The public Id of the story") }, async ({ storyPublicId }) => await tools.getStoryBranchName(storyPublicId));
|
|
1027
1147
|
server$1.tool("create-story", `Create a new Shortcut story.
|
|
1028
1148
|
Name is required, and either a Team or Workflow must be specified:
|
|
1029
1149
|
- If only Team is specified, we will use the default workflow for that team.
|
|
@@ -1166,18 +1286,18 @@ The story will be added to the default state for the workflow.
|
|
|
1166
1286
|
});
|
|
1167
1287
|
return this.toResult(`Created story: ${story.id}`);
|
|
1168
1288
|
}
|
|
1169
|
-
async searchStories(params) {
|
|
1289
|
+
async searchStories(params, nextToken) {
|
|
1170
1290
|
const currentUser = await this.client.getCurrentUser();
|
|
1171
1291
|
const query = await buildSearchQuery(params, currentUser);
|
|
1172
|
-
const { stories, total } = await this.client.searchStories(query);
|
|
1292
|
+
const { stories, total, next_page_token } = await this.client.searchStories(query, nextToken);
|
|
1173
1293
|
if (!stories) throw new Error(`Failed to search for stories matching your query: "${query}".`);
|
|
1174
1294
|
if (!stories.length) return this.toResult(`Result: No stories found.`);
|
|
1175
|
-
return this.toResult(`Result (
|
|
1295
|
+
return this.toResult(`Result (${stories.length} shown of ${total} total stories found):`, await this.entitiesWithRelatedEntities(stories, "stories"), next_page_token);
|
|
1176
1296
|
}
|
|
1177
|
-
async getStory(storyPublicId) {
|
|
1297
|
+
async getStory(storyPublicId, full = false) {
|
|
1178
1298
|
const story = await this.client.getStory(storyPublicId);
|
|
1179
1299
|
if (!story) throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}.`);
|
|
1180
|
-
return this.toResult(`Story: sc-${storyPublicId}`, await this.entityWithRelatedEntities(story, "story"));
|
|
1300
|
+
return this.toResult(`Story: sc-${storyPublicId}`, await this.entityWithRelatedEntities(story, "story", full));
|
|
1181
1301
|
}
|
|
1182
1302
|
async createStoryComment({ storyPublicId, text }) {
|
|
1183
1303
|
if (!storyPublicId) throw new Error("Story public ID is required");
|
|
@@ -1285,14 +1405,17 @@ The story will be added to the default state for the workflow.
|
|
|
1285
1405
|
var TeamTools = class TeamTools extends BaseTools {
|
|
1286
1406
|
static create(client$1, server$1) {
|
|
1287
1407
|
const tools = new TeamTools(client$1);
|
|
1288
|
-
server$1.tool("get-team", "Get a Shortcut team by public ID", {
|
|
1408
|
+
server$1.tool("get-team", "Get a Shortcut team by public ID", {
|
|
1409
|
+
teamPublicId: z.string().describe("The public ID of the team to get"),
|
|
1410
|
+
full: z.boolean().optional().default(false).describe("True to return all team fields from the API. False to return a slim version that excludes uncommon fields")
|
|
1411
|
+
}, async ({ teamPublicId, full }) => await tools.getTeam(teamPublicId, full));
|
|
1289
1412
|
server$1.tool("list-teams", "List all Shortcut teams", async () => await tools.getTeams());
|
|
1290
1413
|
return tools;
|
|
1291
1414
|
}
|
|
1292
|
-
async getTeam(teamPublicId) {
|
|
1415
|
+
async getTeam(teamPublicId, full = false) {
|
|
1293
1416
|
const team = await this.client.getTeam(teamPublicId);
|
|
1294
1417
|
if (!team) return this.toResult(`Team with public ID: ${teamPublicId} not found.`);
|
|
1295
|
-
return this.toResult(`Team: ${team.id}`, await this.entityWithRelatedEntities(team, "team"));
|
|
1418
|
+
return this.toResult(`Team: ${team.id}`, await this.entityWithRelatedEntities(team, "team", full));
|
|
1296
1419
|
}
|
|
1297
1420
|
async getTeams() {
|
|
1298
1421
|
const teams = await this.client.getTeams();
|
|
@@ -1326,14 +1449,17 @@ var UserTools = class UserTools extends BaseTools {
|
|
|
1326
1449
|
var WorkflowTools = class WorkflowTools extends BaseTools {
|
|
1327
1450
|
static create(client$1, server$1) {
|
|
1328
1451
|
const tools = new WorkflowTools(client$1);
|
|
1329
|
-
server$1.tool("get-workflow", "Get a Shortcut workflow by public ID", {
|
|
1452
|
+
server$1.tool("get-workflow", "Get a Shortcut workflow by public ID", {
|
|
1453
|
+
workflowPublicId: z.number().positive().describe("The public ID of the workflow to get"),
|
|
1454
|
+
full: z.boolean().optional().default(false).describe("True to return all workflow fields from the API. False to return a slim version that excludes uncommon fields")
|
|
1455
|
+
}, async ({ workflowPublicId, full }) => await tools.getWorkflow(workflowPublicId, full));
|
|
1330
1456
|
server$1.tool("list-workflows", "List all Shortcut workflows", async () => await tools.listWorkflows());
|
|
1331
1457
|
return tools;
|
|
1332
1458
|
}
|
|
1333
|
-
async getWorkflow(workflowPublicId) {
|
|
1459
|
+
async getWorkflow(workflowPublicId, full = false) {
|
|
1334
1460
|
const workflow = await this.client.getWorkflow(workflowPublicId);
|
|
1335
1461
|
if (!workflow) return this.toResult(`Workflow with public ID: ${workflowPublicId} not found.`);
|
|
1336
|
-
return this.toResult(`Workflow: ${workflow.id}`, await this.entityWithRelatedEntities(workflow, "workflow"));
|
|
1462
|
+
return this.toResult(`Workflow: ${workflow.id}`, await this.entityWithRelatedEntities(workflow, "workflow", full));
|
|
1337
1463
|
}
|
|
1338
1464
|
async listWorkflows() {
|
|
1339
1465
|
const workflows = await this.client.getWorkflows();
|