@postman/postman-mcp-server 2.4.2 → 2.5.1

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 (127) hide show
  1. package/README.md +31 -15
  2. package/dist/package.json +11 -20
  3. package/dist/src/clients/postman.js +2 -4
  4. package/dist/src/constants.js +5 -0
  5. package/dist/src/enabledResources.js +24 -2
  6. package/dist/src/index.js +11 -6
  7. package/dist/src/tools/createCollection.js +35 -35
  8. package/dist/src/tools/createCollectionComment.js +1 -5
  9. package/dist/src/tools/createCollectionFolder.js +1 -5
  10. package/dist/src/tools/createCollectionFork.js +1 -5
  11. package/dist/src/tools/createCollectionRequest.js +1 -5
  12. package/dist/src/tools/createCollectionResponse.js +1 -5
  13. package/dist/src/tools/createEnvironment.js +1 -5
  14. package/dist/src/tools/createFolderComment.js +1 -5
  15. package/dist/src/tools/createMock.js +1 -5
  16. package/dist/src/tools/createMonitor.js +1 -5
  17. package/dist/src/tools/createRequestComment.js +1 -5
  18. package/dist/src/tools/createResponseComment.js +1 -5
  19. package/dist/src/tools/createSpec.js +1 -5
  20. package/dist/src/tools/createSpecFile.js +1 -5
  21. package/dist/src/tools/createWorkspace.js +1 -5
  22. package/dist/src/tools/deleteApiCollectionComment.js +1 -5
  23. package/dist/src/tools/deleteCollection.js +1 -5
  24. package/dist/src/tools/deleteCollectionComment.js +1 -5
  25. package/dist/src/tools/deleteCollectionFolder.js +1 -5
  26. package/dist/src/tools/deleteCollectionRequest.js +1 -5
  27. package/dist/src/tools/deleteCollectionResponse.js +1 -5
  28. package/dist/src/tools/deleteEnvironment.js +1 -5
  29. package/dist/src/tools/deleteFolderComment.js +1 -5
  30. package/dist/src/tools/deleteMock.js +1 -5
  31. package/dist/src/tools/deleteMonitor.js +1 -5
  32. package/dist/src/tools/deletePanElementOrFolder.js +1 -5
  33. package/dist/src/tools/deleteRequestComment.js +1 -5
  34. package/dist/src/tools/deleteResponseComment.js +1 -5
  35. package/dist/src/tools/deleteSpec.js +1 -5
  36. package/dist/src/tools/deleteSpecFile.js +1 -5
  37. package/dist/src/tools/deleteWorkspace.js +1 -5
  38. package/dist/src/tools/duplicateCollection.js +1 -5
  39. package/dist/src/tools/generateCollection.js +1 -5
  40. package/dist/src/tools/generateSpecFromCollection.js +1 -5
  41. package/dist/src/tools/getAllElementsAndFolders.js +1 -5
  42. package/dist/src/tools/getAllPanAddElementRequests.js +1 -5
  43. package/dist/src/tools/getAllSpecs.js +1 -5
  44. package/dist/src/tools/getAsyncSpecTaskStatus.js +1 -5
  45. package/dist/src/tools/getAuthenticatedUser.js +1 -5
  46. package/dist/src/tools/getCodeGenerationInstructions.js +439 -0
  47. package/dist/src/tools/getCollection.js +1 -5
  48. package/dist/src/tools/getCollectionComments.js +1 -5
  49. package/dist/src/tools/getCollectionFolder.js +1 -5
  50. package/dist/src/tools/getCollectionForks.js +1 -5
  51. package/dist/src/tools/getCollectionMap.js +101 -0
  52. package/dist/src/tools/getCollectionRequest.js +1 -5
  53. package/dist/src/tools/getCollectionResponse.js +1 -5
  54. package/dist/src/tools/getCollectionTags.js +1 -5
  55. package/dist/src/tools/getCollectionUpdatesTasks.js +1 -5
  56. package/dist/src/tools/getCollections.js +1 -5
  57. package/dist/src/tools/getCollectionsForkedByUser.js +1 -5
  58. package/dist/src/tools/getDuplicateCollectionTaskStatus.js +1 -5
  59. package/dist/src/tools/getEnabledTools.js +51 -0
  60. package/dist/src/tools/getEnvironment.js +1 -5
  61. package/dist/src/tools/getEnvironments.js +1 -5
  62. package/dist/src/tools/getFolderComments.js +1 -5
  63. package/dist/src/tools/getGeneratedCollectionSpecs.js +1 -5
  64. package/dist/src/tools/getMock.js +1 -5
  65. package/dist/src/tools/getMocks.js +1 -5
  66. package/dist/src/tools/getMonitor.js +1 -5
  67. package/dist/src/tools/getMonitors.js +1 -5
  68. package/dist/src/tools/getRequestComments.js +1 -5
  69. package/dist/src/tools/getResponseComments.js +1 -5
  70. package/dist/src/tools/getSourceCollectionStatus.js +1 -5
  71. package/dist/src/tools/getSpec.js +1 -5
  72. package/dist/src/tools/getSpecCollections.js +1 -5
  73. package/dist/src/tools/getSpecDefinition.js +1 -5
  74. package/dist/src/tools/getSpecFile.js +1 -5
  75. package/dist/src/tools/getSpecFiles.js +1 -5
  76. package/dist/src/tools/getStatusOfAnAsyncApiTask.js +1 -5
  77. package/dist/src/tools/getTaggedEntities.js +1 -5
  78. package/dist/src/tools/getWorkspace.js +1 -5
  79. package/dist/src/tools/getWorkspaceGlobalVariables.js +1 -5
  80. package/dist/src/tools/getWorkspaceTags.js +1 -5
  81. package/dist/src/tools/getWorkspaces.js +1 -5
  82. package/dist/src/tools/mergeCollectionFork.js +1 -5
  83. package/dist/src/tools/patchCollection.js +13 -17
  84. package/dist/src/tools/patchEnvironment.js +1 -5
  85. package/dist/src/tools/postPanElementOrFolder.js +1 -5
  86. package/dist/src/tools/publishDocumentation.js +1 -5
  87. package/dist/src/tools/publishMock.js +1 -5
  88. package/dist/src/tools/pullCollectionChanges.js +1 -5
  89. package/dist/src/tools/putCollection.js +36 -36
  90. package/dist/src/tools/putEnvironment.js +1 -5
  91. package/dist/src/tools/resolveCommentThread.js +1 -5
  92. package/dist/src/tools/runCollection.js +4 -82
  93. package/dist/src/tools/runMonitor.js +1 -5
  94. package/dist/src/tools/runner/executor.js +165 -0
  95. package/dist/src/tools/runner/fetchers.js +33 -0
  96. package/dist/src/tools/runner/index.js +20 -0
  97. package/dist/src/tools/runner/models.js +1 -0
  98. package/dist/src/tools/runner/parsers.js +8 -0
  99. package/dist/src/tools/runner/telemetry.js +178 -0
  100. package/dist/src/tools/searchPostmanElements.js +69 -0
  101. package/dist/src/tools/syncCollectionWithSpec.js +1 -5
  102. package/dist/src/tools/syncSpecWithCollection.js +1 -5
  103. package/dist/src/tools/transferCollectionFolders.js +1 -5
  104. package/dist/src/tools/transferCollectionRequests.js +1 -5
  105. package/dist/src/tools/transferCollectionResponses.js +1 -5
  106. package/dist/src/tools/unpublishDocumentation.js +1 -5
  107. package/dist/src/tools/unpublishMock.js +1 -5
  108. package/dist/src/tools/updateApiCollectionComment.js +1 -5
  109. package/dist/src/tools/updateCollectionComment.js +1 -5
  110. package/dist/src/tools/updateCollectionFolder.js +1 -5
  111. package/dist/src/tools/updateCollectionRequest.js +1 -5
  112. package/dist/src/tools/updateCollectionResponse.js +1 -5
  113. package/dist/src/tools/updateCollectionTags.js +1 -5
  114. package/dist/src/tools/updateFolderComment.js +1 -5
  115. package/dist/src/tools/updateMock.js +1 -5
  116. package/dist/src/tools/updateMonitor.js +1 -5
  117. package/dist/src/tools/updatePanElementOrFolder.js +1 -5
  118. package/dist/src/tools/updateRequestComment.js +1 -5
  119. package/dist/src/tools/updateResponseComment.js +1 -5
  120. package/dist/src/tools/updateSpecFile.js +1 -5
  121. package/dist/src/tools/updateSpecProperties.js +1 -5
  122. package/dist/src/tools/updateWorkspace.js +1 -5
  123. package/dist/src/tools/updateWorkspaceGlobalVariables.js +1 -5
  124. package/dist/src/tools/updateWorkspaceTags.js +1 -5
  125. package/dist/src/tools/utils/toolHelpers.js +6 -0
  126. package/package.json +11 -20
  127. package/dist/src/tools/utils/runner.js +0 -84
