@shortcut/mcp 0.16.0 → 0.17.0

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/README.md CHANGED
@@ -188,6 +188,9 @@ Or you can edit the local JSON file directly:
188
188
  ### Documents
189
189
 
190
190
  - **documents-create** - Create a new document in Shortcut with HTML content
191
+ - **documents-list** - List all documents in Shortcut
192
+ - **documents-search** - Search for documents
193
+ - **documents-get-by-id** - Retrieve a specific document in markdown format by its ID
191
194
 
192
195
  ## Limit tools
193
196
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { CustomMcpServer, DocumentTools, EpicTools, IterationTools, ObjectiveTools, ShortcutClientWrapper, StoryTools, TeamTools, UserTools, WorkflowTools } from "./workflows-ChA_XcfF.js";
2
+ import { CustomMcpServer, DocumentTools, EpicTools, IterationTools, ObjectiveTools, ShortcutClientWrapper, StoryTools, TeamTools, UserTools, WorkflowTools } from "./workflows-TjriXV16.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { ShortcutClient } from "@shortcut/client";
5
5
 
@@ -1,4 +1,4 @@
1
- import { CustomMcpServer, DocumentTools, EpicTools, IterationTools, ObjectiveTools, ShortcutClientWrapper, StoryTools, TeamTools, UserTools, WorkflowTools } from "./workflows-ChA_XcfF.js";
1
+ import { CustomMcpServer, DocumentTools, EpicTools, IterationTools, ObjectiveTools, ShortcutClientWrapper, StoryTools, TeamTools, UserTools, WorkflowTools } from "./workflows-TjriXV16.js";
2
2
  import { ShortcutClient } from "@shortcut/client";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
@@ -422,6 +422,40 @@ var ShortcutClientWrapper = class {
422
422
  if (!doc) throw new Error(`Failed to create the document: ${response.status}`);
423
423
  return doc;
424
424
  }
425
+ async listDocs() {
426
+ const response = await this.client.listDocs();
427
+ if (response.status === 403) throw new Error("Docs feature disabled for this workspace.");
428
+ return response?.data ?? null;
429
+ }
430
+ async searchDocuments({ title, archived, createdByCurrentUser, followedByCurrentUser, pageSize = 25, nextPageToken }) {
431
+ const response = await this.client.searchDocuments({
432
+ title,
433
+ archived,
434
+ created_by_me: createdByCurrentUser,
435
+ followed_by_me: followedByCurrentUser,
436
+ page_size: pageSize,
437
+ next: nextPageToken
438
+ });
439
+ if (response.status === 403) throw new Error("Docs feature disabled for this workspace.");
440
+ const documents = response?.data?.data;
441
+ const total = response?.data?.total;
442
+ const next = response?.data?.next;
443
+ if (!documents) return {
444
+ documents: null,
445
+ total: null,
446
+ next_page_token: null
447
+ };
448
+ return {
449
+ documents,
450
+ total,
451
+ next_page_token: this.getNextPageToken(next)
452
+ };
453
+ }
454
+ async getDocById(docId) {
455
+ const response = await this.client.getDoc(docId);
456
+ if (response.status === 403) throw new Error("Docs feature disabled for this workspace.");
457
+ return response?.data ?? null;
458
+ }
425
459
  async uploadFile(storyId, filePath) {
426
460
  const fileContent = readFileSync(filePath);
427
461
  const fileName = basename(filePath);
@@ -447,7 +481,7 @@ var ShortcutClientWrapper = class {
447
481
  //#endregion
448
482
  //#region package.json
449
483
  var name = "@shortcut/mcp";
450
- var version = "0.16.0";
484
+ var version = "0.17.0";
451
485
 
452
486
  //#endregion
453
487
  //#region src/mcp/CustomMcpServer.ts
@@ -827,6 +861,20 @@ var DocumentTools = class DocumentTools extends BaseTools {
827
861
  title: z.string().max(256).describe("The title for the new document (max 256 characters)"),
828
862
  content: z.string().describe("The content for the new document in HTML format (e.g., <p>Hello</p>, <h1>Title</h1>, <ul><li>Item</li></ul>)")
829
863
  }, async ({ title, content }) => await tools.createDocument(title, content));
864
+ server.addToolWithReadAccess("documents-list", "List all documents in Shortcut.", async () => await tools.listDocuments());
865
+ server.addToolWithReadAccess("documents-search", "Find documents.", {
866
+ 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."),
867
+ title: z.string().describe("Find documents matching the specified name"),
868
+ archived: z.boolean().optional().describe("Find only documents matching the specified archived status"),
869
+ createdByCurrentUser: z.boolean().optional().describe("Find only documents created by current user"),
870
+ followedByCurrentUser: z.boolean().optional().describe("Find only documents followed by current user")
871
+ }, async ({ nextPageToken, title, archived, createdByCurrentUser, followedByCurrentUser }) => await tools.searchDocuments({
872
+ title,
873
+ archived,
874
+ createdByCurrentUser,
875
+ followedByCurrentUser
876
+ }, nextPageToken));
877
+ server.addToolWithReadAccess("documents-get-by-id", "Get a document as markdown by its ID", { docId: z.string().describe("The ID of the document to retrieve") }, async ({ docId }) => await tools.getDocumentById(docId));
830
878
  return tools;
831
879
  }
832
880
  async createDocument(title, content) {
@@ -845,6 +893,40 @@ var DocumentTools = class DocumentTools extends BaseTools {
845
893
  return this.toResult(`Failed to create document: ${errorMessage}`);
846
894
  }
847
895
  }
896
+ async listDocuments() {
897
+ try {
898
+ const docs = await this.client.listDocs();
899
+ if (!docs?.length) return this.toResult("No documents were found.");
900
+ return this.toResult(`Found ${docs.length} documents.`, docs);
901
+ } catch (error) {
902
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
903
+ return this.toResult(`Failed to list documents: ${errorMessage}`);
904
+ }
905
+ }
906
+ async searchDocuments(params, nextPageToken) {
907
+ try {
908
+ const { documents, total, next_page_token } = await this.client.searchDocuments({
909
+ ...params,
910
+ nextPageToken
911
+ });
912
+ if (!documents) throw new Error(`Failed to search for document matching your query.`);
913
+ if (!documents.length) return this.toResult(`Result: No documents found.`);
914
+ return this.toResult(`Result (${documents.length} shown of ${total} total documents found):`, documents, next_page_token);
915
+ } catch (error) {
916
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
917
+ return this.toResult(`Failed to search documents: ${errorMessage}`);
918
+ }
919
+ }
920
+ async getDocumentById(docId) {
921
+ try {
922
+ const doc = await this.client.getDocById(docId);
923
+ if (!doc) return this.toResult(`Document with ID ${docId} not found.`);
924
+ return this.toResult(`Document with ID ${docId}`, doc);
925
+ } catch (error) {
926
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
927
+ return this.toResult(`Failed to get document: ${errorMessage}`);
928
+ }
929
+ }
848
930
  };
849
931
 
850
932
  //#endregion
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "modelcontextprotocol"
13
13
  ],
14
14
  "license": "MIT",
15
- "version": "0.16.0",
15
+ "version": "0.17.0",
16
16
  "type": "module",
17
17
  "main": "dist/index.js",
18
18
  "bin": {
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@modelcontextprotocol/sdk": "^1.25.1",
38
- "@shortcut/client": "^2.2.0",
38
+ "@shortcut/client": "^3.1.0",
39
39
  "express": "^4.18.2",
40
40
  "pino": "^9.5.0",
41
41
  "pino-http": "^10.3.0",