@smartbear/mcp 0.12.0 → 0.13.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 (89) hide show
  1. package/README.md +30 -6
  2. package/dist/bugsnag/client/api/CurrentUser.js +50 -26
  3. package/dist/bugsnag/client/api/Error.js +158 -57
  4. package/dist/bugsnag/client/api/Project.js +398 -243
  5. package/dist/bugsnag/client/api/api.js +4087 -3837
  6. package/dist/bugsnag/client/api/base.js +155 -173
  7. package/dist/bugsnag/client/api/configuration.js +28 -25
  8. package/dist/bugsnag/client/filters.js +11 -20
  9. package/dist/bugsnag/client.js +1398 -1277
  10. package/dist/bugsnag/input-schemas.js +39 -57
  11. package/dist/collaborator/client.js +335 -371
  12. package/dist/common/bugsnag.js +5 -3
  13. package/dist/common/cache.js +50 -57
  14. package/dist/common/client-registry.js +106 -119
  15. package/dist/common/info.js +7 -3
  16. package/dist/common/register-clients.js +0 -16
  17. package/dist/common/server.js +270 -228
  18. package/dist/common/tools.js +19 -0
  19. package/dist/common/transport-http.js +252 -343
  20. package/dist/common/transport-stdio.js +40 -37
  21. package/dist/common/zod-utils.js +20 -0
  22. package/dist/index.js +18 -23
  23. package/dist/package.json.js +11 -0
  24. package/dist/pactflow/client/ai.js +142 -169
  25. package/dist/pactflow/client/base.js +41 -51
  26. package/dist/pactflow/client/prompt-utils.js +93 -84
  27. package/dist/pactflow/client/prompts.js +95 -92
  28. package/dist/pactflow/client/tools.js +94 -83
  29. package/dist/pactflow/client/utils.js +60 -64
  30. package/dist/pactflow/client.js +399 -320
  31. package/dist/qmetry/client/api/client-api.js +43 -41
  32. package/dist/qmetry/client/api/error-handler.js +264 -310
  33. package/dist/qmetry/client/auto-resolve.js +78 -99
  34. package/dist/qmetry/client/automation.js +139 -162
  35. package/dist/qmetry/client/handlers.js +49 -46
  36. package/dist/qmetry/client/issues.js +133 -115
  37. package/dist/qmetry/client/project.js +153 -174
  38. package/dist/qmetry/client/requirement.js +82 -70
  39. package/dist/qmetry/client/testcase.js +240 -208
  40. package/dist/qmetry/client/testsuite.js +332 -293
  41. package/dist/qmetry/client/tools/automation-tools.js +291 -288
  42. package/dist/qmetry/client/tools/index.js +16 -13
  43. package/dist/qmetry/client/tools/issue-tools.js +534 -543
  44. package/dist/qmetry/client/tools/project-tools.js +635 -656
  45. package/dist/qmetry/client/tools/requirement-tools.js +525 -528
  46. package/dist/qmetry/client/tools/testcase-tools.js +773 -786
  47. package/dist/qmetry/client/tools/testsuite-tools.js +1069 -1083
  48. package/dist/qmetry/client/utils.js +8 -14
  49. package/dist/qmetry/client.js +111 -109
  50. package/dist/qmetry/config/constants.js +48 -44
  51. package/dist/qmetry/config/rest-endpoints.js +51 -48
  52. package/dist/qmetry/types/automation.js +7 -7
  53. package/dist/qmetry/types/common.js +763 -1049
  54. package/dist/qmetry/types/issues.js +26 -19
  55. package/dist/qmetry/types/project.js +32 -25
  56. package/dist/qmetry/types/requirements.js +26 -21
  57. package/dist/qmetry/types/testcase.js +55 -44
  58. package/dist/qmetry/types/testsuite.js +66 -52
  59. package/dist/reflect/client.js +284 -226
  60. package/dist/swagger/client/api.js +645 -662
  61. package/dist/swagger/client/configuration.js +31 -33
  62. package/dist/swagger/client/portal-types.js +204 -244
  63. package/dist/swagger/client/registry-types.js +62 -96
  64. package/dist/swagger/client/tools.js +148 -158
  65. package/dist/swagger/client/user-management-types.js +11 -22
  66. package/dist/swagger/client.js +143 -135
  67. package/dist/swagger/config-utils.js +10 -16
  68. package/dist/zephyr/client.js +43 -42
  69. package/dist/zephyr/common/api-client.js +35 -30
  70. package/dist/zephyr/common/auth-service.js +16 -13
  71. package/dist/zephyr/common/rest-api-schemas.js +3173 -5146
  72. package/dist/zephyr/tool/environment/get-environments.js +66 -66
  73. package/dist/zephyr/tool/priority/get-priorities.js +41 -41
  74. package/dist/zephyr/tool/project/get-project.js +37 -37
  75. package/dist/zephyr/tool/project/get-projects.js +46 -46
  76. package/dist/zephyr/tool/status/get-statuses.js +47 -47
  77. package/dist/zephyr/tool/test-case/get-test-case.js +37 -37
  78. package/dist/zephyr/tool/test-case/get-test-cases.js +62 -62
  79. package/dist/zephyr/tool/test-cycle/get-test-cycle.js +37 -37
  80. package/dist/zephyr/tool/test-cycle/get-test-cycles.js +70 -70
  81. package/dist/zephyr/tool/test-execution/get-test-execution.js +37 -37
  82. package/dist/zephyr/tool/test-execution/get-test-executions.js +43 -43
  83. package/package.json +5 -5
  84. package/dist/bugsnag/client/api/index.js +0 -6
  85. package/dist/common/types.js +0 -6
  86. package/dist/qmetry/client/tools/types.js +0 -1
  87. package/dist/swagger/client/index.js +0 -6
  88. package/dist/tests/unit/bugsnag/utils/factories.js +0 -86
  89. package/dist/zephyr/tool/zephyr-tool.js +0 -1
