@shortcut/mcp 0.10.0 → 0.10.2

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 +173 -75
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -53,11 +53,13 @@ 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();
61
63
  }
62
64
  async loadMembers() {
63
65
  if (this.userCache.isStale) {
@@ -80,6 +82,13 @@ var ShortcutClientWrapper = class {
80
82
  if (workflows) this.workflowCache.setMany(workflows.map((workflow) => [workflow.id, workflow]));
81
83
  }
82
84
  }
85
+ async loadCustomFields() {
86
+ if (this.customFieldCache.isStale) {
87
+ const response = await this.client.listCustomFields();
88
+ const customFields = response?.data ?? null;
89
+ if (customFields) this.customFieldCache.setMany(customFields.map((customField) => [customField.id, customField]));
90
+ }
91
+ }
83
92
  async getCurrentUser() {
84
93
  if (this.currentUser) return this.currentUser;
85
94
  const response = await this.client.getCurrentMemberInfo();
@@ -389,12 +398,20 @@ var ShortcutClientWrapper = class {
389
398
  if (!doc) throw new Error(`Failed to create the document: ${response.status}`);
390
399
  return doc;
391
400
  }
401
+ async getCustomFieldMap(customFieldIds) {
402
+ await this.loadCustomFields();
403
+ return new Map(customFieldIds.map((id) => [id, this.customFieldCache.get(id)]).filter((customField) => customField[1] !== null));
404
+ }
405
+ async getCustomFields() {
406
+ await this.loadCustomFields();
407
+ return Array.from(this.customFieldCache.values());
408
+ }
392
409
  };
393
410
 
394
411
  //#endregion
395
412
  //#region package.json
396
413
  var name = "@shortcut/mcp";
397
- var version = "0.10.0";
414
+ var version = "0.10.2";
398
415
 
399
416
  //#endregion
400
417
  //#region src/tools/base.ts
@@ -448,9 +465,33 @@ var BaseTools = class {
448
465
  is_owner
449
466
  };
450
467
  }