@@ -1,10 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { ContentType } from '../clients/postman.js';
3
- import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
4
- function asMcpError(error) {
5
- const cause = error?.cause ?? String(error);
6
- return new McpError(ErrorCode.InternalError, cause);
7
- }
3
+ import { asMcpError, McpError } from './utils/toolHelpers.js';
8
4
  export const method = 'putCollection';
9
5
  export const description = "Replaces the contents of a collection using the [Postman Collection v2.1.0 schema format](https://schema.postman.com/collection/json/v2.1.0/draft-07/docs/index.html). Include the collection's ID values in the request body. If you do not, the endpoint removes the existing items and creates new items.\n\nTo perform an update asynchronously, use the \\`Prefer\\` header with the \\`respond-async\\` value. When performing an async update, this endpoint returns a HTTP \\`202 Accepted\\` response.\n\n**Note:**\n\n- The maximum collection size this endpoint accepts cannot exceed 100 MB.\n- If you don't include the collection items' ID values from the request body, the endpoint **removes** the existing items and recreates the items with new ID values.\n- To copy another collection's contents to the given collection, remove all ID values before you pass it in this endpoint. If you do not, this endpoint returns an error. These values include the \\`id\\`, \\`uid\\`, and \\`postman_id\\` values.\n- For protocol profile behavior, refer to Postman's [Protocol Profile Behavior documentation](https://github.com/postmanlabs/postman-runtime/blob/develop/docs/protocol-profile-behavior.md).\n";
