@shortcut/mcp 0.1.0 → 0.1.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 (3) hide show
  1. package/README.md +19 -24
  2. package/dist/index.js +39 -24
  3. package/package.json +7 -4
package/README.md CHANGED
@@ -1,26 +1,7 @@
1
- # @useshortcut/mcp
2
-
3
- > [!IMPORTANT]
4
- > To use the MCP server, you need to first install the dependencies and run the build step.
5
-
6
- ## Installation
7
-
8
- > First - install **bun** if needed: [Bun](https://bun.sh).
9
-
10
- ```bash
11
- bun install
12
- ```
13
-
14
- ## Build
15
-
16
- ```bash
17
- bun run build
18
- ```
1
+ # @shortcut/mcp
19
2
 
20
3
  ## Usage
21
4
 
22
- > Note: `mcp-server-shortcut` in the paths below refer to the folder name where you cloned this repo. If you used a different folder name, you'll need to use that instead.
23
-
24
5
  ### Windsurf
25
6
 
26
7
  See the [official Windsurf docs](https://codeium.com/docs/windsurf/mcp) for more information.
@@ -33,9 +14,9 @@ See the [official Windsurf docs](https://codeium.com/docs/windsurf/mcp) for more
33
14
  {
34
15
  "mcpServers": {
35
16
  "shortcut": {
36
- "command": "node",
17
+ "command": "npx",
37
18
  "args": [
38
- "/path/to/this/repo/mcp-server-shortcut"
19
+ "@shortcut/mcp"
39
20
  ],
40
21
  "env": {
41
22
  "SHORTCUT_API_TOKEN": "<YOUR_SHORTCUT_API_TOKEN>"
@@ -56,9 +37,9 @@ See the [official Cursor docs](https://docs.cursor.com/context/model-context-pro
56
37
  {
57
38
  "mcpServers": {
58
39
  "shortcut": {
59
- "command": "node",
40
+ "command": "npx",
60
41
  "args": [
61
- "/path/to/this/repo/mcp-server-shortcut"
42
+ "@shortcut/mcp"
62
43
  ],
63
44
  "env": {
64
45
  "SHORTCUT_API_TOKEN": "<YOUR_SHORTCUT_API_TOKEN>"
@@ -66,4 +47,18 @@ See the [official Cursor docs](https://docs.cursor.com/context/model-context-pro
66
47
  }
67
48
  }
68
49
  }
50
+ ```
51
+
52
+ ## Development
53
+
54
+ ## Installation
55
+
56
+ ```bash
57
+ npm install
58
+ ```
59
+
60
+ ## Build
61
+
62
+ ```bash
63
+ npm run build
69
64
  ```
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
- #!/usr/bin/env bun
2
- // @bun
1
+ #!/usr/bin/env node
3
2
  import { createRequire } from "node:module";
4
3
  var __create = Object.create;
5
4
  var __getProtoOf = Object.getPrototypeOf;
@@ -16457,8 +16456,8 @@ var require_lib = __commonJS((exports) => {
16457
16456
  });
16458
16457
 
16459
16458
  // package.json
16460
- var name = "@useshortcut/mcp";
16461
- var version = "0.0.0";
16459
+ var name = "@shortcut/mcp";
16460
+ var version = "0.1.0";
16462
16461
 
16463
16462
  // node_modules/zod/lib/index.mjs
16464
16463
  var util;
@@ -23692,11 +23691,13 @@ var formatStoryList = (stories, users) => {
23692
23691
  return stories
23693
23692
  .map(
23694
23693
  (story) =>
23695
- `- sc-${story.id}: ${story.name} (Type: ${story.story_type}, State: ${story.completed ? "Completed" : story.started ? "In Progress" : "Not Started"}, Owners: ${story.owner_ids
23696
- .map((ownerId) => users.get(ownerId))
23697
- .filter((owner) => owner !== null)
23698
- .map((owner) => `@${owner.profile.mention_name}`)
23699
- .join(", ")})`,
23694
+ `- sc-${story.id}: ${story.name} (Type: ${story.story_type}, State: ${story.completed ? "Completed" : story.started ? "In Progress" : "Not Started"}, Team: ${story.group_id ? `${story.group_id}` : "[None]"}, Epic: ${story.epic_id ? `${story.epic_id}` : "[None]"}, Iteration: ${story.iteration_id ? `${story.iteration_id}` : "[None]"}, Owners: ${
23695
+ story.owner_ids
23696
+ .map((ownerId) => users.get(ownerId))
23697
+ .filter((owner) => owner !== null)
23698
+ .map((owner) => `@${owner.profile.mention_name}`)
23699
+ .join(", ") || "[None]"
23700
+ })`,
23700
23701
  )
23701
23702
  .join(`
23702
23703
  `);
@@ -23881,7 +23882,7 @@ class StoryTools extends BaseTools {
23881
23882
  isUnstarted: is("unstarted"),
23882
23883
  isUnestimated: is("unestimated"),
23883
23884
  isOverdue: is("overdue"),
23884
- isArchived: is("archived"),
23885
+ isArchived: is("archived").default(false),
23885
23886
  isBlocker: is("blocking"),
23886
23887
  isBlocked: is("blocked"),
23887
23888
  hasComment: has("a comment"),
@@ -23970,19 +23971,20 @@ The story will be added to the default state for the workflow.
23970
23971
  });
23971
23972
  return this.toResult(`Unassigned current user as owner of story sc-${storyPublicId}`);
23972
23973
  }
23974
+ createBranchName(currentUser, story) {
23975
+ return `${currentUser.mention_name}/sc-${story.id}/${story.name
23976
+ .toLowerCase()
23977
+ .replace(/\s+/g, "-")
23978
+ .replace(/[^\w\-]/g, "")}`.substring(0, 50);
23979
+ }
23973
23980
  async getStoryBranchName(storyPublicId) {
23974
23981
  const currentUser = await this.client.getCurrentUser();
23975
23982
  if (!currentUser) throw new Error("Unable to find current user");
23976
23983
  const story = await this.client.getStory(storyPublicId);
23977
23984
  if (!story)
23978
23985
  throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}`);
23979
- const branchName = `${currentUser.mention_name}/sc-${storyPublicId}/${story.name
23980
- .toLowerCase()
23981
- .replace(/\s+/g, "-")
23982
- .replace(/[^\w\-]/g, "")}`;
23983
- return this.toResult(
23984
- `Branch name for story sc-${storyPublicId}: ${branchName.substring(0, 50)}`,
23985
- );
23986
+ const branchName = story.formatted_vcs_branch_name || this.createBranchName(currentUser, story);
23987
+ return this.toResult(`Branch name for story sc-${storyPublicId}: ${branchName}`);
23986
23988
  }
23987
23989
  async createStory({ name: name2, description, type, owner, epic, team, workflow }) {
23988
23990
  if (!workflow && !team) throw new Error("Team or Workflow has to be specified");
@@ -24018,7 +24020,11 @@ ${formatStoryList(stories, users)}`);
24018
24020
  const story = await this.client.getStory(storyPublicId);
24019
24021
  if (!story)
24020
24022
  throw new Error(`Failed to retrieve Shortcut story with public ID: ${storyPublicId}.`);
24021
- const owners = await this.client.getUserMap(story.owner_ids);
24023
+ const relatedUsers = new Set([
24024
+ ...story.owner_ids,
24025
+ ...story.comments.flatMap((c) => c.author_id),
24026
+ ]);
24027
+ const users = await this.client.getUserMap([...relatedUsers].filter((id) => !!id));
24022
24028
  return this.toResult(`Story: sc-${storyPublicId}
24023
24029
  URL: ${story.app_url}
24024
24030
  Name: ${story.name}
@@ -24029,22 +24035,28 @@ Started: ${story.started ? "Yes" : "No"}
24029
24035
  Blocked: ${story.blocked ? "Yes" : "No"}
24030
24036
  Blocking: ${story.blocker ? "Yes" : "No"}
24031
24037
  Due date: ${story.deadline ? story.deadline : "[None]"}
24038
+ Team: ${story.group_id ? `${story.group_id}` : "[None]"}
24032
24039
  Owners:${
24033
24040
  story.owner_ids.length
24034
24041
  ? `
24035
- ${formatMemberList(story.owner_ids, owners)}`
24042
+ ${formatMemberList(story.owner_ids, users)}`
24036
24043
  : " [None]"
24037
24044
  }
24045
+ Epic: ${story.epic_id ? `${story.epic_id}` : "[None]"}
24046
+ Iteration: ${story.iteration_id ? `${story.iteration_id}` : "[None]"}
24038
24047
 
24039
24048
  Description:
24040
24049
  ${story.description}
24041
24050
 
24042
24051
  Comments:
24043
24052
  ${(story.comments || [])
24044
- .map(
24045
- (comment) => `- From: ${comment.author_id} on ${comment.created_at}.
24046
- ${comment.text || ""}`,
24047
- )
24053
+ .map((comment) => {
24054
+ const mentionName = comment.author_id
24055
+ ? users.get(comment.author_id)?.profile?.mention_name
24056
+ : null;
24057
+ return `- From: ${mentionName ? `@${mentionName}` : `id=${comment.author_id}` || "[Unknown]"} on ${comment.created_at}.
24058
+ ${comment.text || ""}`;
24059
+ })
24048
24060
  .join(`
24049
24061
 
24050
24062
  `)}`);
@@ -24112,7 +24124,7 @@ class EpicTools extends BaseTools {
24112
24124
  isUnstarted: is("unstarted"),
24113
24125
  isStarted: is("started"),
24114
24126
  isDone: is("completed"),
24115
- isArchived: is("archived"),
24127
+ isArchived: is("archived").default(false),
24116
24128
  isOverdue: is("overdue"),
24117
24129
  hasOwner: has("an owner"),
24118
24130
  hasComment: has("a comment"),
@@ -24149,6 +24161,8 @@ Archived: ${epic.archived ? "Yes" : "No"}
24149
24161
  Completed: ${epic.completed ? "Yes" : "No"}
24150
24162
  Started: ${epic.started ? "Yes" : "No"}
24151
24163
  Due date: ${epic.deadline ? epic.deadline : "[Not set]"}
24164
+ Team: ${epic.group_id ? `${epic.group_id}` : "[None]"}
24165
+ Objective: ${epic.milestone_id ? `${epic.milestone_id}` : "[None]"}
24152
24166
 
24153
24167
  Description:
24154
24168
  ${epic.description}`);
@@ -24315,6 +24329,7 @@ Start date: ${iteration.start_date}
24315
24329
  End date: ${iteration.end_date}
24316
24330
  Completed: ${iteration.status === "completed" ? "Yes" : "No"}
24317
24331
  Started: ${iteration.status === "started" ? "Yes" : "No"}
24332
+ Team: ${iteration.group_ids?.length ? `${iteration.group_ids.join(", ")}` : "[None]"}
24318
24333
 
24319
24334
  Description:
24320
24335
  ${iteration.description}`);
package/package.json CHANGED
@@ -1,20 +1,23 @@
1
1
  {
2
2
  "name": "@shortcut/mcp",
3
+ "author": "Shortcut (https://www.shortcut.com)",
3
4
  "repository": {
4
5
  "type": "git",
5
6
  "url": "https://github.com/useshortcut/mcp-server-shortcut.git"
6
7
  },
7
8
  "keywords": ["shortcut", "mcp", "modelcontextprotocol"],
8
9
  "license": "MIT",
9
- "version": "0.1.0",
10
+ "version": "0.1.2",
10
11
  "type": "module",
11
- "private": false,
12
12
  "main": "dist/index.js",
13
- "bin": "dist/shortcut-mcp",
14
- "files": ["dist", "README.md", "LICENSE"],
13
+ "bin": {
14
+ "mcp-server-shortcut": "dist/index.js"
15
+ },
16
+ "files": ["dist"],
15
17
  "devDependencies": {
16
18
  "@biomejs/biome": "^1.9.4",
17
19
  "@types/bun": "latest",
20
+ "bun": "^1.2.5",
18
21
  "husky": "^9.1.7",
19
22
  "shx": "^0.3.4"
20
23
  },