451
- getSimplifiedStory(entity) {
468
+ getSimplifiedStory(entity, kind) {
452
469
  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;
470
+ 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;
471
+ const additionalFields = {};
472
+ if (kind === "simple") {
473
+ additionalFields.description = description;
474
+ additionalFields.estimate = estimate ?? null;
475
+ additionalFields.comments = (comments || []).filter((c) => !c.deleted).map(({ id: id$1, author_id, text }) => ({
476
+ id: id$1,
477
+ author_id: author_id ?? null,
478
+ text: text ?? ""
479
+ }));
480
+ additionalFields.labels = (labels || []).map((l) => l.name);
481
+ additionalFields.external_links = external_links || [];
482
+ additionalFields.suggested_branch_name = formatted_vcs_branch_name ?? null;
483
+ additionalFields.pull_requests = (pull_requests || []).map((pr) => pr.url);
484
+ additionalFields.branches = (branches || []).map((b) => b.name);
485
+ additionalFields.related_stories = (story_links || []).map((sl) => sl.type === "object" ? sl.subject_id : sl.object_id);
486
+ additionalFields.tasks = (tasks || []).map((t) => ({
487
+ id: t.id,
488
+ description: t.description,
489
+ complete: t.complete
490
+ }));
491
+ additionalFields.custom_fields = (custom_fields || []).map((field) => field.value_id);
492
+ additionalFields.blocked = blocked;
493
+ additionalFields.blocker = blocker;
494
+ }
454
495
  return {
455
496
  id,
456
497
  name: name$1,
@@ -462,7 +503,10 @@ var BaseTools = class {
462
503
  workflow_id,
463
504
  workflow_state_id,
464
505
  owner_ids,
465
- requested_by_id
506
+ requested_by_id,
507
+ parent_story_id: parent_story_id ?? null,
508
+ sub_task_ids: sub_task_story_ids ?? [],
509
+ ...additionalFields
466
510
  };
467
511
  }
468
512
  getSimplifiedWorkflow(entity) {
@@ -502,9 +546,19 @@ var BaseTools = class {
502
546
  categories: categories.map((cat) => cat.name)
503
547
  };
504
548
  }
505
- getSimplifiedEpic(entity) {
549
+ getSimplifiedEpic(entity, kind) {
506
550
  if (!entity) return null;
507
- const { id, name: name$1, app_url, archived, group_id, state, milestone_id } = entity;
551
+ const { id, name: name$1, app_url, archived, group_id, state, milestone_id, comments, description, deadline, owner_ids } = entity;
552
+ const additionalFields = {};
553
+ if (kind === "simple") {
554
+ additionalFields.comments = (comments || []).filter((comment) => !comment.deleted).map(({ id: id$1, author_id, text }) => ({
555
+ id: id$1,
556
+ author_id,
557
+ text
558
+ }));
559
+ additionalFields.description = description;
560
+ additionalFields.deadline = deadline ?? null;
561
+ }
508
562
  return {
509
563
  id,
510
564
  name: name$1,
@@ -512,7 +566,9 @@ var BaseTools = class {
512
566
  archived,
513
567
  state,
514
568
  team_id: group_id || null,
515
- objective_id: milestone_id || null
569
+ objective_id: milestone_id || null,
570
+ owner_ids,
571
+ ...additionalFields
516
572
  };
517
573
  }
518
574
  getSimplifiedIteration(entity) {
@@ -534,8 +590,7 @@ var BaseTools = class {
534
590
  workflows: {}
535
591
  };
536
592
  const { member_ids, workflow_ids } = entity;
537
- const users = await this.client.getUserMap(member_ids);
538
- const workflows = await this.client.getWorkflowMap(workflow_ids);
593
+ const [users, workflows] = await Promise.all([this.client.getUserMap(member_ids), this.client.getWorkflowMap(workflow_ids)]);
539
594
  return {
540
595
  users: Object.fromEntries(member_ids.map((id) => this.getSimplifiedMember(users.get(id))).filter((member) => member !== null).map((member) => [member.id, member])),
541
596
  workflows: Object.fromEntries(workflow_ids.map((id) => this.getSimplifiedWorkflow(workflows.get(id))).filter((workflow) => workflow !== null).map((workflow) => [workflow.id, workflow]))
@@ -564,17 +619,21 @@ var BaseTools = class {
564
619
  teams: {},
565
620
  objectives: {}
566
621
  };
567
- const { group_id, owner_ids, milestone_id, requested_by_id, follower_ids } = entity;
568
- const usersForEpicMap = await this.client.getUserMap([...new Set([
569
- ...owner_ids || [],
570
- requested_by_id,
571
- ...follower_ids || []
572
- ].filter(Boolean))]);
622
+ const { group_id, owner_ids, milestone_id, requested_by_id, follower_ids, comments } = entity;
623
+ const [usersForEpicMap, teams, fullMilestone] = await Promise.all([
624
+ this.client.getUserMap([...new Set([
625
+ ...owner_ids || [],
626
+ requested_by_id,
627
+ ...follower_ids || [],
628
+ ...(comments || []).map((comment) => comment.author_id)
629
+ ].filter(Boolean))]),
630
+ this.client.getTeamMap(group_id ? [group_id] : []),
631
+ milestone_id ? this.client.getMilestone(milestone_id) : null
632
+ ]);
573
633
  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
634
  const team = this.getSimplifiedTeam(teams.get(group_id || ""));
576
635
  const { users, workflows } = await this.getRelatedEntitiesForTeam(teams.get(group_id || ""));
577
- const milestone = this.getSimplifiedObjective(milestone_id ? await this.client.getMilestone(milestone_id) : null);
636
+ const milestone = this.getSimplifiedObjective(fullMilestone);
578
637
  return {
579
638
  users: this.mergeRelatedEntities([usersForEpic, users]),
580
639
  teams: team ? { [team.id]: team } : {},
@@ -582,20 +641,23 @@ var BaseTools = class {
582
641
  workflows
583
642
  };
584
643
  }
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 this.client.getUserMap([...new Set([
588
- ...owner_ids || [],
589
- requested_by_id,
590
- ...follower_ids || []
591
- ].filter(Boolean))]);
644
+ async getRelatedEntitiesForStory(entity, kind) {
645
+ const { group_id, iteration_id, epic_id, owner_ids, requested_by_id, follower_ids, workflow_id, comments, custom_fields } = entity;
646
+ const [fullUsersForStory, teamsForStory, workflowsForStory, iteration, epic] = await Promise.all([
647
+ this.client.getUserMap([...new Set([
648
+ ...owner_ids || [],
649
+ requested_by_id,
650
+ ...follower_ids || [],
651
+ ...(comments || []).map((comment) => comment.author_id || "")
652
+ ].filter(Boolean))]),
653
+ this.client.getTeamMap(group_id ? [group_id] : []),
654
+ this.client.getWorkflowMap(workflow_id ? [workflow_id] : []),
655
+ iteration_id ? this.client.getIteration(iteration_id) : null,
656
+ epic_id ? this.client.getEpic(epic_id) : null
657
+ ]);
592
658
  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
659
  const simplifiedIteration = this.getSimplifiedIteration(iteration);
597
- const epic = epic_id ? await this.client.getEpic(epic_id) : null;
598
- const simplifiedEpic = this.getSimplifiedEpic(epic);
660
+ const simplifiedEpic = this.getSimplifiedEpic(epic, kind);
599
661
  const teamForStory = teamsForStory.get(group_id || "");
600
662
  const workflowForStory = this.getSimplifiedWorkflow(workflowsForStory.get(workflow_id));
601
663
  const { users: usersForTeam, workflows: workflowsForTeam } = await this.getRelatedEntitiesForTeam(teamForStory);
@@ -620,49 +682,67 @@ var BaseTools = class {
620
682
  ]);
621
683
  const epics = simplifiedEpic ? { [simplifiedEpic.id]: simplifiedEpic } : {};
622
684
  const iterations = simplifiedIteration ? { [simplifiedIteration.id]: simplifiedIteration } : {};
685
+ const relatedCustomFields = {};
686
+ if (custom_fields?.length) {
687
+ const customFieldMap = await this.client.getCustomFieldMap(custom_fields.map((cf) => cf.field_id));
688
+ custom_fields.forEach((cf) => {
689
+ const field = customFieldMap.get(cf.field_id);
690
+ if (!field) return;
691
+ const value = field.values?.find((v) => v.id === cf.value_id);
692
+ if (!value) return;
693
+ relatedCustomFields[cf.value_id] = {
694
+ field_id: cf.field_id,
695
+ value_id: cf.value_id,
696
+ field_name: field.name,
697
+ value_name: value.value
698
+ };
699
+ });
700
+ }
623
701
  return {
624
702
  users,
625
703
  epics,
626
704
  iterations,
627
705
  workflows,
628
706
  teams,
629
- objectives
707
+ objectives,
708
+ custom_fields: relatedCustomFields
630
709
  };
631
710
  }
632
- async getRelatedEntities(entity) {
711
+ async getRelatedEntities(entity, kind) {
633
712
  if (entity.entity_type === "group") return this.getRelatedEntitiesForTeam(entity);
634
713
  if (entity.entity_type === "iteration") return this.getRelatedEntitiesForIteration(entity);
635
714
  if (entity.entity_type === "epic") return this.getRelatedEntitiesForEpic(entity);
636
- if (entity.entity_type === "story") return this.getRelatedEntitiesForStory(entity);
715
+ if (entity.entity_type === "story") return this.getRelatedEntitiesForStory(entity, kind);
637
716
  return {};
638
717
  }
639
- getSimplifiedEntity(entity) {
718
+ getSimplifiedEntity(entity, kind) {
640
719
  if (entity.entity_type === "group") return this.getSimplifiedTeam(entity);
641
720
  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);
721
+ if (entity.entity_type === "epic") return this.getSimplifiedEpic(entity, kind);
722
+ if (entity.entity_type === "story") return this.getSimplifiedStory(entity, kind);
644
723
  if (entity.entity_type === "milestone") return this.getSimplifiedObjective(entity);
645
724
  if (entity.entity_type === "workflow") return this.getSimplifiedWorkflow(entity);
646
725
  return entity;
647
726
  }
648
- async entityWithRelatedEntities(entity, entityType = "entity") {
649
- const relatedEntities = await this.getRelatedEntities(entity);
727
+ async entityWithRelatedEntities(entity, entityType = "entity", full = false) {
728
+ const finalEntity = full ? entity : this.getSimplifiedEntity(entity, "simple");
729
+ const relatedEntities = await this.getRelatedEntities(entity, full ? "full" : "simple");
650
730
  return {
651
- [entityType]: this.renameEntityProps(entity),
731
+ [entityType]: this.renameEntityProps(finalEntity),
652
732
  relatedEntities
653
733
  };
654
734
  }
655
735
  async entitiesWithRelatedEntities(entities, entityType = "entities") {
656
- const relatedEntities = await Promise.all(entities.map((entity) => this.getRelatedEntities(entity)));
736
+ const relatedEntities = await Promise.all(entities.map((entity) => this.getRelatedEntities(entity, "list")));
657
737
  return {
658
- [entityType]: entities.map((entity) => this.getSimplifiedEntity(entity)),
738
+ [entityType]: entities.map((entity) => this.getSimplifiedEntity(entity, "list")),
659
739
  relatedEntities: this.mergeRelatedEntities(relatedEntities)
660
740
  };
661
741
  }
662
742
  toResult(message, data) {
663
743
  return { content: [{
664
744
  type: "text",
665
- text: `${message}${data !== void 0 ? `\n\n${JSON.stringify(data, null, 2)}` : ""}`
745
+ text: `${message}${data !== void 0 ? `\n\n<json>\n${JSON.stringify(data, null, 2)}\n</json>` : ""}`
666
746
  }] };
667
747
  }
668
748
  };
@@ -745,7 +825,7 @@ const variations = [
745
825
  })
746
826
  ];
747
827
  const DATE_REGEXP = /* @__PURE__ */ new RegExp(`^(${variations.join("|")})$`);
748
- const date = z.string().regex(DATE_REGEXP).optional().describe("The date in \"YYYY-MM-DD\" format, or one of the keywords: \"yesterday\", \"today\", \"tomorrow\", or a date range in the format \"YYYY-MM-DD..YYYY-MM-DD\". The date range can also be open ended by using \"*\" for one of the bounds. Examples: \"2023-01-01\", \"today\", \"2023-01-01..*\" (from Jan 1, 2023 to any future date), \"*.2023-01-31\" (any date up to Jan 31, 2023), \"today..*\" (from today onwards), \"*.yesterday\" (any date up to yesterday). The keywords cannot be used to calculate relative dates (e.g. the following are not valid: \"today-1\" or \"tomorrow+1\").");
828
+ const date = () => z.string().regex(DATE_REGEXP).optional().describe("The date in \"YYYY-MM-DD\" format, or one of the keywords: \"yesterday\", \"today\", \"tomorrow\", or a date range in the format \"YYYY-MM-DD..YYYY-MM-DD\". The date range can also be open ended by using \"*\" for one of the bounds. Examples: \"2023-01-01\", \"today\", \"2023-01-01..*\" (from Jan 1, 2023 to any future date), \"*.2023-01-31\" (any date up to Jan 31, 2023), \"today..*\" (from today onwards), \"*.yesterday\" (any date up to yesterday). The keywords cannot be used to calculate relative dates (e.g. the following are not valid: \"today-1\" or \"tomorrow+1\").");
749
829
  const is = (field) => z.boolean().optional().describe(`Find only entities that are ${field} when true, or only entities that are not ${field} when false.`);
750
830
  const has = (field) => z.boolean().optional().describe(`Find only entities that have ${field} when true, or only entities that do not have ${field} when false. Example: hasOwner: true will find stories with an owner, hasOwner: false will find stories without an owner.`);
751
831
  const user = (field) => z.string().optional().describe(`Find entities where the ${field} match the specified user. This must either be the user\'s mention name or the keyword "me" for the current user.`);
@@ -755,7 +835,10 @@ const user = (field) => z.string().optional().describe(`Find entities where the
755
835
  var EpicTools = class EpicTools extends BaseTools {
756
836
  static create(client$1, server$1) {
757
837
  const tools = new EpicTools(client$1);
758
- server$1.tool("get-epic", "Get a Shortcut epic by public ID", { epicPublicId: z.number().positive().describe("The public ID of the epic to get") }, async ({ epicPublicId }) => await tools.getEpic(epicPublicId));
838
+ server$1.tool("get-epic", "Get a Shortcut epic by public ID", {
839
+ epicPublicId: z.number().positive().describe("The public ID of the epic to get"),
840
+ 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
+ }, async ({ epicPublicId, full }) => await tools.getEpic(epicPublicId, full));
759
842
  server$1.tool("search-epics", "Find Shortcut epics.", {
760
843
  id: z.number().optional().describe("Find only epics with the specified public ID"),
761
844
  name: z.string().optional().describe("Find only epics matching the specified name"),
@@ -779,10 +862,10 @@ var EpicTools = class EpicTools extends BaseTools {
779
862
  hasComment: has("a comment"),
780
863
  hasDeadline: has("a deadline"),
781
864
  hasLabel: has("a label"),
782
- created: date,
783
- updated: date,
784
- completed: date,
785
- due: date
865
+ created: date(),
866
+ updated: date(),
867
+ completed: date(),
868
+ due: date()
786
869
  }, async (params) => await tools.searchEpics(params));
787
870
  server$1.tool("create-epic", "Create a new Shortcut epic.", {
788
871
  name: z.string().describe("The name of the epic"),
@@ -800,10 +883,10 @@ var EpicTools = class EpicTools extends BaseTools {
800
883
  if (!epics.length) return this.toResult(`Result: No epics found.`);
801
884
  return this.toResult(`Result (first ${epics.length} shown of ${total} total epics found):`, await this.entitiesWithRelatedEntities(epics, "epics"));
802
885
  }
803
- async getEpic(epicPublicId) {
886
+ async getEpic(epicPublicId, full = false) {
804
887
  const epic = await this.client.getEpic(epicPublicId);
805
888
  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"));
889
+ return this.toResult(`Epic: ${epicPublicId}`, await this.entityWithRelatedEntities(epic, "epic", full));
807
890
  }
808
891
  async createEpic({ name: name$1, owner, teamId: group_id, description }) {
809
892
  const epic = await this.client.createEpic({
@@ -825,7 +908,10 @@ var IterationTools = class IterationTools extends BaseTools {
825
908
  iterationPublicId: z.number().positive().describe("The public ID of the iteration"),
826
909
  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
910
  }, async ({ iterationPublicId, includeStoryDescriptions }) => await tools.getIterationStories(iterationPublicId, includeStoryDescriptions));
828
- server$1.tool("get-iteration", "Get a Shortcut iteration by public ID", { iterationPublicId: z.number().positive().describe("The public ID of the iteration to get") }, async ({ iterationPublicId }) => await tools.getIteration(iterationPublicId));
911
+ server$1.tool("get-iteration", "Get a Shortcut iteration by public ID", {
912
+ iterationPublicId: z.number().positive().describe("The public ID of the iteration to get"),
913
+ 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
+ }, async ({ iterationPublicId, full }) => await tools.getIteration(iterationPublicId, full));
829
915
  server$1.tool("search-iterations", "Find Shortcut iterations.", {
830
916
  id: z.number().optional().describe("Find only iterations with the specified public ID"),
831
917
  name: z.string().optional().describe("Find only iterations matching the specified name"),
@@ -836,10 +922,10 @@ var IterationTools = class IterationTools extends BaseTools {
836
922
  "done"
837
923
  ]).optional().describe("Find only iterations matching the specified state"),
838
924
  team: z.string().optional().describe("Find only iterations matching the specified team. This can be a team ID or mention name."),
839
- created: date,
840
- updated: date,
841
- startDate: date,
842
- endDate: date
925
+ created: date(),
926
+ updated: date(),
927
+ startDate: date(),
928
+ endDate: date()
843
929
  }, async (params) => await tools.searchIterations(params));
844
930
  server$1.tool("create-iteration", "Create a new Shortcut iteration", {
845
931
  name: z.string().describe("The name of the iteration"),
@@ -865,10 +951,10 @@ var IterationTools = class IterationTools extends BaseTools {
865
951
  if (!iterations.length) return this.toResult(`Result: No iterations found.`);
866
952
  return this.toResult(`Result (first ${iterations.length} shown of ${total} total iterations found):`, await this.entitiesWithRelatedEntities(iterations, "iterations"));
867
953
  }
868
- async getIteration(iterationPublicId) {
954
+ async getIteration(iterationPublicId, full = false) {
869
955
  const iteration = await this.client.getIteration(iterationPublicId);
870
956
  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"));
957
+ return this.toResult(`Iteration: ${iterationPublicId}`, await this.entityWithRelatedEntities(iteration, "iteration", full));
872
958
  }
873
959
  async createIteration({ name: name$1, startDate, endDate, teamId, description }) {
874
960
  const iteration = await this.client.createIteration({
@@ -928,7 +1014,10 @@ var IterationTools = class IterationTools extends BaseTools {
928
1014
  var ObjectiveTools = class ObjectiveTools extends BaseTools {
929
1015
  static create(client$1, server$1) {
930
1016
  const tools = new ObjectiveTools(client$1);
931
- server$1.tool("get-objective", "Get a Shortcut objective by public ID", { objectivePublicId: z.number().positive().describe("The public ID of the objective to get") }, async ({ objectivePublicId }) => await tools.getObjective(objectivePublicId));
1017
+ server$1.tool("get-objective", "Get a Shortcut objective by public ID", {
1018
+ objectivePublicId: z.number().positive().describe("The public ID of the objective to get"),
1019
+ 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
+ }, async ({ objectivePublicId, full }) => await tools.getObjective(objectivePublicId, full));
932
1021
  server$1.tool("search-objectives", "Find Shortcut objectives.", {
933
1022
  id: z.number().optional().describe("Find objectives matching the specified id"),
934
1023
  name: z.string().optional().describe("Find objectives matching the specified name"),
@@ -946,9 +1035,9 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
946
1035
  isDone: is("completed"),
947
1036
  isArchived: is("archived"),
948
1037
  hasOwner: has("an owner"),
949
- created: date,
950
- updated: date,
951
- completed: date
1038
+ created: date(),
1039
+ updated: date(),
1040
+ completed: date()
952
1041
  }, async (params) => await tools.searchObjectives(params));
953
1042
  return tools;
954
1043
  }
@@ -960,10 +1049,10 @@ var ObjectiveTools = class ObjectiveTools extends BaseTools {
960
1049
  if (!milestones.length) return this.toResult(`Result: No milestones found.`);
961
1050
  return this.toResult(`Result (first ${milestones.length} shown of ${total} total milestones found):`, await this.entitiesWithRelatedEntities(milestones, "objectives"));
962
1051
  }
963
- async getObjective(objectivePublicId) {
1052
+ async getObjective(objectivePublicId, full = false) {
964
1053
  const objective = await this.client.getMilestone(objectivePublicId);
965
1054
  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"));
1055
+ return this.toResult(`Objective: ${objectivePublicId}`, await this.entityWithRelatedEntities(objective, "objective", full));
967
1056
  }
968
1057
  };
969
1058
 
@@ -973,7 +1062,10 @@ var StoryTools = class StoryTools extends BaseTools {
973
1062
  static create(client$1, server$1) {
974
1063
  const tools = new StoryTools(client$1);
975
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));
976
- server$1.tool("get-story", "Get a Shortcut story by public ID", { storyPublicId: z.number().positive().describe("The public ID of the story to get") }, async ({ storyPublicId }) => await tools.getStory(storyPublicId));
1065
+ server$1.tool("get-story", "Get a Shortcut story by public ID", {
1066
+ storyPublicId: z.number().positive().describe("The public ID of the story to get"),
1067
+ 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
+ }, async ({ storyPublicId, full }) => await tools.getStory(storyPublicId, full));
977
1069
  server$1.tool("search-stories", "Find Shortcut stories.", {
978
1070
  id: z.number().optional().describe("Find only stories with the specified public ID"),
979
1071
  name: z.string().optional().describe("Find only stories matching the specified name"),
@@ -1019,10 +1111,10 @@ var StoryTools = class StoryTools extends BaseTools {
1019
1111
  hasEpic: has("an epic"),
1020
1112
  hasTask: has("a task"),
1021
1113
  hasAttachment: has("an attachment"),
1022
- created: date,
1023
- updated: date,
1024
- completed: date,
1025
- due: date
1114
+ created: date(),
1115
+ updated: date(),
1116
+ completed: date(),
1117
+ due: date()
1026
1118
  }, async (params) => await tools.searchStories(params));
1027
1119
  server$1.tool("create-story", `Create a new Shortcut story.
1028
1120
  Name is required, and either a Team or Workflow must be specified:
@@ -1174,10 +1266,10 @@ The story will be added to the default state for the workflow.
1174
1266
  if (!stories.length) return this.toResult(`Result: No stories found.`);
1175
1267
  return this.toResult(`Result (first ${stories.length} shown of ${total} total stories found):`, await this.entitiesWithRelatedEntities(stories, "stories"));
1176
1268
  }
1177
- async getStory(storyPublicId) {
1269
+ async getStory(storyPublicId, full = false) {
1178
1270
  const story = await this.client.getStory(storyPublicId);
1179
1271
  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"));
1272
+ return this.toResult(`Story: sc-${storyPublicId}`, await this.entityWithRelatedEntities(story, "story", full));
1181
1273
  }
1182
1274
  async createStoryComment({ storyPublicId, text }) {
1183
1275
  if (!storyPublicId) throw new Error("Story public ID is required");
@@ -1285,14 +1377,17 @@ The story will be added to the default state for the workflow.
1285
1377
  var TeamTools = class TeamTools extends BaseTools {
1286
1378
  static create(client$1, server$1) {
1287
1379
  const tools = new TeamTools(client$1);
1288
- server$1.tool("get-team", "Get a Shortcut team by public ID", { teamPublicId: z.string().describe("The public ID of the team to get") }, async ({ teamPublicId }) => await tools.getTeam(teamPublicId));
1380
+ server$1.tool("get-team", "Get a Shortcut team by public ID", {
1381
+ teamPublicId: z.string().describe("The public ID of the team to get"),
1382
+ 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")
1383
+ }, async ({ teamPublicId, full }) => await tools.getTeam(teamPublicId, full));
1289
1384
  server$1.tool("list-teams", "List all Shortcut teams", async () => await tools.getTeams());
1290
1385
  return tools;
1291
1386
  }
1292
- async getTeam(teamPublicId) {
1387
+ async getTeam(teamPublicId, full = false) {
1293
1388
  const team = await this.client.getTeam(teamPublicId);
1294
1389
  if (!team) return this.toResult(`Team with public ID: ${teamPublicId} not found.`);
1295
- return this.toResult(`Team: ${team.id}`, await this.entityWithRelatedEntities(team, "team"));
1390
+ return this.toResult(`Team: ${team.id}`, await this.entityWithRelatedEntities(team, "team", full));
1296
1391
  }
1297
1392
  async getTeams() {
1298
1393
  const teams = await this.client.getTeams();
@@ -1326,14 +1421,17 @@ var UserTools = class UserTools extends BaseTools {
1326
1421
  var WorkflowTools = class WorkflowTools extends BaseTools {
1327
1422
  static create(client$1, server$1) {
1328
1423
  const tools = new WorkflowTools(client$1);
1329
- server$1.tool("get-workflow", "Get a Shortcut workflow by public ID", { workflowPublicId: z.number().positive().describe("The public ID of the workflow to get") }, async ({ workflowPublicId }) => await tools.getWorkflow(workflowPublicId));
1424
+ server$1.tool("get-workflow", "Get a Shortcut workflow by public ID", {
1425
+ workflowPublicId: z.number().positive().describe("The public ID of the workflow to get"),
1426
+ 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")
1427
+ }, async ({ workflowPublicId, full }) => await tools.getWorkflow(workflowPublicId, full));
1330
1428
  server$1.tool("list-workflows", "List all Shortcut workflows", async () => await tools.listWorkflows());
1331
1429
  return tools;
1332
1430
  }
1333
- async getWorkflow(workflowPublicId) {
1431
+ async getWorkflow(workflowPublicId, full = false) {
1334
1432
  const workflow = await this.client.getWorkflow(workflowPublicId);
1335
1433
  if (!workflow) return this.toResult(`Workflow with public ID: ${workflowPublicId} not found.`);
1336
- return this.toResult(`Workflow: ${workflow.id}`, await this.entityWithRelatedEntities(workflow, "workflow"));
1434
+ return this.toResult(`Workflow: ${workflow.id}`, await this.entityWithRelatedEntities(workflow, "workflow", full));
1337
1435
  }
1338
1436
  async listWorkflows() {
1339
1437
  const workflows = await this.client.getWorkflows();
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "modelcontextprotocol"
13
13
  ],
14
14
  "license": "MIT",
15
- "version": "0.10.0",
15
+ "version": "0.10.2",
16
16
  "type": "module",
17
17
  "main": "dist/index.js",
18
18
  "bin": {