@muggleai/mcp-qa-gateway 1.0.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 (146) hide show
  1. package/README.md +185 -0
  2. package/dist/scripts/phase0-smoke.d.ts +7 -0
  3. package/dist/scripts/phase0-smoke.d.ts.map +1 -0
  4. package/dist/scripts/phase0-smoke.js +1712 -0
  5. package/dist/scripts/phase0-smoke.js.map +1 -0
  6. package/dist/scripts/types/phase0-smoke-types.d.ts +89 -0
  7. package/dist/scripts/types/phase0-smoke-types.d.ts.map +1 -0
  8. package/dist/scripts/types/phase0-smoke-types.js +3 -0
  9. package/dist/scripts/types/phase0-smoke-types.js.map +1 -0
  10. package/dist/src/__tests__/helpers/mock-setup.d.ts +28 -0
  11. package/dist/src/__tests__/helpers/mock-setup.d.ts.map +1 -0
  12. package/dist/src/__tests__/helpers/mock-setup.js +44 -0
  13. package/dist/src/__tests__/helpers/mock-setup.js.map +1 -0
  14. package/dist/src/__tests__/helpers/test-fixtures.d.ts +38 -0
  15. package/dist/src/__tests__/helpers/test-fixtures.d.ts.map +1 -0
  16. package/dist/src/__tests__/helpers/test-fixtures.js +62 -0
  17. package/dist/src/__tests__/helpers/test-fixtures.js.map +1 -0
  18. package/dist/src/__tests__/tools/artifact-tools.test.d.ts +9 -0
  19. package/dist/src/__tests__/tools/artifact-tools.test.d.ts.map +1 -0
  20. package/dist/src/__tests__/tools/artifact-tools.test.js +307 -0
  21. package/dist/src/__tests__/tools/artifact-tools.test.js.map +1 -0
  22. package/dist/src/__tests__/tools/prd-file-tools.test.d.ts +7 -0
  23. package/dist/src/__tests__/tools/prd-file-tools.test.d.ts.map +1 -0
  24. package/dist/src/__tests__/tools/prd-file-tools.test.js +278 -0
  25. package/dist/src/__tests__/tools/prd-file-tools.test.js.map +1 -0
  26. package/dist/src/__tests__/tools/project-tools.test.d.ts +7 -0
  27. package/dist/src/__tests__/tools/project-tools.test.d.ts.map +1 -0
  28. package/dist/src/__tests__/tools/project-tools.test.js +281 -0
  29. package/dist/src/__tests__/tools/project-tools.test.js.map +1 -0
  30. package/dist/src/__tests__/tools/recommendation-tools.test.d.ts +6 -0
  31. package/dist/src/__tests__/tools/recommendation-tools.test.d.ts.map +1 -0
  32. package/dist/src/__tests__/tools/recommendation-tools.test.js +193 -0
  33. package/dist/src/__tests__/tools/recommendation-tools.test.js.map +1 -0
  34. package/dist/src/__tests__/tools/report-tools.test.d.ts +7 -0
  35. package/dist/src/__tests__/tools/report-tools.test.d.ts.map +1 -0
  36. package/dist/src/__tests__/tools/report-tools.test.js +226 -0
  37. package/dist/src/__tests__/tools/report-tools.test.js.map +1 -0
  38. package/dist/src/__tests__/tools/secret-tools.test.d.ts +6 -0
  39. package/dist/src/__tests__/tools/secret-tools.test.d.ts.map +1 -0
  40. package/dist/src/__tests__/tools/secret-tools.test.js +243 -0
  41. package/dist/src/__tests__/tools/secret-tools.test.js.map +1 -0
  42. package/dist/src/__tests__/tools/test-case-prompt-tools.test.d.ts +6 -0
  43. package/dist/src/__tests__/tools/test-case-prompt-tools.test.d.ts.map +1 -0
  44. package/dist/src/__tests__/tools/test-case-prompt-tools.test.js +291 -0
  45. package/dist/src/__tests__/tools/test-case-prompt-tools.test.js.map +1 -0
  46. package/dist/src/__tests__/tools/tool-registry.test.d.ts +7 -0
  47. package/dist/src/__tests__/tools/tool-registry.test.d.ts.map +1 -0
  48. package/dist/src/__tests__/tools/tool-registry.test.js +205 -0
  49. package/dist/src/__tests__/tools/tool-registry.test.js.map +1 -0
  50. package/dist/src/__tests__/tools/use-case-tools.test.d.ts +7 -0
  51. package/dist/src/__tests__/tools/use-case-tools.test.d.ts.map +1 -0
  52. package/dist/src/__tests__/tools/use-case-tools.test.js +177 -0
  53. package/dist/src/__tests__/tools/use-case-tools.test.js.map +1 -0
  54. package/dist/src/__tests__/tools/workflow-tools.test.d.ts +15 -0
  55. package/dist/src/__tests__/tools/workflow-tools.test.d.ts.map +1 -0
  56. package/dist/src/__tests__/tools/workflow-tools.test.js +627 -0
  57. package/dist/src/__tests__/tools/workflow-tools.test.js.map +1 -0
  58. package/dist/src/config/index.d.ts +18 -0
  59. package/dist/src/config/index.d.ts.map +1 -0
  60. package/dist/src/config/index.js +76 -0
  61. package/dist/src/config/index.js.map +1 -0
  62. package/dist/src/index.d.ts +21 -0
  63. package/dist/src/index.d.ts.map +1 -0
  64. package/dist/src/index.js +88 -0
  65. package/dist/src/index.js.map +1 -0
  66. package/dist/src/interfaces/caller-credentials.d.ts +10 -0
  67. package/dist/src/interfaces/caller-credentials.d.ts.map +1 -0
  68. package/dist/src/interfaces/caller-credentials.js +3 -0
  69. package/dist/src/interfaces/caller-credentials.js.map +1 -0
  70. package/dist/src/interfaces/gateway-config.d.ts +28 -0
  71. package/dist/src/interfaces/gateway-config.d.ts.map +1 -0
  72. package/dist/src/interfaces/gateway-config.js +3 -0
  73. package/dist/src/interfaces/gateway-config.js.map +1 -0
  74. package/dist/src/interfaces/index.d.ts +13 -0
  75. package/dist/src/interfaces/index.d.ts.map +1 -0
  76. package/dist/src/interfaces/index.js +7 -0
  77. package/dist/src/interfaces/index.js.map +1 -0
  78. package/dist/src/interfaces/mcp-tool-call-protocol.d.ts +61 -0
  79. package/dist/src/interfaces/mcp-tool-call-protocol.d.ts.map +1 -0
  80. package/dist/src/interfaces/mcp-tool-call-protocol.js +7 -0
  81. package/dist/src/interfaces/mcp-tool-call-protocol.js.map +1 -0
  82. package/dist/src/interfaces/pagination.d.ts +24 -0
  83. package/dist/src/interfaces/pagination.d.ts.map +1 -0
  84. package/dist/src/interfaces/pagination.js +6 -0
  85. package/dist/src/interfaces/pagination.js.map +1 -0
  86. package/dist/src/interfaces/tool-definition.d.ts +22 -0
  87. package/dist/src/interfaces/tool-definition.d.ts.map +1 -0
  88. package/dist/src/interfaces/tool-definition.js +6 -0
  89. package/dist/src/interfaces/tool-definition.js.map +1 -0
  90. package/dist/src/interfaces/tool-mapping.d.ts +20 -0
  91. package/dist/src/interfaces/tool-mapping.d.ts.map +1 -0
  92. package/dist/src/interfaces/tool-mapping.js +6 -0
  93. package/dist/src/interfaces/tool-mapping.js.map +1 -0
  94. package/dist/src/interfaces/upstream-call.d.ts +27 -0
  95. package/dist/src/interfaces/upstream-call.d.ts.map +1 -0
  96. package/dist/src/interfaces/upstream-call.js +3 -0
  97. package/dist/src/interfaces/upstream-call.js.map +1 -0
  98. package/dist/src/interfaces/upstream-response.d.ts +12 -0
  99. package/dist/src/interfaces/upstream-response.d.ts.map +1 -0
  100. package/dist/src/interfaces/upstream-response.js +3 -0
  101. package/dist/src/interfaces/upstream-response.js.map +1 -0
  102. package/dist/src/server/http-server.d.ts +13 -0
  103. package/dist/src/server/http-server.d.ts.map +1 -0
  104. package/dist/src/server/http-server.js +219 -0
  105. package/dist/src/server/http-server.js.map +1 -0
  106. package/dist/src/server/mcp-server.d.ts +11 -0
  107. package/dist/src/server/mcp-server.d.ts.map +1 -0
  108. package/dist/src/server/mcp-server.js +363 -0
  109. package/dist/src/server/mcp-server.js.map +1 -0
  110. package/dist/src/server/session-credentials.d.ts +8 -0
  111. package/dist/src/server/session-credentials.d.ts.map +1 -0
  112. package/dist/src/server/session-credentials.js +24 -0
  113. package/dist/src/server/session-credentials.js.map +1 -0
  114. package/dist/src/tools/constants.d.ts +6 -0
  115. package/dist/src/tools/constants.d.ts.map +1 -0
  116. package/dist/src/tools/constants.js +9 -0
  117. package/dist/src/tools/constants.js.map +1 -0
  118. package/dist/src/tools/index.d.ts +7 -0
  119. package/dist/src/tools/index.d.ts.map +1 -0
  120. package/dist/src/tools/index.js +23 -0
  121. package/dist/src/tools/index.js.map +1 -0
  122. package/dist/src/tools/schemas.d.ts +906 -0
  123. package/dist/src/tools/schemas.d.ts.map +1 -0
  124. package/dist/src/tools/schemas.js +386 -0
  125. package/dist/src/tools/schemas.js.map +1 -0
  126. package/dist/src/tools/tool-registry.d.ts +26 -0
  127. package/dist/src/tools/tool-registry.d.ts.map +1 -0
  128. package/dist/src/tools/tool-registry.js +1142 -0
  129. package/dist/src/tools/tool-registry.js.map +1 -0
  130. package/dist/src/types/index.d.ts +35 -0
  131. package/dist/src/types/index.d.ts.map +1 -0
  132. package/dist/src/types/index.js +55 -0
  133. package/dist/src/types/index.js.map +1 -0
  134. package/dist/src/upstream/prompt-service-client.d.ts +62 -0
  135. package/dist/src/upstream/prompt-service-client.d.ts.map +1 -0
  136. package/dist/src/upstream/prompt-service-client.js +329 -0
  137. package/dist/src/upstream/prompt-service-client.js.map +1 -0
  138. package/dist/src/utils/logger.d.ts +17 -0
  139. package/dist/src/utils/logger.d.ts.map +1 -0
  140. package/dist/src/utils/logger.js +64 -0
  141. package/dist/src/utils/logger.js.map +1 -0
  142. package/dist/vitest.config.d.ts +3 -0
  143. package/dist/vitest.config.d.ts.map +1 -0
  144. package/dist/vitest.config.js +21 -0
  145. package/dist/vitest.config.js.map +1 -0
  146. package/package.json +66 -0
