@shortcut/mcp 0.10.2 → 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.
Files changed (2) hide show
  1. package/dist/index.js +64 -36
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -61,6 +61,14 @@ var ShortcutClientWrapper = class {
61
61
  this.workflowCache = new Cache();
62
62
  this.customFieldCache = new Cache();
63
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;
71
+ }
64
72
  async loadMembers() {
65
73
  if (this.userCache.isStale) {
66
74
  const response = await this.client.listMembers({});
@@ -181,38 +189,46 @@ var ShortcutClientWrapper = class {
181
189
  if (!milestone) return null;
182
190
  return milestone;
183
191
  }
184
- async searchStories(query) {
192
+ async searchStories(query, nextToken) {
185
193
  const response = await this.client.searchStories({
186
194
  query,
187
195
  page_size: 25,
188
- detail: "full"
196
+ detail: "full",
197
+ next: nextToken
189
198
  });
190
199
  const stories = response?.data?.data;
191
200
  const total = response?.data?.total;
201
+ const next = response?.data?.next;
192
202
  if (!stories) return {
193
203
  stories: null,
194
- total: null
204
+ total: null,
205
+ next_page_token: null
195
206
  };
196
207
  return {
197
208
  stories,
198
- total
209
+ total,
210
+ next_page_token: this.getNextPageToken(next)
199
211
  };
200
212
  }
201
- async searchIterations(query) {
213
+ async searchIterations(query, nextToken) {
202
214
  const response = await this.client.searchIterations({
203
215
  query,
204
216
  page_size: 25,
205
- detail: "full"
217
+ detail: "full",
218
+ next: nextToken
206
219
  });
207
220
  const iterations = response?.data?.data;
208
221
  const total = response?.data?.total;
222
+ const next = response?.data?.next;
209
223
  if (!iterations) return {
210
224
  iterations: null,
211
- total: null
225
+ total: null,
226
+ next_page_token: null
212
227
  };
213
228
  return {
214
229
  iterations,
215
- total
230
+ total,
231
+ next_page_token: this.getNextPageToken(next)
216
232
  };
217
233
  }
218
234
  async getActiveIteration(teamIds) {
@@ -259,38 +275,46 @@ var ShortcutClientWrapper = class {
259
275
  }, /* @__PURE__ */ new Map());
260
276
  return upcomingIterationByTeam;
261
277
  }
262
- async searchEpics(query) {
278
+ async searchEpics(query, nextToken) {
263
279
  const response = await this.client.searchEpics({
264
280
  query,
265
281
  page_size: 25,
266
- detail: "full"
282
+ detail: "full",
283
+ next: nextToken
267
284
  });
268
285
  const epics = response?.data?.data;
269
286
  const total = response?.data?.total;
287
+ const next = response?.data?.next;
270
288
  if (!epics) return {
271
289
  epics: null,
272
- total: null
290
+ total: null,
291
+ next_page_token: null
273
292
  };
274
293
  return {
275
294
  epics,
276
- total
295
+ total,
296
+ next_page_token: this.getNextPageToken(next)
277
297
  };
278
298
  }
279
- async searchMilestones(query) {
299
+ async searchMilestones(query, nextToken) {
280
300
  const response = await this.client.searchMilestones({
281
301
  query,
282
302
  page_size: 25,
283
- detail: "full"
303
+ detail: "full",
304
+ next: nextToken
284
305
  });
285
306
  const milestones = response?.data?.data;
286
307
  const total = response?.data?.total;
308
+ const next = response?.data?.next;
287
309
  if (!milestones) return {
288
310
  milestones: null,
289
- total: null
311
+ total: null,
312
+ next_page_token: null
290
313
  };
291
314
  return {
292
315
  milestones,
293
- total
316
+ total,
317
+ next_page_token: this.getNextPageToken(next)
294
318
  };
295
319
  }
296
320
  async listIterationStories(iterationPublicId, includeDescription = false) {
@@ -411,7 +435,7 @@ var ShortcutClientWrapper = class {
411
435
  //#endregion
412
436
  //#region package.json
413
437
  var name = "@shortcut/mcp";
414
- var version = "0.10.2";
438
+ var version = "0.10.3";
415
439
 
416
440
  //#endregion
417
441
  //#region src/tools/base.ts
@@ -739,10 +763,10 @@ var BaseTools = class {
739
763
  relatedEntities: this.mergeRelatedEntities(relatedEntities)
740
764
  };
741
765
  }
742
- toResult(message, data) {
766
+ toResult(message, data, paginationToken) {
743
767
  return { content: [{
744
768
  type: "text",
745
- text: `${message}${data !== void 0 ? `\n\n<json>\n${JSON.stringify(data, null, 2)}\n</json>` : ""}`
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>` : ""}` : ""}`
746
770
  }] };
747
771
  }
748
772
  };
@@ -840,6 +864,7 @@ var EpicTools = class EpicTools extends BaseTools {
840
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")
841
865
  }, async ({ epicPublicId, full }) => await tools.getEpic(epicPublicId, full));
842
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."),
843
868
  id: z.number().optional().describe("Find only epics with the specified public ID"),
844
869
  name: z.string().optional().describe("Find only epics matching the specified name"),
845
870
  description: z.string().optional().describe("Find only epics matching the specified description"),
@@ -866,7 +891,7 @@ var EpicTools = class EpicTools extends BaseTools {
866
891
  updated: date(),
867
892
  completed: date(),
868
893
  due: date()
869
- }, async (params) => await tools.searchEpics(params));
894
+ }, async ({ nextPageToken,...params }) => await tools.searchEpics(params, nextPageToken));
870
895
  server$1.tool("create-epic", "Create a new Shortcut epic.", {
871
896
  name: z.string().describe("The name of the epic"),
872
897
  owner: z.string().optional().describe("The user ID of the owner of the epic"),
@@ -875,13 +900,13 @@ var EpicTools = class EpicTools extends BaseTools {
875
900
  }, async (params) => await tools.createEpic(params));
876
901
  return tools;
877
902
  }
878
- async searchEpics(params) {
903
+ async searchEpics(params, nextToken) {
879
904
  const currentUser = await this.client.getCurrentUser();
880
905
  const query = await buildSearchQuery(params, currentUser);
881
- const { epics, total } = await this.client.searchEpics(query);
906
+ const { epics, total, next_page_token } = await this.client.searchEpics(query, nextToken);
882
907
  if (!epics) throw new Error(`Failed to search for epics matching your query: "${query}"`);
883
908
  if (!epics.length) return this.toResult(`Result: No epics found.`);
884
- return this.toResult(`Result (first ${epics.length} shown of ${total} total epics found):`, await this.entitiesWithRelatedEntities(epics, "epics"));
909
+ return this.toResult(`Result (${epics.length} shown of ${total} total epics found):`, await this.entitiesWithRelatedEntities(epics, "epics"), next_page_token);
885
910
  }
886
911
  async getEpic(epicPublicId, full = false) {
887
912
  const epic = await this.client.getEpic(epicPublicId);
@@ -913,6 +938,7 @@ var IterationTools = class IterationTools extends BaseTools {
913
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")
914
939
  }, async ({ iterationPublicId, full }) => await tools.getIteration(iterationPublicId, full));
915
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."),
916
942
  id: z.number().optional().describe("Find only iterations with the specified public ID"),
917
943
  name: z.string().optional().describe("Find only iterations matching the specified name"),
918
944
  description: z.string().optional().describe("Find only iterations matching the specified description"),
@@ -926,7 +952,7 @@ var IterationTools = class IterationTools extends BaseTools {
926
952
  updated: date(),
927
953
  startDate: date(),
928
954
  endDate: date()
929
- }, async (params) => await tools.searchIterations(params));
955
+ }, async ({ nextPageToken,...params }) => await tools.searchIterations(params, nextPageToken));
930
956
  server$1.tool("create-iteration", "Create a new Shortcut iteration", {
931
957
  name: z.string().describe("The name of the iteration"),
932
958
  startDate: z.string().describe("The start date of the iteration in YYYY-MM-DD format"),
@@ -943,13 +969,13 @@ var IterationTools = class IterationTools extends BaseTools {
943
969
  if (!stories) throw new Error(`Failed to retrieve Shortcut stories in iteration with public ID: ${iterationPublicId}.`);
944
970
  return this.toResult(`Result (${stories.length} stories found):`, await this.entitiesWithRelatedEntities(stories, "stories"));
945
971
  }
946
- async searchIterations(params) {
972
+ async searchIterations(params, nextToken) {
947
973
  const currentUser = await this.client.getCurrentUser();
948
974
  const query = await buildSearchQuery(params, currentUser);
949
- const { iterations, total } = await this.client.searchIterations(query);
975
+ const { iterations, total, next_page_token } = await this.client.searchIterations(query, nextToken);
950
976
  if (!iterations) throw new Error(`Failed to search for iterations matching your query: "${query}".`);
951
977
  if (!iterations.length) return this.toResult(`Result: No iterations found.`);
952
- return this.toResult(`Result (first ${iterations.length} shown of ${total} total iterations found):`, await this.entitiesWithRelatedEntities(iterations, "iterations"));
978
+ return this.toResult(`Result (${iterations.length} shown of ${total} total iterations found):`, await this.entitiesWithRelatedEntities(iterations, "iterations"), next_page_token);
953
979
  }
954
980
  async getIteration(iterationPublicId, full = false) {
955
981
  const iteration = await this.client.getIteration(iterationPublicId);
@@ -1019,6 +1045,7 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
1019
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")
1020
1046
  }, async ({ objectivePublicId, full }) => await tools.getObjective(objectivePublicId, full));
1021
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."),
1022
1049
  id: z.number().optional().describe("Find objectives matching the specified id"),
1023
1050
  name: z.string().optional().describe("Find objectives matching the specified name"),
1024
1051
  description: z.string().optional().describe("Find objectives matching the specified description"),
@@ -1038,16 +1065,16 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
1038
1065
  created: date(),
1039
1066
  updated: date(),
1040
1067
  completed: date()
1041
- }, async (params) => await tools.searchObjectives(params));
1068
+ }, async ({ nextPageToken,...params }) => await tools.searchObjectives(params, nextPageToken));
1042
1069
  return tools;
1043
1070
  }
1044
- async searchObjectives(params) {
1071
+ async searchObjectives(params, nextToken) {
1045
1072
  const currentUser = await this.client.getCurrentUser();
1046
1073
  const query = await buildSearchQuery(params, currentUser);
1047
- const { milestones, total } = await this.client.searchMilestones(query);
1074
+ const { milestones, total, next_page_token } = await this.client.searchMilestones(query, nextToken);
1048
1075
  if (!milestones) throw new Error(`Failed to search for milestones matching your query: "${query}"`);
1049
1076
  if (!milestones.length) return this.toResult(`Result: No milestones found.`);
1050
- return this.toResult(`Result (first ${milestones.length} shown of ${total} total milestones found):`, await this.entitiesWithRelatedEntities(milestones, "objectives"));
1077
+ return this.toResult(`Result (${milestones.length} shown of ${total} total milestones found):`, await this.entitiesWithRelatedEntities(milestones, "objectives"), next_page_token);
1051
1078
  }
1052
1079
  async getObjective(objectivePublicId, full = false) {
1053
1080
  const objective = await this.client.getMilestone(objectivePublicId);
@@ -1061,12 +1088,12 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
1061
1088
  var StoryTools = class StoryTools extends BaseTools {
1062
1089
  static create(client$1, server$1) {
1063
1090
  const tools = new StoryTools(client$1);
1064
- 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));
1065
1091
  server$1.tool("get-story", "Get a Shortcut story by public ID", {
1066
1092
  storyPublicId: z.number().positive().describe("The public ID of the story to get"),
1067
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")
1068
1094
  }, async ({ storyPublicId, full }) => await tools.getStory(storyPublicId, full));
1069
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."),
1070
1097
  id: z.number().optional().describe("Find only stories with the specified public ID"),
1071
1098
  name: z.string().optional().describe("Find only stories matching the specified name"),
1072
1099
  description: z.string().optional().describe("Find only stories matching the specified description"),
@@ -1115,7 +1142,8 @@ var StoryTools = class StoryTools extends BaseTools {
1115
1142
  updated: date(),
1116
1143
  completed: date(),
1117
1144
  due: date()
1118
- }, 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));
1119
1147
  server$1.tool("create-story", `Create a new Shortcut story.
1120
1148
  Name is required, and either a Team or Workflow must be specified:
1121
1149
  - If only Team is specified, we will use the default workflow for that team.
@@ -1258,13 +1286,13 @@ The story will be added to the default state for the workflow.
1258
1286
  });
1259
1287
  return this.toResult(`Created story: ${story.id}`);
1260
1288
  }
1261
- async searchStories(params) {
1289
+ async searchStories(params, nextToken) {
1262
1290
  const currentUser = await this.client.getCurrentUser();
1263
1291
  const query = await buildSearchQuery(params, currentUser);
1264
- const { stories, total } = await this.client.searchStories(query);
1292
+ const { stories, total, next_page_token } = await this.client.searchStories(query, nextToken);
1265
1293
  if (!stories) throw new Error(`Failed to search for stories matching your query: "${query}".`);
1266
1294
  if (!stories.length) return this.toResult(`Result: No stories found.`);
1267
- return this.toResult(`Result (first ${stories.length} shown of ${total} total stories found):`, await this.entitiesWithRelatedEntities(stories, "stories"));
1295
+ return this.toResult(`Result (${stories.length} shown of ${total} total stories found):`, await this.entitiesWithRelatedEntities(stories, "stories"), next_page_token);
1268
1296
  }
1269
1297
  async getStory(storyPublicId, full = false) {
1270
1298
  const story = await this.client.getStory(storyPublicId);
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "modelcontextprotocol"
13
13
  ],
14
14
  "license": "MIT",
15
- "version": "0.10.2",
15
+ "version": "0.10.3",
16
16
  "type": "module",
17
17
  "main": "dist/index.js",
18
18
  "bin": {