@@ -1,106 +1,85 @@
1
1
  import { QMetryToolsHandlers } from "../config/constants.js";
2
- /**
3
- * Registry of all modules that support auto-resolution
4
- * Add new modules here to automatically support viewId/folderPath resolution
5
- */
6
- export const AUTO_RESOLVE_MODULES = [
7
- {
8
- handler: QMetryToolsHandlers.FETCH_TEST_CASES,
9
- viewIdPath: "latestViews.TC.viewId",
10
- moduleName: "Test Cases",
11
- },
12
- {
13
- handler: QMetryToolsHandlers.CREATE_TEST_CASE,
14
- folderIdPath: "rootFolders.TC.id",
15
- folderIdField: "tcFolderID",
16
- moduleName: "Test Cases",
17
- },
18
- {
19
- handler: QMetryToolsHandlers.FETCH_REQUIREMENTS,
20
- viewIdPath: "latestViews.RQ.viewId",
21
- moduleName: "Requirements",
22
- },
23
- {
24
- handler: QMetryToolsHandlers.FETCH_TEST_SUITES,
25
- viewIdPath: "latestViews.TS.viewId",
26
- moduleName: "Test Suites",
27
- },
28
- {
29
- handler: QMetryToolsHandlers.FETCH_TESTCASE_RUNS_BY_TESTSUITE_RUN,
30
- viewIdPath: "latestViews.TE.viewId",
31
- moduleName: "Test Case Run By Test Suite Run",
32
- },
33
- {
34
- handler: QMetryToolsHandlers.FETCH_EXECUTIONS_BY_TESTSUITE,
35
- viewIdPath: "latestViews.TEL.viewId",
36
- moduleName: "Executions By Test Suites",
37
- },
38
- {
39
- handler: QMetryToolsHandlers.FETCH_TESTSUITES_FOR_TESTCASE,
40
- viewIdPath: "latestViews.TSFS.viewId",
41
- folderIdPath: "rootFolders.TS.id",
42
- folderIdField: "tsFolderID",
43
- moduleName: "Test Suites",
44
- },
45
- {
46
- handler: QMetryToolsHandlers.CREATE_TEST_SUITE,
47
- folderIdPath: "rootFolders.TS.id",
48
- folderIdField: "parentFolderId",
49
- moduleName: "Test Suites",
50
- },
51
- {
52
- handler: QMetryToolsHandlers.FETCH_ISSUES,
53
- viewIdPath: "latestViews.IS.viewId",
54
- moduleName: "Issues",
55
- },
2
+ const AUTO_RESOLVE_MODULES = [
3
+ {
4
+ handler: QMetryToolsHandlers.FETCH_TEST_CASES,
5
+ viewIdPath: "latestViews.TC.viewId",
6
+ moduleName: "Test Cases"
7
+ },
8
+ {
9
+ handler: QMetryToolsHandlers.CREATE_TEST_CASE,
10
+ folderIdPath: "rootFolders.TC.id",
11
+ folderIdField: "tcFolderID",
12
+ moduleName: "Test Cases"
13
+ },
14
+ {
15
+ handler: QMetryToolsHandlers.FETCH_REQUIREMENTS,
16
+ viewIdPath: "latestViews.RQ.viewId",
17
+ moduleName: "Requirements"
18
+ },
19
+ {
20
+ handler: QMetryToolsHandlers.FETCH_TEST_SUITES,
21
+ viewIdPath: "latestViews.TS.viewId",
22
+ moduleName: "Test Suites"
23
+ },
24
+ {
25
+ handler: QMetryToolsHandlers.FETCH_TESTCASE_RUNS_BY_TESTSUITE_RUN,
26
+ viewIdPath: "latestViews.TE.viewId",
27
+ moduleName: "Test Case Run By Test Suite Run"
28
+ },
29
+ {
30
+ handler: QMetryToolsHandlers.FETCH_EXECUTIONS_BY_TESTSUITE,
31
+ viewIdPath: "latestViews.TEL.viewId",
32
+ moduleName: "Executions By Test Suites"
33
+ },
34
+ {
35
+ handler: QMetryToolsHandlers.FETCH_TESTSUITES_FOR_TESTCASE,
36
+ viewIdPath: "latestViews.TSFS.viewId",
37
+ folderIdPath: "rootFolders.TS.id",
38
+ folderIdField: "tsFolderID",
39
+ moduleName: "Test Suites"
40
+ },
41
+ {
42
+ handler: QMetryToolsHandlers.CREATE_TEST_SUITE,
43
+ folderIdPath: "rootFolders.TS.id",
44
+ folderIdField: "parentFolderId",
45
+ moduleName: "Test Suites"
46
+ },
47
+ {
48
+ handler: QMetryToolsHandlers.FETCH_ISSUES,
49
+ viewIdPath: "latestViews.IS.viewId",
50
+ moduleName: "Issues"
51
+ }
56
52
  ];
57
- /**
58
- * Helper function to safely get nested property value using dot notation
59
- * @param obj - Object to traverse
60
- * @param path - Dot notation path (e.g., 'latestViews.TC.viewId')
61
- * @returns The value at the path or undefined if not found
62
- */
63
- export function getNestedProperty(obj, path) {
64
- return path.split(".").reduce((current, key) => current?.[key], obj);
53
+ function getNestedProperty(obj, path) {
54
+ return path.split(".").reduce((current, key) => current?.[key], obj);
65
55
  }
66
- /**
67
- * Generic auto-resolve function for viewId, folderPath, and folderID
68
- * @param args - Tool arguments that may contain viewId/folderPath/folderID
69
- * @param projectInfo - Project information from QMetry API
70
- * @param config - Module configuration for this specific handler
71
- * @returns Updated args with resolved values
72
- */
73
- export function autoResolveViewIdAndFolderPath(args, projectInfo, config) {
74
- const updatedArgs = { ...args };
75
- let viewId = updatedArgs.viewId;
76
- const folderPath = updatedArgs.folderPath;
77
- // Auto-resolve viewId if not provided and config has viewIdPath
78
- if (!viewId && config.viewIdPath) {
79
- viewId = getNestedProperty(projectInfo, config.viewIdPath);
80
- if (viewId) {
81
- updatedArgs.viewId = viewId;
82
- }
56
+ function autoResolveViewIdAndFolderPath(args, projectInfo, config) {
57
+ const updatedArgs = { ...args };
58
+ let viewId = updatedArgs.viewId;
59
+ const folderPath = updatedArgs.folderPath;
60
+ if (!viewId && config.viewIdPath) {
61
+ viewId = getNestedProperty(projectInfo, config.viewIdPath);
62
+ if (viewId) {
63
+ updatedArgs.viewId = viewId;
83
64
  }
84
- // Auto-resolve folderPath if not provided (defaults to root)
85
- if (folderPath === undefined) {
86
- updatedArgs.folderPath = "";
65
+ }
66
+ if (folderPath === void 0) {
67
+ updatedArgs.folderPath = "";
68
+ }
69
+ if (config.folderIdPath && config.folderIdField && !updatedArgs[config.folderIdField]) {
70
+ const folderId = getNestedProperty(projectInfo, config.folderIdPath);
71
+ if (folderId) {
72
+ updatedArgs[config.folderIdField] = folderId;
87
73
  }
88
- // Auto-resolve folder ID if not provided and config has folderIdPath
89
- if (config.folderIdPath &&
90
- config.folderIdField &&
91
- !updatedArgs[config.folderIdField]) {
92
- const folderId = getNestedProperty(projectInfo, config.folderIdPath);
93
- if (folderId) {
94
- updatedArgs[config.folderIdField] = folderId;
95
- }
96
- }
97
- return updatedArgs;
74
+ }
75
+ return updatedArgs;
98
76
  }
99
- /**
100
- * Find the auto-resolve configuration for a given handler
101
- * @param handler - The handler name to find config for
102
- * @returns Module configuration or undefined if not found
103
- */
104
- export function findAutoResolveConfig(handler) {
105
- return AUTO_RESOLVE_MODULES.find((module) => module.handler === handler);
77
+ function findAutoResolveConfig(handler) {
78
+ return AUTO_RESOLVE_MODULES.find((module) => module.handler === handler);
106
79
  }
80
+ export {
81
+ AUTO_RESOLVE_MODULES,
82
+ autoResolveViewIdAndFolderPath,
83
+ findAutoResolveConfig,
84
+ getNestedProperty
85
+ };
@@ -4,168 +4,145 @@ import { QMETRY_PATHS } from "../config/rest-endpoints.js";
4
4
  import { DEFAULT_IMPORT_AUTOMATION_PAYLOAD } from "../types/automation.js";
5
5
  import { qmetryRequest } from "./api/client-api.js";
6
6
  import { handleQMetryApiError } from "./api/error-handler.js";
7
- /**
8
- * Imports automation test results into QMetry
9
- *
10
- * This function handles file upload via FormData to import automation test results
11
- * from various frameworks (TestNG, JUnit, Cucumber, Robot, etc.)
12
- *
13
- * CRITICAL NOTES:
14
- * - User MUST provide a valid result file (.json, .xml, or .zip up to 30 MB)
15
- * - File should be base64 encoded or provided as file path
16
- * - EntityType is required and determines the framework format
17
- * - Various parameters control test case/suite creation and linking behavior
18
- *
19
- * @param token - QMetry API authentication token
20
- * @param baseUrl - QMetry instance base URL
21
- * @param project - Project key (used in header, can be overridden by projectID in payload)
22
- * @param payload - Import configuration including file data, entityType, and optional parameters
23
- * @returns Promise resolving to import result with test suite and execution details
24
- */
25
- export async function importAutomationResults(token, baseUrl, project, payload) {
26
- // Merge with defaults
27
- const finalPayload = {
28
- ...DEFAULT_IMPORT_AUTOMATION_PAYLOAD,
29
- ...payload,
30
- };
31
- // Create FormData for multipart/form-data upload
32
- const formData = new FormData();
33
- // Handle file upload
34
- // The file should be provided as base64 string or file content
35
- let fileBlob;
36
- if (finalPayload.file.startsWith("data:")) {
37
- // Base64 data URI format
38
- const base64Data = finalPayload.file.split(",")[1];
39
- const binaryData = atob(base64Data);
40
- const bytes = new Uint8Array(binaryData.length);
41
- for (let i = 0; i < binaryData.length; i++) {
42
- bytes[i] = binaryData.charCodeAt(i);
43
- }
44
- fileBlob = new Blob([bytes]);
45
- }
46
- else if (finalPayload.file.startsWith("/") ||
47
- finalPayload.file.includes(":\\")) {
48
- // File path - read file from filesystem (Node.js only)
49
- try {
50
- const fs = await import("node:fs/promises");
51
- const fileBuffer = await fs.readFile(finalPayload.file);
52
- fileBlob = new Blob([new Uint8Array(fileBuffer)]);
53
- }
54
- catch (error) {
55
- throw new Error(`Failed to read file from path: ${finalPayload.file}. Error: ${error instanceof Error ? error.message : String(error)}`);
56
- }
57
- }
58
- else {
59
- // Assume raw base64 string
60
- try {
61
- const binaryData = atob(finalPayload.file);
62
- const bytes = new Uint8Array(binaryData.length);
63
- for (let i = 0; i < binaryData.length; i++) {
64
- bytes[i] = binaryData.charCodeAt(i);
65
- }
66
- fileBlob = new Blob([bytes]);
67
- }
68
- catch (_error) {
69
- throw new Error("Invalid file format. Please provide base64 encoded file content or file path.");
70
- }
71
- }
72
- // Add file to FormData
73
- formData.append("file", fileBlob, finalPayload.fileName);
74
- // Add required entityType
75
- formData.append("entityType", finalPayload.entityType);
76
- // Add optional parameters
77
- if (finalPayload.automationHierarchy) {
78
- formData.append("automationHierarchy", finalPayload.automationHierarchy);
79
- }
80
- if (finalPayload.testsuiteName) {
81
- formData.append("testsuiteName", finalPayload.testsuiteName);
82
- }
83
- if (finalPayload.testsuiteId) {
84
- formData.append("testsuiteId", finalPayload.testsuiteId);
85
- }
86
- if (finalPayload.tsFolderPath) {
87
- formData.append("tsFolderPath", finalPayload.tsFolderPath);
88
- }
89
- if (finalPayload.tcFolderPath) {
90
- formData.append("tcFolderPath", finalPayload.tcFolderPath);
91
- }
92
- if (finalPayload.platformID) {
93
- formData.append("platformID", finalPayload.platformID);
94
- }
95
- if (finalPayload.projectID) {
96
- formData.append("projectID", finalPayload.projectID);
97
- }
98
- if (finalPayload.releaseID) {
99
- formData.append("releaseID", finalPayload.releaseID);
100
- }
101
- if (finalPayload.cycleID) {
102
- formData.append("cycleID", finalPayload.cycleID);
103
- }
104
- if (finalPayload.buildID) {
105
- formData.append("buildID", finalPayload.buildID);
106
- }
107
- if (finalPayload.testcase_fields) {
108
- formData.append("testcase_fields", finalPayload.testcase_fields);
109
- }
110
- if (finalPayload.testsuite_fields) {
111
- formData.append("testsuite_fields", finalPayload.testsuite_fields);
112
- }
113
- if (finalPayload.skipWarning) {
114
- formData.append("skipWarning", finalPayload.skipWarning);
115
- }
116
- if (finalPayload.is_matching_required) {
117
- formData.append("is_matching_required", finalPayload.is_matching_required);
118
- }
119
- // Make API request
120
- const url = `${baseUrl || QMETRY_DEFAULTS.BASE_URL}${QMETRY_PATHS.AUTOMATION.IMPORT_RESULTS}`;
121
- const headers = {
122
- apikey: token,
123
- project: finalPayload.projectID || project || QMETRY_DEFAULTS.PROJECT_KEY,
124
- "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`,
125
- // Note: Content-Type will be set automatically by fetch for FormData
126
- };
127
- let res;
7
+ async function importAutomationResults(token, baseUrl, project, payload) {
8
+ const finalPayload = {
9
+ ...DEFAULT_IMPORT_AUTOMATION_PAYLOAD,
10
+ ...payload
11
+ };
12
+ const formData = new FormData();
13
+ let fileBlob;
14
+ if (finalPayload.file.startsWith("data:")) {
15
+ const base64Data = finalPayload.file.split(",")[1];
16
+ const binaryData = atob(base64Data);
17
+ const bytes = new Uint8Array(binaryData.length);
18
+ for (let i = 0; i < binaryData.length; i++) {
19
+ bytes[i] = binaryData.charCodeAt(i);
20
+ }
21
+ fileBlob = new Blob([bytes]);
22
+ } else if (finalPayload.file.startsWith("/") || finalPayload.file.includes(":\\")) {
128
23
  try {
129
- res = await fetch(url, {
130
- method: "POST",
131
- headers,
132
- body: formData,
133
- });
134
- }
135
- catch (error) {
136
- throw new Error(`Failed to import automation results. Network error: ${error instanceof Error ? error.message : String(error)}\n\nPlease check:\n- QMetry server is accessible\n- File size is under 30 MB\n- File format is .json, .xml, or .zip`);
137
- }
138
- if (!res.ok) {
139
- await handleQMetryApiError(res, baseUrl || QMETRY_DEFAULTS.BASE_URL, project || QMETRY_DEFAULTS.PROJECT_KEY, QMETRY_PATHS.AUTOMATION.IMPORT_RESULTS);
140
- }
141
- return await res.json();
142
- }
143
- /**
144
- * Fetches automation status by request ID from QMetry
145
- * @param token - QMetry API authentication token
146
- * @param baseUrl - QMetry instance base URL
147
- * @param requestID - Numeric request ID from import automation response
148
- * @returns Promise resolving to automation status
149
- */
150
- export async function getAutomationStatus(token, baseUrl, project, requestID) {
151
- let numericRequestID;
152
- if (typeof requestID === "object" &&
153
- requestID !== null &&
154
- "requestID" in requestID &&
155
- typeof requestID.requestID !== "undefined") {
156
- numericRequestID = Number(requestID.requestID);
157
- }
158
- else {
159
- numericRequestID = Number(requestID);
160
- }
161
- if (!numericRequestID || Number.isNaN(numericRequestID)) {
162
- throw new Error("requestID must be a valid number");
163
- }
164
- return qmetryRequest({
165
- method: "GET",
166
- path: QMETRY_PATHS.AUTOMATION.GET_STATUS.replace(":requestID", String(numericRequestID)),
167
- token,
168
- baseUrl: baseUrl || QMETRY_DEFAULTS.BASE_URL,
169
- project: project || QMETRY_DEFAULTS.PROJECT_KEY,
24
+ const fs = await import("node:fs/promises");
25
+ const fileBuffer = await fs.readFile(finalPayload.file);
26
+ fileBlob = new Blob([new Uint8Array(fileBuffer)]);
27
+ } catch (error) {
28
+ throw new Error(
29
+ `Failed to read file from path: ${finalPayload.file}. Error: ${error instanceof Error ? error.message : String(error)}`
30
+ );
31
+ }
32
+ } else {
33
+ try {
34
+ const binaryData = atob(finalPayload.file);
35
+ const bytes = new Uint8Array(binaryData.length);
36
+ for (let i = 0; i < binaryData.length; i++) {
37
+ bytes[i] = binaryData.charCodeAt(i);
38
+ }
39
+ fileBlob = new Blob([bytes]);
40
+ } catch (_error) {
41
+ throw new Error(
42
+ "Invalid file format. Please provide base64 encoded file content or file path."
43
+ );
44
+ }
45
+ }
46
+ formData.append("file", fileBlob, finalPayload.fileName);
47
+ formData.append("entityType", finalPayload.entityType);
48
+ if (finalPayload.automationHierarchy) {
49
+ formData.append("automationHierarchy", finalPayload.automationHierarchy);
50
+ }
51
+ if (finalPayload.testsuiteName) {
52
+ formData.append("testsuiteName", finalPayload.testsuiteName);
53
+ }
54
+ if (finalPayload.testsuiteId) {
55
+ formData.append("testsuiteId", finalPayload.testsuiteId);
56
+ }
57
+ if (finalPayload.tsFolderPath) {
58
+ formData.append("tsFolderPath", finalPayload.tsFolderPath);
59
+ }
60
+ if (finalPayload.tcFolderPath) {
61
+ formData.append("tcFolderPath", finalPayload.tcFolderPath);
62
+ }
63
+ if (finalPayload.platformID) {
64
+ formData.append("platformID", finalPayload.platformID);
65
+ }
66
+ if (finalPayload.projectID) {
67
+ formData.append("projectID", finalPayload.projectID);
68
+ }
69
+ if (finalPayload.releaseID) {
70
+ formData.append("releaseID", finalPayload.releaseID);
71
+ }
72
+ if (finalPayload.cycleID) {
73
+ formData.append("cycleID", finalPayload.cycleID);
74
+ }
75
+ if (finalPayload.buildID) {
76
+ formData.append("buildID", finalPayload.buildID);
77
+ }
78
+ if (finalPayload.testcase_fields) {
79
+ formData.append("testcase_fields", finalPayload.testcase_fields);
80
+ }
81
+ if (finalPayload.testsuite_fields) {
82
+ formData.append("testsuite_fields", finalPayload.testsuite_fields);
83
+ }
84
+ if (finalPayload.skipWarning) {
85
+ formData.append("skipWarning", finalPayload.skipWarning);
86
+ }
87
+ if (finalPayload.is_matching_required) {
88
+ formData.append("is_matching_required", finalPayload.is_matching_required);
89
+ }
90
+ const url = `${baseUrl || QMETRY_DEFAULTS.BASE_URL}${QMETRY_PATHS.AUTOMATION.IMPORT_RESULTS}`;
91
+ const headers = {
92
+ apikey: token,
93
+ project: finalPayload.projectID || project || QMETRY_DEFAULTS.PROJECT_KEY,
94
+ "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`
95
+ // Note: Content-Type will be set automatically by fetch for FormData
96
+ };
97
+ let res;
98
+ try {
99
+ res = await fetch(url, {
100
+ method: "POST",
101
+ headers,
102
+ body: formData
170
103
  });
104
+ } catch (error) {
105
+ throw new Error(
106
+ `Failed to import automation results. Network error: ${error instanceof Error ? error.message : String(error)}
107
+
108
+ Please check:
109
+ - QMetry server is accessible
110
+ - File size is under 30 MB
111
+ - File format is .json, .xml, or .zip`
112
+ );
113
+ }
114
+ if (!res.ok) {
115
+ await handleQMetryApiError(
116
+ res,
117
+ baseUrl || QMETRY_DEFAULTS.BASE_URL,
118
+ project || QMETRY_DEFAULTS.PROJECT_KEY,
119
+ QMETRY_PATHS.AUTOMATION.IMPORT_RESULTS
120
+ );
121
+ }
122
+ return await res.json();
123
+ }
124
+ async function getAutomationStatus(token, baseUrl, project, requestID) {
125
+ let numericRequestID;
126
+ if (typeof requestID === "object" && requestID !== null && "requestID" in requestID && typeof requestID.requestID !== "undefined") {
127
+ numericRequestID = Number(requestID.requestID);
128
+ } else {
129
+ numericRequestID = Number(requestID);
130
+ }
131
+ if (!numericRequestID || Number.isNaN(numericRequestID)) {
132
+ throw new Error("requestID must be a valid number");
133
+ }
134
+ return qmetryRequest({
135
+ method: "GET",
136
+ path: QMETRY_PATHS.AUTOMATION.GET_STATUS.replace(
137
+ ":requestID",
138
+ String(numericRequestID)
139
+ ),
140
+ token,
141
+ baseUrl: baseUrl || QMETRY_DEFAULTS.BASE_URL,
142
+ project: project || QMETRY_DEFAULTS.PROJECT_KEY
143
+ });
171
144
  }
145
+ export {
146
+ getAutomationStatus,
147
+ importAutomationResults
148
+ };
@@ -1,49 +1,52 @@
1
1
  import { QMetryToolsHandlers } from "../config/constants.js";
2
2
  import { getAutomationStatus, importAutomationResults } from "./automation.js";
3
- import { createIssue, fetchIssues, fetchIssuesLinkedToTestCase, linkIssuesToTestcaseRun, updateIssue, } from "./issues.js";
4
- import { createCycle, createRelease, getBuilds, getPlatforms, getProjectInfo, getProjects, getReleasesCycles, updateCycle, } from "./project.js";
5
- import { fetchRequirementDetails, fetchRequirements, fetchRequirementsLinkedToTestCase, } from "./requirement.js";
6
- import { createTestCases, fetchTestCaseDetails, fetchTestCaseExecutions, fetchTestCaseSteps, fetchTestCases, fetchTestCasesLinkedToRequirement, fetchTestCaseVersionDetails, linkRequirementToTestCase, updateTestCase, } from "./testcase.js";
7
- import { bulkUpdateExecutionStatus, createTestSuites, fetchExecutionsByTestSuite, fetchLinkedIssuesByTestCaseRun, fetchTestCaseRunsByTestSuiteRun, fetchTestCasesByTestSuite, fetchTestSuites, fetchTestSuitesForTestCase, linkPlatformsToTestSuite, linkTestCasesToTestSuite, reqLinkedTestCasesToTestSuite, updateTestSuite, } from "./testsuite.js";
8
- export const QMETRY_HANDLER_MAP = {
9
- [QMetryToolsHandlers.FETCH_PROJECTS]: getProjects,
10
- [QMetryToolsHandlers.SET_PROJECT_INFO]: getProjectInfo,
11
- [QMetryToolsHandlers.FETCH_PROJECT_INFO]: getProjectInfo,
12
- [QMetryToolsHandlers.FETCH_RELEASES_CYCLES]: getReleasesCycles,
13
- [QMetryToolsHandlers.FETCH_BUILDS]: getBuilds,
14
- [QMetryToolsHandlers.FETCH_PLATFORMS]: getPlatforms,
15
- [QMetryToolsHandlers.CREATE_RELEASE]: createRelease,
16
- [QMetryToolsHandlers.CREATE_CYCLE]: createCycle,
17
- [QMetryToolsHandlers.UPDATE_CYCLE]: updateCycle,
18
- [QMetryToolsHandlers.CREATE_TEST_CASE]: createTestCases,
19
- [QMetryToolsHandlers.UPDATE_TEST_CASE]: updateTestCase,
20
- [QMetryToolsHandlers.FETCH_TEST_CASES]: fetchTestCases,
21
- [QMetryToolsHandlers.FETCH_TEST_CASE_DETAILS]: fetchTestCaseDetails,
22
- [QMetryToolsHandlers.FETCH_TEST_CASE_VERSION_DETAILS]: fetchTestCaseVersionDetails,
23
- [QMetryToolsHandlers.FETCH_TEST_CASE_STEPS]: fetchTestCaseSteps,
24
- [QMetryToolsHandlers.FETCH_TEST_CASE_EXECUTIONS]: fetchTestCaseExecutions,
25
- [QMetryToolsHandlers.LINK_REQUIREMENT_TO_TESTCASE]: linkRequirementToTestCase,
26
- [QMetryToolsHandlers.FETCH_REQUIREMENTS]: fetchRequirements,
27
- [QMetryToolsHandlers.FETCH_REQUIREMENT_DETAILS]: fetchRequirementDetails,
28
- [QMetryToolsHandlers.FETCH_TESTCASES_LINKED_TO_REQUIREMENT]: fetchTestCasesLinkedToRequirement,
29
- [QMetryToolsHandlers.FETCH_REQUIREMENTS_LINKED_TO_TESTCASE]: fetchRequirementsLinkedToTestCase,
30
- [QMetryToolsHandlers.CREATE_TEST_SUITE]: createTestSuites,
31
- [QMetryToolsHandlers.UPDATE_TEST_SUITE]: updateTestSuite,
32
- [QMetryToolsHandlers.FETCH_TEST_SUITES]: fetchTestSuites,
33
- [QMetryToolsHandlers.FETCH_TESTSUITES_FOR_TESTCASE]: fetchTestSuitesForTestCase,
34
- [QMetryToolsHandlers.LINK_TESTCASES_TO_TESTSUITE]: linkTestCasesToTestSuite,
35
- [QMetryToolsHandlers.REQUIREMENTS_LINKED_TESTCASES_TO_TESTSUITE]: reqLinkedTestCasesToTestSuite,
36
- [QMetryToolsHandlers.FETCH_TESTCASES_BY_TESTSUITE]: fetchTestCasesByTestSuite,
37
- [QMetryToolsHandlers.FETCH_EXECUTIONS_BY_TESTSUITE]: fetchExecutionsByTestSuite,
38
- [QMetryToolsHandlers.BULK_UPDATE_EXECUTION_STATUS]: bulkUpdateExecutionStatus,
39
- [QMetryToolsHandlers.FETCH_TESTCASE_RUNS_BY_TESTSUITE_RUN]: fetchTestCaseRunsByTestSuiteRun,
40
- [QMetryToolsHandlers.FETCH_LINKED_ISSUES_BY_TESTCASE_RUN]: fetchLinkedIssuesByTestCaseRun,
41
- [QMetryToolsHandlers.FETCH_ISSUES_LINKED_TO_TESTCASE]: fetchIssuesLinkedToTestCase,
42
- [QMetryToolsHandlers.CREATE_ISSUE]: createIssue,
43
- [QMetryToolsHandlers.UPDATE_ISSUE]: updateIssue,
44
- [QMetryToolsHandlers.FETCH_ISSUES]: fetchIssues,
45
- [QMetryToolsHandlers.LINK_ISSUES_TO_TESTCASE_RUN]: linkIssuesToTestcaseRun,
46
- [QMetryToolsHandlers.LINK_PLATFORMS_TO_TESTSUITE]: linkPlatformsToTestSuite,
47
- [QMetryToolsHandlers.IMPORT_AUTOMATION_RESULTS]: importAutomationResults,
48
- [QMetryToolsHandlers.FETCH_AUTOMATION_STATUS]: getAutomationStatus,
3
+ import { linkIssuesToTestcaseRun, fetchIssues, updateIssue, createIssue, fetchIssuesLinkedToTestCase } from "./issues.js";
4
+ import { updateCycle, createCycle, createRelease, getPlatforms, getBuilds, getReleasesCycles, getProjectInfo, getProjects } from "./project.js";
5
+ import { fetchRequirementsLinkedToTestCase, fetchRequirementDetails, fetchRequirements } from "./requirement.js";
6
+ import { fetchTestCasesLinkedToRequirement, linkRequirementToTestCase, fetchTestCaseExecutions, fetchTestCaseSteps, fetchTestCaseVersionDetails, fetchTestCaseDetails, fetchTestCases, updateTestCase, createTestCases } from "./testcase.js";
7
+ import { linkPlatformsToTestSuite, fetchLinkedIssuesByTestCaseRun, fetchTestCaseRunsByTestSuiteRun, bulkUpdateExecutionStatus, fetchExecutionsByTestSuite, fetchTestCasesByTestSuite, reqLinkedTestCasesToTestSuite, linkTestCasesToTestSuite, fetchTestSuitesForTestCase, fetchTestSuites, updateTestSuite, createTestSuites } from "./testsuite.js";
8
+ const QMETRY_HANDLER_MAP = {
9
+ [QMetryToolsHandlers.FETCH_PROJECTS]: getProjects,
10
+ [QMetryToolsHandlers.SET_PROJECT_INFO]: getProjectInfo,
11
+ [QMetryToolsHandlers.FETCH_PROJECT_INFO]: getProjectInfo,
12
+ [QMetryToolsHandlers.FETCH_RELEASES_CYCLES]: getReleasesCycles,
13
+ [QMetryToolsHandlers.FETCH_BUILDS]: getBuilds,
14
+ [QMetryToolsHandlers.FETCH_PLATFORMS]: getPlatforms,
15
+ [QMetryToolsHandlers.CREATE_RELEASE]: createRelease,
16
+ [QMetryToolsHandlers.CREATE_CYCLE]: createCycle,
17
+ [QMetryToolsHandlers.UPDATE_CYCLE]: updateCycle,
18
+ [QMetryToolsHandlers.CREATE_TEST_CASE]: createTestCases,
19
+ [QMetryToolsHandlers.UPDATE_TEST_CASE]: updateTestCase,
20
+ [QMetryToolsHandlers.FETCH_TEST_CASES]: fetchTestCases,
21
+ [QMetryToolsHandlers.FETCH_TEST_CASE_DETAILS]: fetchTestCaseDetails,
22
+ [QMetryToolsHandlers.FETCH_TEST_CASE_VERSION_DETAILS]: fetchTestCaseVersionDetails,
23
+ [QMetryToolsHandlers.FETCH_TEST_CASE_STEPS]: fetchTestCaseSteps,
24
+ [QMetryToolsHandlers.FETCH_TEST_CASE_EXECUTIONS]: fetchTestCaseExecutions,
25
+ [QMetryToolsHandlers.LINK_REQUIREMENT_TO_TESTCASE]: linkRequirementToTestCase,
26
+ [QMetryToolsHandlers.FETCH_REQUIREMENTS]: fetchRequirements,
27
+ [QMetryToolsHandlers.FETCH_REQUIREMENT_DETAILS]: fetchRequirementDetails,
28
+ [QMetryToolsHandlers.FETCH_TESTCASES_LINKED_TO_REQUIREMENT]: fetchTestCasesLinkedToRequirement,
29
+ [QMetryToolsHandlers.FETCH_REQUIREMENTS_LINKED_TO_TESTCASE]: fetchRequirementsLinkedToTestCase,
30
+ [QMetryToolsHandlers.CREATE_TEST_SUITE]: createTestSuites,
31
+ [QMetryToolsHandlers.UPDATE_TEST_SUITE]: updateTestSuite,
32
+ [QMetryToolsHandlers.FETCH_TEST_SUITES]: fetchTestSuites,
33
+ [QMetryToolsHandlers.FETCH_TESTSUITES_FOR_TESTCASE]: fetchTestSuitesForTestCase,
34
+ [QMetryToolsHandlers.LINK_TESTCASES_TO_TESTSUITE]: linkTestCasesToTestSuite,
35
+ [QMetryToolsHandlers.REQUIREMENTS_LINKED_TESTCASES_TO_TESTSUITE]: reqLinkedTestCasesToTestSuite,
36
+ [QMetryToolsHandlers.FETCH_TESTCASES_BY_TESTSUITE]: fetchTestCasesByTestSuite,
37
+ [QMetryToolsHandlers.FETCH_EXECUTIONS_BY_TESTSUITE]: fetchExecutionsByTestSuite,
38
+ [QMetryToolsHandlers.BULK_UPDATE_EXECUTION_STATUS]: bulkUpdateExecutionStatus,
39
+ [QMetryToolsHandlers.FETCH_TESTCASE_RUNS_BY_TESTSUITE_RUN]: fetchTestCaseRunsByTestSuiteRun,
40
+ [QMetryToolsHandlers.FETCH_LINKED_ISSUES_BY_TESTCASE_RUN]: fetchLinkedIssuesByTestCaseRun,
41
+ [QMetryToolsHandlers.FETCH_ISSUES_LINKED_TO_TESTCASE]: fetchIssuesLinkedToTestCase,
42
+ [QMetryToolsHandlers.CREATE_ISSUE]: createIssue,
43
+ [QMetryToolsHandlers.UPDATE_ISSUE]: updateIssue,
44
+ [QMetryToolsHandlers.FETCH_ISSUES]: fetchIssues,
45
+ [QMetryToolsHandlers.LINK_ISSUES_TO_TESTCASE_RUN]: linkIssuesToTestcaseRun,
46
+ [QMetryToolsHandlers.LINK_PLATFORMS_TO_TESTSUITE]: linkPlatformsToTestSuite,
47
+ [QMetryToolsHandlers.IMPORT_AUTOMATION_RESULTS]: importAutomationResults,
48
+ [QMetryToolsHandlers.FETCH_AUTOMATION_STATUS]: getAutomationStatus
49
+ };
50
+ export {
51
+ QMETRY_HANDLER_MAP
49
52
  };