@@ -0,0 +1,1142 @@
1
+ "use strict";
2
+ /**
3
+ * Tool registry for MCP QA Gateway.
4
+ * Maps tool names to their implementations and upstream API calls.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.allTools = void 0;
41
+ exports.getToolByName = getToolByName;
42
+ exports.executeTool = executeTool;
43
+ const index_js_1 = require("../config/index.js");
44
+ const prompt_service_client_js_1 = require("../upstream/prompt-service-client.js");
45
+ const constants_js_1 = require("./constants.js");
46
+ const schemas = __importStar(require("./schemas.js"));
47
+ // =============================================================================
48
+ // Helper Functions
49
+ // =============================================================================
50
+ /**
51
+ * Default response mapper (pass through data).
52
+ */
53
+ function defaultResponseMapper(response) {
54
+ return response.data;
55
+ }
56
+ // =============================================================================
57
+ // Project Tools
58
+ // =============================================================================
59
+ const projectTools = [
60
+ {
61
+ name: "qa_project_create",
62
+ description: "Create a new QA testing project. Projects organize use cases, test cases, and test scripts.",
63
+ inputSchema: schemas.ProjectCreateInputSchema,
64
+ mapToUpstream: (input) => {
65
+ const data = input;
66
+ return {
67
+ method: "POST",
68
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects`,
69
+ body: {
70
+ name: data.projectName,
71
+ description: data.description,
72
+ url: data.url,
73
+ },
74
+ };
75
+ },
76
+ },
77
+ {
78
+ name: "qa_project_get",
79
+ description: "Get details of a specific project by ID.",
80
+ inputSchema: schemas.ProjectGetInputSchema,
81
+ mapToUpstream: (input) => {
82
+ const data = input;
83
+ return {
84
+ method: "GET",
85
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}`,
86
+ };
87
+ },
88
+ },
89
+ {
90
+ name: "qa_project_update",
91
+ description: "Update an existing project's details.",
92
+ inputSchema: schemas.ProjectUpdateInputSchema,
93
+ mapToUpstream: (input) => {
94
+ const data = input;
95
+ const body = {
96
+ id: data.projectId,
97
+ };
98
+ if (data.projectName !== undefined)
99
+ body.name = data.projectName;
100
+ if (data.description !== undefined)
101
+ body.description = data.description;
102
+ if (data.url !== undefined)
103
+ body.url = data.url;
104
+ return {
105
+ method: "PUT",
106
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}`,
107
+ body: body,
108
+ };
109
+ },
110
+ },
111
+ {
112
+ name: "qa_project_list",
113
+ description: "List all projects accessible to the authenticated user.",
114
+ inputSchema: schemas.ProjectListInputSchema,
115
+ mapToUpstream: (input) => {
116
+ const data = input;
117
+ return {
118
+ method: "GET",
119
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects`,
120
+ queryParams: {
121
+ page: data.page,
122
+ pageSize: data.pageSize,
123
+ },
124
+ };
125
+ },
126
+ },
127
+ {
128
+ name: "qa_project_delete",
129
+ description: "Delete a project and all associated entities (use cases, test cases, test scripts). This is a soft delete.",
130
+ inputSchema: schemas.ProjectDeleteInputSchema,
131
+ mapToUpstream: (input) => {
132
+ const data = input;
133
+ return {
134
+ method: "DELETE",
135
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}`,
136
+ };
137
+ },
138
+ },
139
+ ];
140
+ // =============================================================================
141
+ // PRD File Tools
142
+ // =============================================================================
143
+ const prdFileTools = [
144
+ {
145
+ name: "qa_prd_file_upload",
146
+ description: "Upload a PRD (Product Requirements Document) file to a project. The file content should be base64-encoded.",
147
+ inputSchema: schemas.PrdFileUploadInputSchema,
148
+ mapToUpstream: (input) => {
149
+ const data = input;
150
+ return {
151
+ method: "POST",
152
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/use-case/prd-file-upload`,
153
+ multipartFormData: {
154
+ fileFieldName: "file",
155
+ fileName: data.fileName,
156
+ contentType: data.contentType || "application/octet-stream",
157
+ fileBase64: data.contentBase64,
158
+ },
159
+ };
160
+ },
161
+ },
162
+ {
163
+ name: "qa_prd_file_list_by_project",
164
+ description: "List all PRD files associated with a project.",
165
+ inputSchema: schemas.PrdFileListInputSchema,
166
+ mapToUpstream: (input) => {
167
+ const data = input;
168
+ return {
169
+ method: "GET",
170
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/prd-files`,
171
+ };
172
+ },
173
+ },
174
+ {
175
+ name: "qa_prd_file_delete",
176
+ description: "Delete a PRD file from a project.",
177
+ inputSchema: schemas.PrdFileDeleteInputSchema,
178
+ mapToUpstream: (input) => {
179
+ const data = input;
180
+ return {
181
+ method: "DELETE",
182
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/prd-files/${data.prdFileId}`,
183
+ };
184
+ },
185
+ },
186
+ {
187
+ name: "qa_workflow_start_prd_file_process",
188
+ description: "Start a PRD file processing workflow to extract use cases from uploaded PRD documents. Requires the prdFilePath, contentChecksum, and fileSize from the upload response.",
189
+ inputSchema: schemas.PrdFileProcessStartInputSchema,
190
+ mapToUpstream: (input) => {
191
+ const data = input;
192
+ return {
193
+ method: "POST",
194
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/use-case/prd-file-process`,
195
+ body: {
196
+ projectId: data.projectId,
197
+ name: data.name,
198
+ description: data.description,
199
+ prdFilePath: data.prdFilePath,
200
+ originalFileName: data.originalFileName,
201
+ url: data.url,
202
+ contentChecksum: data.contentChecksum,
203
+ fileSize: data.fileSize,
204
+ },
205
+ };
206
+ },
207
+ },
208
+ {
209
+ name: "qa_workflow_get_prd_file_process_latest_run",
210
+ description: "Get the latest run status of a PRD file processing workflow.",
211
+ inputSchema: schemas.PrdFileProcessLatestRunInputSchema,
212
+ mapToUpstream: (input) => {
213
+ const data = input;
214
+ return {
215
+ method: "GET",
216
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/use-case/prd-file-process/${data.workflowRuntimeId}/run/latest`,
217
+ };
218
+ },
219
+ },
220
+ ];
221
+ // =============================================================================
222
+ // Secret Tools
223
+ // =============================================================================
224
+ const secretTools = [
225
+ {
226
+ name: "qa_secret_list",
227
+ description: "List all secrets (credentials) for a project. Secret values are not returned for security.",
228
+ inputSchema: schemas.SecretListInputSchema,
229
+ mapToUpstream: (input) => {
230
+ const data = input;
231
+ return {
232
+ method: "GET",
233
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/secrets`,
234
+ queryParams: { projectId: data.projectId },
235
+ };
236
+ },
237
+ },
238
+ {
239
+ name: "qa_secret_create",
240
+ description: "Create a new secret (credential) for a project. Secrets can be used in test workflows.",
241
+ inputSchema: schemas.SecretCreateInputSchema,
242
+ mapToUpstream: (input) => {
243
+ const data = input;
244
+ return {
245
+ method: "POST",
246
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/secrets`,
247
+ body: {
248
+ projectId: data.projectId,
249
+ name: data.name,
250
+ value: data.value,
251
+ description: data.description,
252
+ },
253
+ };
254
+ },
255
+ },
256
+ {
257
+ name: "qa_secret_get",
258
+ description: "Get details of a specific secret by ID. The secret value is not returned for security.",
259
+ inputSchema: schemas.SecretGetInputSchema,
260
+ mapToUpstream: (input) => {
261
+ const data = input;
262
+ return {
263
+ method: "GET",
264
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/secrets/${data.secretId}`,
265
+ };
266
+ },
267
+ },
268
+ {
269
+ name: "qa_secret_update",
270
+ description: "Update an existing secret.",
271
+ inputSchema: schemas.SecretUpdateInputSchema,
272
+ mapToUpstream: (input) => {
273
+ const data = input;
274
+ const body = {};
275
+ if (data.name !== undefined)
276
+ body.name = data.name;
277
+ if (data.value !== undefined)
278
+ body.value = data.value;
279
+ if (data.description !== undefined)
280
+ body.description = data.description;
281
+ return {
282
+ method: "PUT",
283
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/secrets/${data.secretId}`,
284
+ body: body,
285
+ };
286
+ },
287
+ },
288
+ {
289
+ name: "qa_secret_delete",
290
+ description: "Delete a secret from a project.",
291
+ inputSchema: schemas.SecretDeleteInputSchema,
292
+ mapToUpstream: (input) => {
293
+ const data = input;
294
+ return {
295
+ method: "DELETE",
296
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/secrets/${data.secretId}`,
297
+ };
298
+ },
299
+ },
300
+ ];
301
+ // =============================================================================
302
+ // Use Case Tools
303
+ // =============================================================================
304
+ const useCaseTools = [
305
+ {
306
+ name: "qa_use_case_discovery_memory_get",
307
+ description: "Get the use case discovery memory for a project, including all discovered use case candidates with their status, evidence (screenshots, notes), and evaluation scores.",
308
+ inputSchema: schemas.UseCaseDiscoveryMemoryGetInputSchema,
309
+ mapToUpstream: (input) => {
310
+ const data = input;
311
+ return {
312
+ method: "GET",
313
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/use-case-discovery-memory`,
314
+ };
315
+ },
316
+ },
317
+ {
318
+ name: "qa_use_case_candidates_approve",
319
+ description: "Approve (graduate) selected use case candidates into actual use cases. This promotes candidates from 'candidate' status to 'graduated' status.",
320
+ inputSchema: schemas.UseCaseCandidatesApproveInputSchema,
321
+ mapToUpstream: (input) => {
322
+ const data = input;
323
+ return {
324
+ method: "POST",
325
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/use-case-discovery-memory/graduate`,
326
+ body: {
327
+ approveIds: data.approvedCandidateIds,
328
+ },
329
+ };
330
+ },
331
+ },
332
+ {
333
+ name: "qa_use_case_list",
334
+ description: "List all use cases for a project.",
335
+ inputSchema: schemas.UseCaseListInputSchema,
336
+ mapToUpstream: (input) => {
337
+ const data = input;
338
+ return {
339
+ method: "GET",
340
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/use-cases`,
341
+ queryParams: {
342
+ projectId: data.projectId,
343
+ page: data.page,
344
+ pageSize: data.pageSize,
345
+ },
346
+ };
347
+ },
348
+ },
349
+ {
350
+ name: "qa_use_case_get",
351
+ description: "Get details of a specific use case by ID.",
352
+ inputSchema: schemas.UseCaseGetInputSchema,
353
+ mapToUpstream: (input) => {
354
+ const data = input;
355
+ return {
356
+ method: "GET",
357
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/use-cases/${data.useCaseId}`,
358
+ };
359
+ },
360
+ },
361
+ {
362
+ name: "qa_use_case_prompt_preview",
363
+ description: "Preview a use case generated from a natural language instruction without saving. Returns a complete use case structure including title, user story, description, and breakdown items that can be reviewed before creation.",
364
+ inputSchema: schemas.UseCasePromptPreviewInputSchema,
365
+ mapToUpstream: (input) => {
366
+ const data = input;
367
+ return {
368
+ method: "POST",
369
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/use-cases/prompt/preview`,
370
+ body: {
371
+ instruction: data.instruction,
372
+ },
373
+ };
374
+ },
375
+ },
376
+ {
377
+ name: "qa_use_case_create_from_prompts",
378
+ description: "Create one or more use cases from natural language instructions. Each prompt generates a use case with title, user story, description, and breakdown items. After creation, test case detection workflows are automatically triggered.",
379
+ inputSchema: schemas.UseCaseCreateFromPromptsInputSchema,
380
+ mapToUpstream: (input) => {
381
+ const data = input;
382
+ return {
383
+ method: "POST",
384
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/use-cases/prompts/bulk`,
385
+ body: {
386
+ projectId: data.projectId,
387
+ prompts: data.prompts,
388
+ },
389
+ };
390
+ },
391
+ },
392
+ {
393
+ name: "qa_use_case_update_from_prompt",
394
+ description: "Update an existing use case by regenerating its fields from a new natural language instruction. This replaces the title, user story, description, and breakdown items, then triggers test case detection workflows.",
395
+ inputSchema: schemas.UseCaseUpdateFromPromptInputSchema,
396
+ mapToUpstream: (input) => {
397
+ const data = input;
398
+ return {
399
+ method: "POST",
400
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/use-cases/${data.useCaseId}/prompt`,
401
+ body: {
402
+ instruction: data.instruction,
403
+ },
404
+ };
405
+ },
406
+ },
407
+ ];
408
+ // =============================================================================
409
+ // Workflow Tools
410
+ // =============================================================================
411
+ const config = (0, index_js_1.getConfig)();
412
+ const workflowTools = [
413
+ {
414
+ name: "qa_workflow_start_website_scan",
415
+ description: "Start a website scan workflow to discover use cases from a URL. This crawls the website and proposes use case candidates based on the site structure and content.",
416
+ inputSchema: schemas.WorkflowStartWebsiteScanInputSchema,
417
+ mapToUpstream: (input) => {
418
+ const data = input;
419
+ return {
420
+ method: "POST",
421
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/use-case/website-scan`,
422
+ body: {
423
+ projectId: data.projectId,
424
+ url: data.url,
425
+ description: data.description,
426
+ archiveUnapproved: data.archiveUnapproved,
427
+ },
428
+ timeoutMs: config.workflowTimeoutMs,
429
+ };
430
+ },
431
+ },
432
+ {
433
+ name: "qa_workflow_list_website_scan_runtimes",
434
+ description: "List website scan workflow runtimes, optionally filtered by project.",
435
+ inputSchema: schemas.WorkflowListRuntimesInputSchema,
436
+ mapToUpstream: (input) => {
437
+ const data = input;
438
+ return {
439
+ method: "GET",
440
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/use-case/website-scan/workflowRuntimes`,
441
+ queryParams: { projectId: data.projectId },
442
+ };
443
+ },
444
+ },
445
+ {
446
+ name: "qa_workflow_get_website_scan_latest_run",
447
+ description: "Get the latest run status for a website scan workflow runtime.",
448
+ inputSchema: schemas.WorkflowGetLatestRunInputSchema,
449
+ mapToUpstream: (input) => {
450
+ const data = input;
451
+ return {
452
+ method: "GET",
453
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/use-case/website-scan/${data.workflowRuntimeId}/run/latest`,
454
+ };
455
+ },
456
+ },
457
+ {
458
+ name: "qa_workflow_start_test_case_detection",
459
+ description: "Start a test case detection workflow to generate test cases from approved use cases.",
460
+ inputSchema: schemas.WorkflowStartTestCaseDetectionInputSchema,
461
+ mapToUpstream: (input) => {
462
+ const data = input;
463
+ return {
464
+ method: "POST",
465
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-case/test-case-detection`,
466
+ body: {
467
+ projectId: data.projectId,
468
+ useCaseId: data.useCaseId,
469
+ name: data.name,
470
+ description: data.description,
471
+ url: data.url,
472
+ },
473
+ timeoutMs: config.workflowTimeoutMs,
474
+ };
475
+ },
476
+ },
477
+ {
478
+ name: "qa_workflow_list_test_case_detection_runtimes",
479
+ description: "List test case detection workflow runtimes.",
480
+ inputSchema: schemas.WorkflowListRuntimesInputSchema,
481
+ mapToUpstream: (input) => {
482
+ const data = input;
483
+ return {
484
+ method: "GET",
485
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-case/test-case-detection/workflowRuntimes`,
486
+ queryParams: { projectId: data.projectId },
487
+ };
488
+ },
489
+ },
490
+ {
491
+ name: "qa_workflow_get_test_case_detection_latest_run",
492
+ description: "Get the latest run status for a test case detection workflow runtime.",
493
+ inputSchema: schemas.WorkflowGetLatestRunInputSchema,
494
+ mapToUpstream: (input) => {
495
+ const data = input;
496
+ return {
497
+ method: "GET",
498
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-case/test-case-detection/${data.workflowRuntimeId}/run/latest`,
499
+ };
500
+ },
501
+ },
502
+ {
503
+ name: "qa_workflow_start_test_script_generation",
504
+ description: "Start a test script generation workflow to generate executable test scripts from test cases.",
505
+ inputSchema: schemas.WorkflowStartTestScriptGenerationInputSchema,
506
+ mapToUpstream: (input) => {
507
+ const data = input;
508
+ return {
509
+ method: "POST",
510
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-generation`,
511
+ body: {
512
+ projectId: data.projectId,
513
+ testCaseId: data.testCaseId,
514
+ useCaseId: data.useCaseId,
515
+ name: data.name,
516
+ url: data.url,
517
+ goal: data.goal,
518
+ precondition: data.precondition,
519
+ instructions: data.instructions,
520
+ expectedResult: data.expectedResult,
521
+ },
522
+ timeoutMs: config.workflowTimeoutMs,
523
+ };
524
+ },
525
+ },
526
+ {
527
+ name: "qa_workflow_get_test_script_generation_latest_run",
528
+ description: "Get the latest run status for a test script generation workflow runtime.",
529
+ inputSchema: schemas.WorkflowGetLatestRunInputSchema,
530
+ mapToUpstream: (input) => {
531
+ const data = input;
532
+ return {
533
+ method: "GET",
534
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-generation/${data.workflowRuntimeId}/run/latest`,
535
+ };
536
+ },
537
+ },
538
+ {
539
+ name: "qa_workflow_get_latest_test_script_generation_runtime_by_test_case",
540
+ description: "Get the latest test script generation runtime for a specific test case.",
541
+ inputSchema: schemas.WorkflowGetLatestScriptGenByTestCaseInputSchema,
542
+ mapToUpstream: (input) => {
543
+ const data = input;
544
+ return {
545
+ method: "GET",
546
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-generation/testcases/${data.testCaseId}/runtime/latest`,
547
+ };
548
+ },
549
+ },
550
+ {
551
+ name: "qa_workflow_start_test_script_replay",
552
+ description: "Start a test script replay workflow to execute a single test script.",
553
+ inputSchema: schemas.WorkflowStartTestScriptReplayInputSchema,
554
+ mapToUpstream: (input) => {
555
+ const data = input;
556
+ return {
557
+ method: "POST",
558
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-replay`,
559
+ body: {
560
+ projectId: data.projectId,
561
+ useCaseId: data.useCaseId,
562
+ testCaseId: data.testCaseId,
563
+ testScriptId: data.testScriptId,
564
+ name: data.name,
565
+ },
566
+ timeoutMs: config.workflowTimeoutMs,
567
+ };
568
+ },
569
+ },
570
+ {
571
+ name: "qa_workflow_get_test_script_replay_latest_run",
572
+ description: "Get the latest run status for a test script replay workflow runtime.",
573
+ inputSchema: schemas.WorkflowGetLatestRunInputSchema,
574
+ mapToUpstream: (input) => {
575
+ const data = input;
576
+ return {
577
+ method: "GET",
578
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-replay/${data.workflowRuntimeId}/run/latest`,
579
+ };
580
+ },
581
+ },
582
+ {
583
+ name: "qa_workflow_start_test_script_replay_bulk",
584
+ description: "Start a bulk test script replay workflow to execute multiple test scripts in parallel.",
585
+ inputSchema: schemas.WorkflowStartTestScriptReplayBulkInputSchema,
586
+ mapToUpstream: (input) => {
587
+ const data = input;
588
+ return {
589
+ method: "POST",
590
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-replay/bulk/workflowRuntimes`,
591
+ body: {
592
+ projectId: data.projectId,
593
+ name: data.name,
594
+ intervalSec: data.intervalSec,
595
+ useCaseId: data.useCaseId,
596
+ namePrefix: data.namePrefix,
597
+ limit: data.limit,
598
+ testCaseIds: data.testCaseIds,
599
+ repeatPerTestCase: data.repeatPerTestCase,
600
+ },
601
+ timeoutMs: config.workflowTimeoutMs,
602
+ };
603
+ },
604
+ },
605
+ {
606
+ name: "qa_workflow_list_test_script_replay_bulk_runtimes",
607
+ description: "List bulk test script replay workflow runtimes.",
608
+ inputSchema: schemas.WorkflowListRuntimesInputSchema,
609
+ mapToUpstream: (input) => {
610
+ const data = input;
611
+ return {
612
+ method: "GET",
613
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-replay/bulk/workflowRuntimes`,
614
+ queryParams: { projectId: data.projectId },
615
+ };
616
+ },
617
+ },
618
+ {
619
+ name: "qa_workflow_get_test_script_replay_bulk_latest_run",
620
+ description: "Get the latest run status for a bulk test script replay workflow runtime.",
621
+ inputSchema: schemas.WorkflowGetLatestRunInputSchema,
622
+ mapToUpstream: (input) => {
623
+ const data = input;
624
+ return {
625
+ method: "GET",
626
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-replay/bulk/${data.workflowRuntimeId}/run/latest`,
627
+ };
628
+ },
629
+ },
630
+ {
631
+ name: "qa_workflow_get_replay_bulk_run_batch_summary",
632
+ description: "Get the summary of a bulk replay run batch, including pass/fail counts and individual results.",
633
+ inputSchema: schemas.WorkflowGetReplayBulkBatchSummaryInputSchema,
634
+ mapToUpstream: (input) => {
635
+ const data = input;
636
+ return {
637
+ method: "GET",
638
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/test-script/test-script-replay/bulk/run-batch/${data.runBatchId}/summary`,
639
+ };
640
+ },
641
+ },
642
+ {
643
+ name: "qa_workflow_cancel_run",
644
+ description: "Cancel a running workflow run.",
645
+ inputSchema: schemas.WorkflowCancelRunInputSchema,
646
+ mapToUpstream: (input) => {
647
+ const data = input;
648
+ return {
649
+ method: "POST",
650
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/runs/${data.workflowRunId}/cancel`,
651
+ };
652
+ },
653
+ },
654
+ {
655
+ name: "qa_workflow_cancel_runtime",
656
+ description: "Cancel a workflow runtime and all its runs.",
657
+ inputSchema: schemas.WorkflowCancelRuntimeInputSchema,
658
+ mapToUpstream: (input) => {
659
+ const data = input;
660
+ return {
661
+ method: "POST",
662
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/workflow/runtimes/${data.workflowRuntimeId}/cancel`,
663
+ };
664
+ },
665
+ },
666
+ ];
667
+ // =============================================================================
668
+ // Artifact Inspection Tools (Test Cases, Scripts, Summaries)
669
+ // =============================================================================
670
+ const artifactTools = [
671
+ {
672
+ name: "qa_test_case_list",
673
+ description: "List test cases for a project.",
674
+ inputSchema: schemas.TestCaseListInputSchema,
675
+ mapToUpstream: (input) => {
676
+ const data = input;
677
+ return {
678
+ method: "GET",
679
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/test-cases`,
680
+ queryParams: {
681
+ projectId: data.projectId,
682
+ page: data.page,
683
+ pageSize: data.pageSize,
684
+ },
685
+ };
686
+ },
687
+ },
688
+ {
689
+ name: "qa_test_case_get",
690
+ description: "Get details of a specific test case, including steps and expected outcomes.",
691
+ inputSchema: schemas.TestCaseGetInputSchema,
692
+ mapToUpstream: (input) => {
693
+ const data = input;
694
+ return {
695
+ method: "GET",
696
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/test-cases/${data.testCaseId}`,
697
+ };
698
+ },
699
+ },
700
+ {
701
+ name: "qa_test_case_list_by_use_case",
702
+ description: "List test cases for a specific use case.",
703
+ inputSchema: schemas.TestCaseListByUseCaseInputSchema,
704
+ mapToUpstream: (input) => {
705
+ const data = input;
706
+ return {
707
+ method: "GET",
708
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/use-cases/${data.useCaseId}/test-cases`,
709
+ };
710
+ },
711
+ },
712
+ {
713
+ name: "qa_test_case_generate_from_prompt",
714
+ description: "Generate one or more test cases from a natural language prompt. " +
715
+ "Requires project and use case context. Returns preview test cases " +
716
+ "(not persisted) that can be reviewed and then created using qa_test_case_create.",
717
+ inputSchema: schemas.TestCaseGenerateFromPromptInputSchema,
718
+ mapToUpstream: (input) => {
719
+ const data = input;
720
+ return {
721
+ method: "POST",
722
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/use-cases/${data.useCaseId}/test-cases/prompt/preview`,
723
+ body: {
724
+ instruction: data.instruction,
725
+ },
726
+ };
727
+ },
728
+ },
729
+ {
730
+ name: "qa_test_case_create",
731
+ description: "Create a new test case for a use case. Use this to persist test cases " +
732
+ "after reviewing previews from qa_test_case_generate_from_prompt.",
733
+ inputSchema: schemas.TestCaseCreateInputSchema,
734
+ mapToUpstream: (input) => {
735
+ const data = input;
736
+ return {
737
+ method: "POST",
738
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/test-cases`,
739
+ body: {
740
+ projectId: data.projectId,
741
+ useCaseId: data.useCaseId,
742
+ title: data.title,
743
+ description: data.description,
744
+ goal: data.goal,
745
+ precondition: data.precondition,
746
+ expectedResult: data.expectedResult,
747
+ url: data.url,
748
+ status: data.status || "DRAFT",
749
+ priority: data.priority || "MEDIUM",
750
+ tags: data.tags || [],
751
+ category: data.category || "Functional",
752
+ automated: data.automated ?? true,
753
+ },
754
+ };
755
+ },
756
+ },
757
+ {
758
+ name: "qa_test_script_list",
759
+ description: "List test scripts for a project.",
760
+ inputSchema: schemas.TestScriptListInputSchema,
761
+ mapToUpstream: (input) => {
762
+ const data = input;
763
+ return {
764
+ method: "GET",
765
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/test-scripts`,
766
+ queryParams: {
767
+ projectId: data.projectId,
768
+ page: data.page,
769
+ pageSize: data.pageSize,
770
+ },
771
+ };
772
+ },
773
+ },
774
+ {
775
+ name: "qa_test_script_get",
776
+ description: "Get details of a specific test script, including executable steps and screenshots.",
777
+ inputSchema: schemas.TestScriptGetInputSchema,
778
+ mapToUpstream: (input) => {
779
+ const data = input;
780
+ return {
781
+ method: "GET",
782
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/test-scripts/${data.testScriptId}`,
783
+ };
784
+ },
785
+ },
786
+ {
787
+ name: "qa_test_script_list_paginated",
788
+ description: "List test scripts with full pagination support.",
789
+ inputSchema: schemas.TestScriptListPaginatedInputSchema,
790
+ mapToUpstream: (input) => {
791
+ const data = input;
792
+ return {
793
+ method: "GET",
794
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/test-scripts/paginated`,
795
+ queryParams: {
796
+ projectId: data.projectId,
797
+ page: data.page,
798
+ pageSize: data.pageSize,
799
+ },
800
+ };
801
+ },
802
+ },
803
+ {
804
+ name: "qa_project_test_results_summary_get",
805
+ description: "Get a summary of test results for a project, including pass/fail counts and trends.",
806
+ inputSchema: schemas.ProjectTestResultsSummaryInputSchema,
807
+ mapToUpstream: (input) => {
808
+ const data = input;
809
+ return {
810
+ method: "GET",
811
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/testResults`,
812
+ };
813
+ },
814
+ },
815
+ {
816
+ name: "qa_project_test_scripts_summary_get",
817
+ description: "Get a summary of test scripts for a project.",
818
+ inputSchema: schemas.ProjectTestScriptsSummaryInputSchema,
819
+ mapToUpstream: (input) => {
820
+ const data = input;
821
+ return {
822
+ method: "GET",
823
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/test-scripts/summary`,
824
+ };
825
+ },
826
+ },
827
+ {
828
+ name: "qa_project_test_runs_summary_get",
829
+ description: "Get a summary of test runs for a project, including recent execution history.",
830
+ inputSchema: schemas.ProjectTestRunsSummaryInputSchema,
831
+ mapToUpstream: (input) => {
832
+ const data = input;
833
+ return {
834
+ method: "GET",
835
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/projects/${data.projectId}/test-runs/summary`,
836
+ };
837
+ },
838
+ },
839
+ ];
840
+ // =============================================================================
841
+ // Report Tools
842
+ // =============================================================================
843
+ const reportTools = [
844
+ {
845
+ name: "qa_report_stats_summary_get",
846
+ description: "Get report statistics summary for a project, including health score and key metrics.",
847
+ inputSchema: schemas.ReportStatsSummaryInputSchema,
848
+ mapToUpstream: (input) => {
849
+ const data = input;
850
+ return {
851
+ method: "GET",
852
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/report/stats-summary`,
853
+ queryParams: { projectId: data.projectId },
854
+ };
855
+ },
856
+ },
857
+ {
858
+ name: "qa_report_cost_query",
859
+ description: "Query cost/usage data for a project over a date range.",
860
+ inputSchema: schemas.ReportCostQueryInputSchema,
861
+ mapToUpstream: (input) => {
862
+ const data = input;
863
+ return {
864
+ method: "POST",
865
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/report/cost/query`,
866
+ body: {
867
+ projectId: data.projectId,
868
+ startDateKey: data.startDateKey,
869
+ endDateKey: data.endDateKey,
870
+ filterType: data.filterType,
871
+ filterIds: data.filterIds,
872
+ },
873
+ };
874
+ },
875
+ },
876
+ {
877
+ name: "qa_report_preferences_upsert",
878
+ description: "Update report delivery preferences for a project. Configure email, SMS, or webhook delivery channels.",
879
+ inputSchema: schemas.ReportPreferencesUpsertInputSchema,
880
+ mapToUpstream: (input) => {
881
+ const data = input;
882
+ return {
883
+ method: "PUT",
884
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/report/preferences`,
885
+ body: {
886
+ projectId: data.projectId,
887
+ channels: data.channels,
888
+ emails: data.emails,
889
+ phones: data.phones,
890
+ webhookUrl: data.webhookUrl,
891
+ defaultExportFormat: data.defaultExportFormat,
892
+ },
893
+ };
894
+ },
895
+ },
896
+ {
897
+ name: "qa_report_final_generate",
898
+ description: "Generate a final test report for a project. Returns a workflow runtime ID that can be polled for completion.",
899
+ inputSchema: schemas.ReportFinalGenerateInputSchema,
900
+ mapToUpstream: (input) => {
901
+ const data = input;
902
+ return {
903
+ method: "POST",
904
+ path: `${constants_js_1.MUGGLE_TEST_PREFIX}/report/final/generate`,
905
+ body: {
906
+ projectId: data.projectId,
907
+ exportFormat: data.exportFormat,
908
+ },
909
+ timeoutMs: config.workflowTimeoutMs,
910
+ };
911
+ },
912
+ },
913
+ ];
914
+ // =============================================================================
915
+ // Recommendation Tools (No Side Effects)
916
+ // =============================================================================
917
+ const recommendationTools = [
918
+ {
919
+ name: "qa_recommend_schedule",
920
+ description: "Get recommendations for test scheduling based on project needs. This tool provides guidance only and does not create schedules.",
921
+ inputSchema: schemas.RecommendScheduleInputSchema,
922
+ mapToUpstream: () => {
923
+ // This tool returns static recommendations, no upstream call needed
924
+ throw new Error("RECOMMENDATION_ONLY");
925
+ },
926
+ mapFromUpstream: () => {
927
+ return {
928
+ recommendations: [
929
+ {
930
+ title: "Nightly Regression Tests",
931
+ rationale: "Running tests every night catches regressions quickly while minimizing CI resource usage during peak development hours.",
932
+ schedule: "0 2 * * *",
933
+ timezone: "UTC",
934
+ tradeoffs: [
935
+ "Pro: Catches issues overnight, fresh results every morning",
936
+ "Pro: Lower CI costs than running on every commit",
937
+ "Con: Issues discovered after developer context is lost",
938
+ ],
939
+ },
940
+ {
941
+ title: "On-Demand with Smoke Tests",
942
+ rationale: "Run a quick smoke test on every PR, with full regression on merge to main.",
943
+ schedule: "Pull Request trigger + main branch merge",
944
+ tradeoffs: [
945
+ "Pro: Fast feedback on PRs",
946
+ "Pro: Full coverage before release",
947
+ "Con: Requires good smoke test selection",
948
+ ],
949
+ },
950
+ {
951
+ title: "Continuous Monitoring",
952
+ rationale: "Run tests every 4 hours for production monitoring of critical flows.",
953
+ schedule: "0 */4 * * *",
954
+ tradeoffs: [
955
+ "Pro: Quick detection of production issues",
956
+ "Con: Higher resource usage",
957
+ "Con: May generate noise if tests are flaky",
958
+ ],
959
+ },
960
+ ],
961
+ };
962
+ },
963
+ },
964
+ {
965
+ name: "qa_recommend_cicd_setup",
966
+ description: "Get recommendations and templates for CI/CD integration. This tool provides guidance and sample YAML configurations only.",
967
+ inputSchema: schemas.RecommendCicdSetupInputSchema,
968
+ mapToUpstream: () => {
969
+ throw new Error("RECOMMENDATION_ONLY");
970
+ },
971
+ mapFromUpstream: (_response, input) => {
972
+ const data = input;
973
+ const provider = data?.repositoryProvider || "github";
974
+ const cadence = data?.cadence || "onPullRequest";
975
+ const recommendations = [];
976
+ if (provider === "github" || provider === "other") {
977
+ recommendations.push({
978
+ title: "GitHub Actions Integration",
979
+ rationale: "Native GitHub integration with minimal setup. Uses workflow dispatch for on-demand triggers.",
980
+ steps: [
981
+ "Create .github/workflows/muggle-test.yml in your repository",
982
+ "Add your Muggle AI API key as a repository secret (MUGGLE_AI_API_KEY)",
983
+ "Configure the workflow trigger based on your cadence preference",
984
+ "Optionally add status checks to require passing tests for PR merge",
985
+ ],
986
+ sampleYaml: cadence === "onPullRequest"
987
+ ? `name: Muggle AI Tests
988
+ on:
989
+ pull_request:
990
+ branches: [main, master]
991
+ workflow_dispatch:
992
+
993
+ jobs:
994
+ test:
995
+ runs-on: ubuntu-latest
996
+ steps:
997
+ - name: Trigger Muggle AI Tests
998
+ run: |
999
+ curl -X POST "https://mcp-qa-gateway.muggle-ai.com/trigger" \\
1000
+ -H "x-api-key: \${{ secrets.MUGGLE_AI_API_KEY }}" \\
1001
+ -H "Content-Type: application/json" \\
1002
+ -d '{"projectId": "\${{ vars.MUGGLE_PROJECT_ID }}"}'`
1003
+ : `name: Muggle AI Nightly Tests
1004
+ on:
1005
+ schedule:
1006
+ - cron: '0 2 * * *'
1007
+ workflow_dispatch:
1008
+
1009
+ jobs:
1010
+ test:
1011
+ runs-on: ubuntu-latest
1012
+ steps:
1013
+ - name: Trigger Muggle AI Tests
1014
+ run: |
1015
+ curl -X POST "https://mcp-qa-gateway.muggle-ai.com/trigger" \\
1016
+ -H "x-api-key: \${{ secrets.MUGGLE_AI_API_KEY }}" \\
1017
+ -H "Content-Type: application/json" \\
1018
+ -d '{"projectId": "\${{ vars.MUGGLE_PROJECT_ID }}"}'`,
1019
+ });
1020
+ }
1021
+ if (provider === "azureDevOps" || provider === "other") {
1022
+ recommendations.push({
1023
+ title: "Azure DevOps Pipelines Integration",
1024
+ rationale: "Native Azure DevOps integration with pipeline triggers and variable groups.",
1025
+ steps: [
1026
+ "Create azure-pipelines.yml in your repository root",
1027
+ "Add MUGGLE_AI_API_KEY to a variable group or pipeline variables",
1028
+ "Configure triggers based on your cadence preference",
1029
+ "Add branch policies to require passing tests",
1030
+ ],
1031
+ sampleYaml: `trigger:
1032
+ - main
1033
+ - master
1034
+
1035
+ schedules:
1036
+ - cron: '0 2 * * *'
1037
+ displayName: Nightly Tests
1038
+ branches:
1039
+ include:
1040
+ - main
1041
+
1042
+ pool:
1043
+ vmImage: 'ubuntu-latest'
1044
+
1045
+ steps:
1046
+ - script: |
1047
+ curl -X POST "https://mcp-qa-gateway.muggle-ai.com/trigger" \\
1048
+ -H "x-api-key: $(MUGGLE_AI_API_KEY)" \\
1049
+ -H "Content-Type: application/json" \\
1050
+ -d '{"projectId": "$(MUGGLE_PROJECT_ID)}"'
1051
+ displayName: 'Trigger Muggle AI Tests'`,
1052
+ });
1053
+ }
1054
+ if (provider === "gitlab" || provider === "other") {
1055
+ recommendations.push({
1056
+ title: "GitLab CI Integration",
1057
+ rationale: "Native GitLab CI integration with merge request pipelines.",
1058
+ steps: [
1059
+ "Add .gitlab-ci.yml to your repository",
1060
+ "Add MUGGLE_AI_API_KEY as a CI/CD variable (masked)",
1061
+ "Configure pipeline rules based on your cadence",
1062
+ ],
1063
+ sampleYaml: `stages:
1064
+ - test
1065
+
1066
+ muggle-ai-tests:
1067
+ stage: test
1068
+ image: curlimages/curl:latest
1069
+ rules:
1070
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
1071
+ - if: $CI_PIPELINE_SOURCE == "schedule"
1072
+ script:
1073
+ - |
1074
+ curl -X POST "https://mcp-qa-gateway.muggle-ai.com/trigger" \\
1075
+ -H "x-api-key: $MUGGLE_AI_API_KEY" \\
1076
+ -H "Content-Type: application/json" \\
1077
+ -d '{"projectId": "'$MUGGLE_PROJECT_ID'"}'`,
1078
+ });
1079
+ }
1080
+ return { recommendations: recommendations };
1081
+ },
1082
+ },
1083
+ ];
1084
+ // =============================================================================
1085
+ // Tool Registry
1086
+ // =============================================================================
1087
+ /**
1088
+ * All registered tools.
1089
+ */
1090
+ exports.allTools = [
1091
+ ...projectTools,
1092
+ ...prdFileTools,
1093
+ ...secretTools,
1094
+ ...useCaseTools,
1095
+ ...workflowTools,
1096
+ ...artifactTools,
1097
+ ...reportTools,
1098
+ ...recommendationTools,
1099
+ ];
1100
+ /**
1101
+ * Get a tool definition by name.
1102
+ * @param name - Tool name.
1103
+ * @returns Tool definition or undefined.
1104
+ */
1105
+ function getToolByName(name) {
1106
+ return exports.allTools.find((tool) => tool.name === name);
1107
+ }
1108
+ /**
1109
+ * Execute a tool with the given input.
1110
+ * @param toolName - Name of the tool to execute.
1111
+ * @param input - Tool input (will be validated).
1112
+ * @param credentials - Caller credentials.
1113
+ * @param correlationId - Request correlation ID.
1114
+ * @returns Tool output.
1115
+ */
1116
+ async function executeTool(toolName, input, credentials, correlationId) {
1117
+ const tool = getToolByName(toolName);
1118
+ if (!tool) {
1119
+ throw new Error(`Unknown tool: ${toolName}`);
1120
+ }
1121
+ // Validate input
1122
+ const validatedInput = tool.inputSchema.parse(input);
1123
+ // Check if this is a recommendation-only tool
1124
+ try {
1125
+ const upstreamCall = tool.mapToUpstream(validatedInput);
1126
+ // Execute upstream call
1127
+ const client = (0, prompt_service_client_js_1.getPromptServiceClient)();
1128
+ const response = await client.execute(upstreamCall, credentials, correlationId);
1129
+ // Map response
1130
+ const mapper = tool.mapFromUpstream || defaultResponseMapper;
1131
+ return mapper(response);
1132
+ }
1133
+ catch (error) {
1134
+ if (error instanceof Error && error.message === "RECOMMENDATION_ONLY") {
1135
+ // This is a recommendation tool, return static response
1136
+ const mapper = tool.mapFromUpstream || defaultResponseMapper;
1137
+ return mapper({ statusCode: 200, data: {}, headers: {} }, validatedInput);
1138
+ }
1139
+ throw error;
1140
+ }
1141
+ }
1142
+ //# sourceMappingURL=tool-registry.js.map