10
6
  export const parameters = z.object({
@@ -164,7 +160,7 @@ export const parameters = z.object({
164
160
  .object({
165
161
  key: z.string().describe("The auth method's key value."),
166
162
  value: z
167
- .union([z.string(), z.array(z.record(z.any()))])
163
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
168
164
  .describe("The key's value.")
169
165
  .optional(),
170
166
  type: z
@@ -180,7 +176,7 @@ export const parameters = z.object({
180
176
  .object({
181
177
  key: z.string().describe("The auth method's key value."),
182
178
  value: z
183
- .union([z.string(), z.array(z.record(z.any()))])
179
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
184
180
  .describe("The key's value.")
185
181
  .optional(),
186
182
  type: z
@@ -196,7 +192,7 @@ export const parameters = z.object({
196
192
  .object({
197
193
  key: z.string().describe("The auth method's key value."),
198
194
  value: z
199
- .union([z.string(), z.array(z.record(z.any()))])
195
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
200
196
  .describe("The key's value.")
201
197
  .optional(),
202
198
  type: z
@@ -212,7 +208,7 @@ export const parameters = z.object({
212
208
  .object({
213
209
  key: z.string().describe("The auth method's key value."),
214
210
  value: z
215
- .union([z.string(), z.array(z.record(z.any()))])
211
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
216
212
  .describe("The key's value.")
217
213
  .optional(),
218
214
  type: z
@@ -228,7 +224,7 @@ export const parameters = z.object({
228
224
  .object({
229
225
  key: z.string().describe("The auth method's key value."),
230
226
  value: z
231
- .union([z.string(), z.array(z.record(z.any()))])
227
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
232
228
  .describe("The key's value.")
233
229
  .optional(),
234
230
  type: z
@@ -244,7 +240,7 @@ export const parameters = z.object({
244
240
  .object({
245
241
  key: z.string().describe("The auth method's key value."),
246
242
  value: z
247
- .union([z.string(), z.array(z.record(z.any()))])
243
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
248
244
  .describe("The key's value.")
249
245
  .optional(),
250
246
  type: z
@@ -260,7 +256,7 @@ export const parameters = z.object({
260
256
  .object({
261
257
  key: z.string().describe("The auth method's key value."),
262
258
  value: z
263
- .union([z.string(), z.array(z.record(z.any()))])
259
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
264
260
  .describe("The key's value.")
265
261
  .optional(),
266
262
  type: z
@@ -276,7 +272,7 @@ export const parameters = z.object({
276
272
  .object({
277
273
  key: z.string().describe("The auth method's key value."),
278
274
  value: z
279
- .union([z.string(), z.array(z.record(z.any()))])
275
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
280
276
  .describe("The key's value.")
281
277
  .optional(),
282
278
  type: z
@@ -292,7 +288,7 @@ export const parameters = z.object({
292
288
  .object({
293
289
  key: z.string().describe("The auth method's key value."),
294
290
  value: z
295
- .union([z.string(), z.array(z.record(z.any()))])
291
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
296
292
  .describe("The key's value.")
297
293
  .optional(),
298
294
  type: z
@@ -308,7 +304,7 @@ export const parameters = z.object({
308
304
  .object({
309
305
  key: z.string().describe("The auth method's key value."),
310
306
  value: z
311
- .union([z.string(), z.array(z.record(z.any()))])
307
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
312
308
  .describe("The key's value.")
313
309
  .optional(),
314
310
  type: z
@@ -324,7 +320,7 @@ export const parameters = z.object({
324
320
  .object({
325
321
  key: z.string().describe("The auth method's key value."),
326
322
  value: z
327
- .union([z.string(), z.array(z.record(z.any()))])
323
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
328
324
  .describe("The key's value.")
329
325
  .optional(),
330
326
  type: z
@@ -340,7 +336,7 @@ export const parameters = z.object({
340
336
  .object({
341
337
  key: z.string().describe("The auth method's key value."),
342
338
  value: z
343
- .union([z.string(), z.array(z.record(z.any()))])
339
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
344
340
  .describe("The key's value.")
345
341
  .optional(),
346
342
  type: z
@@ -399,7 +395,7 @@ export const parameters = z.object({
399
395
  .describe('A list of x-www-form-encoded key/value pairs.')
400
396
  .optional(),
401
397
  formdata: z
402
- .array(z.record(z.any()).and(z.union([
398
+ .array(z.record(z.string(), z.unknown()).and(z.union([
403
399
  z.object({
404
400
  key: z.string().describe('The key value.').optional(),
405
401
  value: z.string().describe("The key's value.").optional(),
@@ -417,7 +413,7 @@ export const parameters = z.object({
417
413
  z.object({
418
414
  key: z.string().describe('The key value.').optional(),
419
415
  src: z
420
- .any()
416
+ .unknown()
421
417
  .superRefine((x, ctx) => {
422
418
  const schemas = [z.string().nullable(), z.array(z.string())];
423
419
  const errors = schemas.reduce((errors, schema) => ((result) => result.error ? [...errors, result.error] : errors)(schema.safeParse(x)), []);
@@ -467,7 +463,7 @@ export const parameters = z.object({
467
463
  .describe('If the `mode` value is `graphql`, an object containing the GraphQL request information.')
468
464
  .optional(),
469
465
  options: z
470
- .record(z.any())
466
+ .record(z.string(), z.unknown())
471
467
  .describe('Additional configurations and options set for various modes.')
472
468
  .optional(),
473
469
  })
@@ -476,6 +472,10 @@ export const parameters = z.object({
476
472
  })
477
473
  .describe('Information about the collection request.')
478
474
  .optional(),
475
+ response: z
476
+ .array(z.unknown().describe("Information about the request's response."))
477
+ .describe("A list of the collection's responses.")
478
+ .optional(),
479
479
  protocolProfileBehavior: z
480
480
  .object({
481
481
  strictSSL: z
@@ -617,7 +617,7 @@ export const parameters = z.object({
617
617
  .object({
618
618
  key: z.string().describe("The auth method's key value."),
619
619
  value: z
620
- .union([z.string(), z.array(z.record(z.any()))])
620
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
621
621
  .describe("The key's value.")
622
622
  .optional(),
623
623
  type: z
@@ -633,7 +633,7 @@ export const parameters = z.object({
633
633
  .object({
634
634
  key: z.string().describe("The auth method's key value."),
635
635
  value: z
636
- .union([z.string(), z.array(z.record(z.any()))])
636
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
637
637
  .describe("The key's value.")
638
638
  .optional(),
639
639
  type: z
@@ -649,7 +649,7 @@ export const parameters = z.object({
649
649
  .object({
650
650
  key: z.string().describe("The auth method's key value."),
651
651
  value: z
652
- .union([z.string(), z.array(z.record(z.any()))])
652
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
653
653
  .describe("The key's value.")
654
654
  .optional(),
655
655
  type: z
@@ -665,7 +665,7 @@ export const parameters = z.object({
665
665
  .object({
666
666
  key: z.string().describe("The auth method's key value."),
667
667
  value: z
668
- .union([z.string(), z.array(z.record(z.any()))])
668
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
669
669
  .describe("The key's value.")
670
670
  .optional(),
671
671
  type: z
@@ -681,7 +681,7 @@ export const parameters = z.object({
681
681
  .object({
682
682
  key: z.string().describe("The auth method's key value."),
683
683
  value: z
684
- .union([z.string(), z.array(z.record(z.any()))])
684
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
685
685
  .describe("The key's value.")
686
686
  .optional(),
687
687
  type: z
@@ -697,7 +697,7 @@ export const parameters = z.object({
697
697
  .object({
698
698
  key: z.string().describe("The auth method's key value."),
699
699
  value: z
700
- .union([z.string(), z.array(z.record(z.any()))])
700
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
701
701
  .describe("The key's value.")
702
702
  .optional(),
703
703
  type: z
@@ -713,7 +713,7 @@ export const parameters = z.object({
713
713
  .object({
714
714
  key: z.string().describe("The auth method's key value."),
715
715
  value: z
716
- .union([z.string(), z.array(z.record(z.any()))])
716
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
717
717
  .describe("The key's value.")
718
718
  .optional(),
719
719
  type: z
@@ -729,7 +729,7 @@ export const parameters = z.object({
729
729
  .object({
730
730
  key: z.string().describe("The auth method's key value."),
731
731
  value: z
732
- .union([z.string(), z.array(z.record(z.any()))])
732
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
733
733
  .describe("The key's value.")
734
734
  .optional(),
735
735
  type: z
@@ -745,7 +745,7 @@ export const parameters = z.object({
745
745
  .object({
746
746
  key: z.string().describe("The auth method's key value."),
747
747
  value: z
748
- .union([z.string(), z.array(z.record(z.any()))])
748
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
749
749
  .describe("The key's value.")
750
750
  .optional(),
751
751
  type: z
@@ -761,7 +761,7 @@ export const parameters = z.object({
761
761
  .object({
762
762
  key: z.string().describe("The auth method's key value."),
763
763
  value: z
764
- .union([z.string(), z.array(z.record(z.any()))])
764
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
765
765
  .describe("The key's value.")
766
766
  .optional(),
767
767
  type: z
@@ -777,7 +777,7 @@ export const parameters = z.object({
777
777
  .object({
778
778
  key: z.string().describe("The auth method's key value."),
779
779
  value: z
780
- .union([z.string(), z.array(z.record(z.any()))])
780
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
781
781
  .describe("The key's value.")
782
782
  .optional(),
783
783
  type: z
@@ -793,7 +793,7 @@ export const parameters = z.object({
793
793
  .object({
794
794
  key: z.string().describe("The auth method's key value."),
795
795
  value: z
796
- .union([z.string(), z.array(z.record(z.any()))])
796
+ .union([z.string(), z.array(z.record(z.string(), z.unknown()))])
797
797
  .describe("The key's value.")
798
798
  .optional(),
799
799
  type: z
@@ -882,14 +882,14 @@ export const annotations = {
882
882
  destructiveHint: false,
883
883
  idempotentHint: true,
884
884
  };
885
- export async function handler(params, extra) {
885
+ export async function handler(args, extra) {
886
886
  try {
887
- const endpoint = `/collections/${params.collectionId}`;
887
+ const endpoint = `/collections/${args.collectionId}`;
888
888
  const query = new URLSearchParams();
889
889
  const url = query.toString() ? `${endpoint}?${query.toString()}` : endpoint;
890
890
  const bodyPayload = {};
891
- if (params.collection !== undefined)
892
- bodyPayload.collection = params.collection;
891
+ if (args.collection !== undefined)
892
+ bodyPayload.collection = args.collection;
893
893
  const options = {
894
894
  body: JSON.stringify(bodyPayload),
895
895
  contentType: ContentType.Json,
@@ -1,10 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import { ContentType } from '../clients/postman.js';
3
- import { McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
4
- function asMcpError(error) {
5
- const cause = error?.cause ?? String(error);
6
- return new McpError(ErrorCode.InternalError, cause);
7
- }
3
+ import { asMcpError, McpError } from './utils/toolHelpers.js';
8
4
  export const method = 'putEnvironment';
9
5
  export const description = 'Replaces all the contents of an environment with the given information.\n\n**Note:**\n\n- The request body size cannot exceed the maximum allowed size of 30MB.\n- If you receive an HTTP \\`411 Length Required\\` error response, manually pass the \\`Content-Length\\` header and its value in the request header.\n';
10
6
  export const parameters = z.object({
@@ -1,9 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
3
- function asMcpError(error) {
4
- const cause = error?.cause ?? String(error);
5
- return new McpError(ErrorCode.InternalError, cause);
6
- }
2
+ import { asMcpError, McpError } from './utils/toolHelpers.js';
7
3
  export const method = 'resolveCommentThread';
8
4
  export const description = 'Resolves a comment and any associated replies. On success, this returns an HTTP \\`204 No Content\\` response.\n\nComment thread IDs return in the GET comments response for [APIs](https://www.postman.com/postman/workspace/postman-public-workspace/request/12959542-2103ea20-f7de-4628-90e6-b823b3084a52), [collections](https://www.postman.com/postman/workspace/postman-public-workspace/request/12959542-a6582e0a-9382-4760-8b91-53a8aa6cb8d7), and [collection items](https://www.postman.com/postman/workspace/postman-public-workspace/folder/12959542-efeda219-66e1-474c-a83b-253d15723bf7).\n';
9
5
  export const parameters = z.object({
@@ -1,11 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
3
- import newman from 'newman';
4
- import { TestTracker, OutputBuilder, buildNewmanOptions } from './utils/runner.js';
5
- function asMcpError(error) {
6
- const cause = error?.cause ?? String(error);
7
- return new McpError(ErrorCode.InternalError, cause);
8
- }
2
+ import { asMcpError, McpError } from './utils/toolHelpers.js';
3
+ import { runCollection } from './runner/index.js';
9
4
  export const method = 'runCollection';
10
5
  export const description = 'Runs a Postman collection by ID with detailed test results and execution statistics. Supports optional environment for variable substitution. Note: Advanced parameters like custom delays and other runtime options are not yet available.';
11
6
  export const parameters = z.object({
@@ -41,85 +36,12 @@ export const annotations = {
41
36
  };
42
37
  export async function handler(params, extra) {
43
38
  try {
44
- const tracker = new TestTracker();
45
- const output = new OutputBuilder();
46
- output.add(`šŸš€ Fetching collection with ID: ${params.collectionId}`);
47
- const response = await extra.client.get(`/collections/${params.collectionId}`);
48
- const collectionJSON = response.collection || response;
49
- output.add(`āœ… Successfully fetched collection: ${collectionJSON.info?.name || 'Unknown'}\n`);
50
- let environmentJSON;
51
- if (params.environmentId) {
52
- output.add(`šŸŒ Fetching environment with ID: ${params.environmentId}`);
53
- const envResponse = await extra.client.get(`/environments/${params.environmentId}`);
54
- environmentJSON = envResponse.environment || envResponse;
55
- output.add(`āœ… Successfully fetched environment: ${environmentJSON.name || 'Unknown'}\n`);
56
- }
57
- const newmanOptions = buildNewmanOptions(params, collectionJSON, environmentJSON);
58
- const startTime = Date.now();
59
- await new Promise((resolve, reject) => {
60
- newman
61
- .run(newmanOptions)
62
- .on('start', () => {
63
- output.add('šŸŽÆ Starting collection run...\n');
64
- })
65
- .on('assertion', (_err, args) => {
66
- if (args.assertion) {
67
- tracker.addAssertion({
68
- passed: !args.error,
69
- assertion: args.assertion,
70
- name: args.assertion,
71
- error: args.error,
72
- });
73
- }
74
- })
75
- .on('item', (_err, args) => {
76
- if (args.item) {
77
- const testResults = tracker.displayCurrentResults();
78
- if (testResults) {
79
- output.add(`\nšŸ“ Request: ${args.item.name}`);
80
- output.add(testResults);
81
- }
82
- }
83
- })
84
- .on('done', (err, summary) => {
85
- const endTime = Date.now();
86
- const durationMs = endTime - startTime;
87
- const durationSec = (durationMs / 1000).toFixed(2);
88
- if (err) {
89
- output.add('\nāŒ Run error: ' + err.message);
90
- output.add(`ā±ļø Duration: ${durationSec}s`);
91
- reject(err);
92
- return;
93
- }
94
- output.add('\n=== āœ… Run completed! ===');
95
- output.add(`ā±ļø Duration: ${durationSec}s`);
96
- const testStats = tracker.getTotalStats();
97
- if (testStats.total > 0) {
98
- output.add('\nšŸ“Š Overall Test Statistics:');
99
- output.add(` Total tests: ${testStats.total}`);
100
- output.add(` Passed: ${testStats.passed} āœ…`);
101
- output.add(` Failed: ${testStats.failed} āŒ`);
102
- output.add(` Success rate: ${((testStats.passed / testStats.total) * 100).toFixed(1)}%`);
103
- }
104
- if (summary?.run?.stats) {
105
- output.add('\nšŸ“ˆ Request Summary:');
106
- output.add(` Total requests: ${summary.run.stats.requests?.total || 0}`);
107
- output.add(` Failed requests: ${summary.run.stats.requests?.failed || 0}`);
108
- output.add(` Total assertions: ${summary.run.stats.assertions?.total || 0}`);
109
- output.add(` Failed assertions: ${summary.run.stats.assertions?.failed || 0}`);
110
- if (summary.run.stats.iterations) {
111
- output.add(` Total iterations: ${summary.run.stats.iterations.total || 0}`);
112
- output.add(` Failed iterations: ${summary.run.stats.iterations.failed || 0}`);
113
- }
114
- }
115
- resolve();
116
- });
117
- });
39
+ const output = await runCollection(params, extra.client);
118
40
  return {
119
41
  content: [
120
42
  {
121
43
  type: 'text',
122
- text: output.build(),
44
+ text: output,
123
45
  },
124
46
  ],
125
47
  };
@@ -1,9 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { McpError, ErrorCode, } from '@modelcontextprotocol/sdk/types.js';
3
- function asMcpError(error) {
4
- const cause = error?.cause ?? String(error);
5
- return new McpError(ErrorCode.InternalError, cause);
6
- }
2
+ import { asMcpError, McpError } from './utils/toolHelpers.js';
7
3
  export const method = 'runMonitor';
8
4
  export const description = "Runs a monitor and returns its run results.\n\n**Note:**\n\n- If you pass the \\`async=true\\` query parameter, the response does not return the \\`stats\\`, \\`executions\\`, and \\`failures\\` responses. To get this information for an asynchronous run, call the GET \\`/monitors/{id}\\` endpoint.\n- If the call exceeds 300 seconds, the endpoint returns an HTTP \\`202 Accepted\\` response. Use the GET \\`/monitors/{id}\\` endpoint to check the run's status in the response's \\`lastRun\\` property. To avoid this, it is recommended that you include the \\`async=true\\` query parameter when using this endpoint.\n";
9
5
  export const parameters = z.object({
@@ -0,0 +1,165 @@
1
+ import newman from 'newman';
2
+ export class OutputBuilder {
3
+ lines = [];
4
+ add(line) {
5
+ this.lines.push(line);
6
+ }
7
+ build() {
8
+ return this.lines.join('\n');
9
+ }
10
+ }
11
+ export class TestTracker {
12
+ assertions = [];
13
+ totalTests = 0;
14
+ totalPassed = 0;
15
+ totalFailed = 0;
16
+ addAssertion(assertion) {
17
+ this.assertions.push(assertion);
18
+ this.totalTests++;
19
+ if (assertion.passed) {
20
+ this.totalPassed++;
21
+ }
22
+ else {
23
+ this.totalFailed++;
24
+ }
25
+ }
26
+ displayCurrentResults() {
27
+ if (this.assertions.length === 0) {
28
+ return '';
29
+ }
30
+ const lines = [' šŸ“Š Test Results:'];
31
+ this.assertions.forEach((assertion) => {
32
+ const status = assertion.passed ? 'āœ“' : 'āœ—';
33
+ const name = assertion.assertion || assertion.name || 'Unnamed test';
34
+ lines.push(` ${status} ${name}`);
35
+ if (!assertion.passed && assertion.error) {
36
+ const errorMessage = typeof assertion.error === 'string'
37
+ ? assertion.error
38
+ : assertion.error.message || 'Unknown error';
39
+ lines.push(` └─ Error: ${errorMessage}`);
40
+ }
41
+ });
42
+ const passed = this.assertions.filter((a) => a.passed).length;
43
+ const failed = this.assertions.filter((a) => !a.passed).length;
44
+ lines.push(` ────────────────────────────────────────`);
45
+ lines.push(` ${this.assertions.length} tests | āœ“ ${passed} passed | āœ— ${failed} failed\n`);
46
+ this.assertions.length = 0;
47
+ return lines.join('\n');
48
+ }
49
+ getTotalStats() {
50
+ return {
51
+ total: this.totalTests,
52
+ passed: this.totalPassed,
53
+ failed: this.totalFailed,
54
+ };
55
+ }
56
+ reset() {
57
+ this.assertions.length = 0;
58
+ this.totalTests = 0;
59
+ this.totalPassed = 0;
60
+ this.totalFailed = 0;
61
+ }
62
+ }
63
+ export function buildNewmanOptions(params, collection, environment) {
64
+ return {
65
+ collection: collection,
66
+ environment: environment,
67
+ iterationCount: params.iterationCount || 1,
68
+ timeout: params.requestTimeout || 60000,
69
+ timeoutRequest: params.requestTimeout || 60000,
70
+ timeoutScript: params.scriptTimeout || 5000,
71
+ delayRequest: 1000,
72
+ ignoreRedirects: false,
73
+ insecure: false,
74
+ bail: params.stopOnFailure ? ['failure'] : false,
75
+ suppressExitCode: true,
76
+ reporters: [],
77
+ reporter: {},
78
+ color: 'off',
79
+ verbose: false,
80
+ requestAgents: {
81
+ http: undefined,
82
+ https: undefined,
83
+ },
84
+ };
85
+ }
86
+ export async function executeCollection(context) {
87
+ const tracker = new TestTracker();
88
+ const output = new OutputBuilder();
89
+ output.add(`šŸš€ Starting collection: ${context.collection.name}`);
90
+ if (context.environment) {
91
+ output.add(`šŸŒ Using environment: ${context.environment.name}\n`);
92
+ }
93
+ const newmanOptions = buildNewmanOptions(context.params, context.collection.json, context.environment?.json);
94
+ const startTime = Date.now();
95
+ const summary = await runNewman(newmanOptions, tracker, output);
96
+ const endTime = Date.now();
97
+ const durationMs = endTime - startTime;
98
+ return {
99
+ output: output.build(),
100
+ testStats: tracker.getTotalStats(),
101
+ summary,
102
+ startTime,
103
+ endTime,
104
+ durationMs,
105
+ };
106
+ }
107
+ function runNewman(options, tracker, output) {
108
+ return new Promise((resolve, reject) => {
109
+ newman
110
+ .run(options)
111
+ .on('start', () => {
112
+ output.add('šŸŽÆ Starting collection run...\n');
113
+ })
114
+ .on('assertion', (_err, args) => {
115
+ if (args.assertion) {
116
+ tracker.addAssertion({
117
+ passed: !args.error,
118
+ assertion: args.assertion,
119
+ name: args.assertion,
120
+ error: args.error,
121
+ });
122
+ }
123
+ })
124
+ .on('item', (_err, args) => {
125
+ if (args.item) {
126
+ const testResults = tracker.displayCurrentResults();
127
+ if (testResults) {
128
+ output.add(`\nšŸ“ Request: ${args.item.name}`);
129
+ output.add(testResults);
130
+ }
131
+ }
132
+ })
133
+ .on('done', (err, summary) => {
134
+ if (err) {
135
+ output.add('\nāŒ Run error: ' + err.message);
136
+ reject(err);
137
+ return;
138
+ }
139
+ output.add('\n=== āœ… Run completed! ===');
140
+ appendSummaryToOutput(output, tracker, summary);
141
+ resolve(summary);
142
+ });
143
+ });
144
+ }
145
+ function appendSummaryToOutput(output, tracker, summary) {
146
+ const testStats = tracker.getTotalStats();
147
+ if (testStats.total > 0) {
148
+ output.add('\nšŸ“Š Overall Test Statistics:');
149
+ output.add(` Total tests: ${testStats.total}`);
150
+ output.add(` Passed: ${testStats.passed} āœ…`);
151
+ output.add(` Failed: ${testStats.failed} āŒ`);
152
+ output.add(` Success rate: ${((testStats.passed / testStats.total) * 100).toFixed(1)}%`);
153
+ }
154
+ if (summary?.run?.stats) {
155
+ output.add('\nšŸ“ˆ Request Summary:');
156
+ output.add(` Total requests: ${summary.run.stats.requests?.total || 0}`);
157
+ output.add(` Failed requests: ${summary.run.stats.requests?.failed || 0}`);
158
+ output.add(` Total assertions: ${summary.run.stats.assertions?.total || 0}`);
159
+ output.add(` Failed assertions: ${summary.run.stats.assertions?.failed || 0}`);
160
+ if (summary.run.stats.iterations) {
161
+ output.add(` Total iterations: ${summary.run.stats.iterations.total || 0}`);
162
+ output.add(` Failed iterations: ${summary.run.stats.iterations.failed || 0}`);
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,33 @@
1
+ import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
2
+ export async function fetchCollection(collectionId, client) {
3
+ try {
4
+ const response = await client.get(`/collections/${collectionId}`);
5
+ const collectionJSON = response.collection || response;
6
+ return {
7
+ json: collectionJSON,
8
+ name: collectionJSON.info?.name || 'Unknown',
9
+ id: collectionId,
10
+ };
11
+ }
12
+ catch (error) {
13
+ throw new McpError(ErrorCode.InternalError, `Failed to fetch collection: ${collectionId}`, {
14
+ cause: error,
15
+ });
16
+ }
17
+ }
18
+ export async function fetchEnvironment(environmentId, client) {
19
+ try {
20
+ const response = await client.get(`/environments/${environmentId}`);
21
+ const environmentJSON = response.environment || response;
22
+ return {
23
+ json: environmentJSON,
24
+ name: environmentJSON.name || 'Unknown',
25
+ id: environmentId,
26
+ };
27
+ }
28
+ catch (error) {
29
+ throw new McpError(ErrorCode.InternalError, `Failed to fetch environment: ${environmentId}`, {
30
+ cause: error,
31
+ });
32
+ }
33
+ }
@@ -0,0 +1,20 @@
1
+ import { fetchCollection, fetchEnvironment } from './fetchers.js';
2
+ import { executeCollection } from './executor.js';
3
+ import { parseToTelemetry, formatUserOutput } from './parsers.js';
4
+ import { reportTelemetryAsync } from './telemetry.js';
5
+ export async function runCollection(params, client) {
6
+ const collection = await fetchCollection(params.collectionId, client);
7
+ let environment;
8
+ if (params.environmentId) {
9
+ environment = await fetchEnvironment(params.environmentId, client);
10
+ }
11
+ const result = await executeCollection({
12
+ collection,
13
+ environment,
14
+ params,
15
+ });
16
+ const telemetryPayload = parseToTelemetry(result, params.collectionId, collection.name);
17
+ const userOutput = formatUserOutput(result);
18
+ reportTelemetryAsync(telemetryPayload, client);
19
+ return userOutput;
20
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { buildTelemetryPayload } from './telemetry.js';
2
+ export function parseToTelemetry(result, collectionId, collectionName) {
3
+ return buildTelemetryPayload(collectionId, collectionName, result);
4
+ }
5
+ export function formatUserOutput(result) {
6
+ const durationSec = (result.durationMs / 1000).toFixed(2);
7
+ return `${result.output}\nā±ļø Duration: ${durationSec}s`;
8
+ }