@muggleai/works 4.2.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +100 -50
  2. package/dist/{chunk-CXTJOYWM.js → chunk-23NOSJFH.js} +284 -184
  3. package/dist/cli.js +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/plugin/.claude-plugin/plugin.json +4 -4
  6. package/dist/plugin/.cursor-plugin/plugin.json +3 -3
  7. package/dist/plugin/README.md +7 -5
  8. package/dist/plugin/scripts/ensure-electron-app.sh +3 -3
  9. package/dist/plugin/skills/do/e2e-acceptance.md +161 -0
  10. package/dist/plugin/skills/do/open-prs.md +78 -14
  11. package/dist/plugin/skills/muggle/SKILL.md +4 -2
  12. package/dist/plugin/skills/muggle-do/SKILL.md +6 -6
  13. package/dist/plugin/skills/muggle-test/SKILL.md +416 -0
  14. package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +77 -80
  15. package/dist/plugin/skills/muggle-test-import/SKILL.md +276 -0
  16. package/dist/plugin/skills/muggle-upgrade/SKILL.md +1 -1
  17. package/dist/plugin/skills/optimize-descriptions/SKILL.md +8 -8
  18. package/package.json +15 -12
  19. package/plugin/.claude-plugin/plugin.json +4 -4
  20. package/plugin/.cursor-plugin/plugin.json +3 -3
  21. package/plugin/README.md +7 -5
  22. package/plugin/scripts/ensure-electron-app.sh +3 -3
  23. package/plugin/skills/do/e2e-acceptance.md +161 -0
  24. package/plugin/skills/do/open-prs.md +78 -14
  25. package/plugin/skills/muggle/SKILL.md +4 -2
  26. package/plugin/skills/muggle-do/SKILL.md +6 -6
  27. package/plugin/skills/muggle-test/SKILL.md +416 -0
  28. package/plugin/skills/muggle-test-feature-local/SKILL.md +77 -80
  29. package/plugin/skills/muggle-test-import/SKILL.md +276 -0
  30. package/plugin/skills/muggle-upgrade/SKILL.md +1 -1
  31. package/plugin/skills/optimize-descriptions/SKILL.md +8 -8
  32. package/scripts/postinstall.mjs +2 -2
  33. package/dist/plugin/skills/do/qa.md +0 -89
  34. package/plugin/skills/do/qa.md +0 -89
@@ -8,9 +8,10 @@ import { fileURLToPath } from 'url';
8
8
  import winston from 'winston';
9
9
  import axios, { AxiosError } from 'axios';
10
10
  import { spawn, exec, execFile } from 'child_process';
11
+ import * as crypto from 'crypto';
12
+ import { randomUUID } from 'crypto';
11
13
  import * as fs5 from 'fs/promises';
12
14
  import { z, ZodError } from 'zod';
13
- import * as crypto from 'crypto';
14
15
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
15
16
  import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from '@modelcontextprotocol/sdk/types.js';
16
17
  import { v4 } from 'uuid';
@@ -39,6 +40,7 @@ var DEFAULT_PROMPT_SERVICE_PRODUCTION_URL = "https://promptservice.muggle-ai.com
39
40
  var DEFAULT_PROMPT_SERVICE_DEV_URL = "http://localhost:5050";
40
41
  var DEFAULT_WEB_SERVICE_URL = "http://localhost:3001";
41
42
  var ELECTRON_APP_DIR = "electron-app";
43
+ var ELECTRON_APP_RELEASE_TAG_PREFIX = "electron-app-v";
42
44
  var API_KEY_FILE = "api-key.json";
43
45
  var DEFAULT_AUTH0_PRODUCTION_DOMAIN = "login.muggle-ai.com";
44
46
  var DEFAULT_AUTH0_PRODUCTION_CLIENT_ID = "UgG5UjoyLksxMciWWKqVpwfWrJ4rFvtT";
@@ -262,7 +264,7 @@ function buildAuth0Config() {
262
264
  scope: process.env.AUTH0_SCOPE ?? DEFAULT_AUTH0_SCOPE
263
265
  };
264
266
  }
265
- function buildQaConfig() {
267
+ function buildE2eConfig() {
266
268
  const defaultPromptServiceUrl = getDefaultPromptServiceUrl();
267
269
  return {
268
270
  promptServiceBaseUrl: process.env.PROMPT_SERVICE_BASE_URL ?? defaultPromptServiceUrl,
@@ -306,7 +308,7 @@ function getConfig() {
306
308
  serverVersion: "1.0.0",
307
309
  logLevel: process.env.LOG_LEVEL ?? "info",
308
310
  auth0: buildAuth0Config(),
309
- qa: buildQaConfig(),
311
+ e2e: buildE2eConfig(),
310
312
  localQa: buildLocalQaConfig()
311
313
  };
312
314
  return configInstance;
@@ -357,6 +359,15 @@ function getBundledElectronAppVersion() {
357
359
  function getDownloadBaseUrl() {
358
360
  return getMuggleConfig().downloadBaseUrl;
359
361
  }
362
+ function buildElectronAppReleaseTag(version) {
363
+ return `${ELECTRON_APP_RELEASE_TAG_PREFIX}${version}`;
364
+ }
365
+ function buildElectronAppReleaseAssetUrl(params) {
366
+ return `${getDownloadBaseUrl()}/${buildElectronAppReleaseTag(params.version)}/${params.assetFileName}`;
367
+ }
368
+ function buildElectronAppChecksumsUrl(version) {
369
+ return `${getDownloadBaseUrl()}/${buildElectronAppReleaseTag(version)}/checksums.txt`;
370
+ }
360
371
  function getElectronAppChecksums() {
361
372
  return getMuggleConfig().checksums;
362
373
  }
@@ -403,12 +414,14 @@ function resetLogger() {
403
414
  loggerInstance = null;
404
415
  }
405
416
 
406
- // packages/mcps/src/mcp/qa/index.ts
407
- var qa_exports2 = {};
408
- __export(qa_exports2, {
417
+ // packages/mcps/src/mcp/e2e/index.ts
418
+ var e2e_exports2 = {};
419
+ __export(e2e_exports2, {
420
+ ActionScriptGetInputSchema: () => ActionScriptGetInputSchema,
409
421
  ApiKeyCreateInputSchema: () => ApiKeyCreateInputSchema,
410
422
  ApiKeyGetInputSchema: () => ApiKeyGetInputSchema,
411
423
  ApiKeyListInputSchema: () => ApiKeyListInputSchema,
424
+ ApiKeyRecordIdSchema: () => ApiKeyRecordIdSchema,
412
425
  ApiKeyRevokeInputSchema: () => ApiKeyRevokeInputSchema,
413
426
  AuthLoginInputSchema: () => AuthLoginInputSchema,
414
427
  AuthPollInputSchema: () => AuthPollInputSchema,
@@ -418,6 +431,7 @@ __export(qa_exports2, {
418
431
  LocalExecutionContextInputSchema: () => LocalExecutionContextInputSchema,
419
432
  LocalRunUploadInputSchema: () => LocalRunUploadInputSchema,
420
433
  McpErrorCode: () => McpErrorCode,
434
+ MuggleEntityIdSchema: () => MuggleEntityIdSchema,
421
435
  PaginationInputSchema: () => PaginationInputSchema,
422
436
  PrdFileDeleteInputSchema: () => PrdFileDeleteInputSchema,
423
437
  PrdFileListInputSchema: () => PrdFileListInputSchema,
@@ -439,11 +453,13 @@ __export(qa_exports2, {
439
453
  ReportFinalGenerateInputSchema: () => ReportFinalGenerateInputSchema,
440
454
  ReportPreferencesUpsertInputSchema: () => ReportPreferencesUpsertInputSchema,
441
455
  ReportStatsSummaryInputSchema: () => ReportStatsSummaryInputSchema,
456
+ RunBatchIdSchema: () => RunBatchIdSchema,
442
457
  SecretCreateInputSchema: () => SecretCreateInputSchema,
443
458
  SecretDeleteInputSchema: () => SecretDeleteInputSchema,
444
459
  SecretGetInputSchema: () => SecretGetInputSchema,
445
460
  SecretListInputSchema: () => SecretListInputSchema,
446
461
  SecretUpdateInputSchema: () => SecretUpdateInputSchema,
462
+ StripePaymentMethodIdSchema: () => StripePaymentMethodIdSchema,
447
463
  TestCaseCreateInputSchema: () => TestCaseCreateInputSchema,
448
464
  TestCaseGenerateFromPromptInputSchema: () => TestCaseGenerateFromPromptInputSchema,
449
465
  TestCaseGetInputSchema: () => TestCaseGetInputSchema,
@@ -452,6 +468,8 @@ __export(qa_exports2, {
452
468
  TestScriptGetInputSchema: () => TestScriptGetInputSchema,
453
469
  TestScriptListInputSchema: () => TestScriptListInputSchema,
454
470
  TestScriptListPaginatedInputSchema: () => TestScriptListPaginatedInputSchema,
471
+ TokenPackageIdSchema: () => TokenPackageIdSchema,
472
+ TokenUsageFilterTypeSchema: () => TokenUsageFilterTypeSchema,
455
473
  UseCaseCandidatesApproveInputSchema: () => UseCaseCandidatesApproveInputSchema,
456
474
  UseCaseCreateFromPromptsInputSchema: () => UseCaseCreateFromPromptsInputSchema,
457
475
  UseCaseDiscoveryMemoryGetInputSchema: () => UseCaseDiscoveryMemoryGetInputSchema,
@@ -1620,7 +1638,7 @@ var RunResultStorageService = class {
1620
1638
  */
1621
1639
  createRunResult(params) {
1622
1640
  const now = (/* @__PURE__ */ new Date()).toISOString();
1623
- const id = `run_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
1641
+ const id = randomUUID();
1624
1642
  const result = {
1625
1643
  id,
1626
1644
  runType: params.runType,
@@ -1703,7 +1721,7 @@ var RunResultStorageService = class {
1703
1721
  */
1704
1722
  createTestScript(params) {
1705
1723
  const now = (/* @__PURE__ */ new Date()).toISOString();
1706
- const id = `ts_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
1724
+ const id = randomUUID();
1707
1725
  const script = {
1708
1726
  id,
1709
1727
  name: params.name,
@@ -1750,7 +1768,7 @@ function getAuthenticatedUserId() {
1750
1768
  const authService = getAuthService();
1751
1769
  const authStatus = authService.getAuthStatus();
1752
1770
  if (!authStatus.authenticated) {
1753
- throw new Error("Not authenticated. Please run qa_auth_login first.");
1771
+ throw new Error("Not authenticated. Please run muggle-remote-auth-login first.");
1754
1772
  }
1755
1773
  if (!authStatus.userId) {
1756
1774
  throw new Error("User ID not found in auth. Please re-authenticate.");
@@ -1800,7 +1818,7 @@ function buildStudioAuthContent() {
1800
1818
  const authStatus = authService.getAuthStatus();
1801
1819
  const storedAuth = authService.loadStoredAuth();
1802
1820
  if (!authStatus.authenticated || !storedAuth) {
1803
- throw new Error("Not authenticated. Please run qa_auth_login first.");
1821
+ throw new Error("Not authenticated. Please run muggle-remote-auth-login first.");
1804
1822
  }
1805
1823
  if (!storedAuth.email || !storedAuth.userId) {
1806
1824
  throw new Error("Auth data incomplete. Please re-authenticate.");
@@ -1927,6 +1945,7 @@ function buildGenerationActionScript(params) {
1927
1945
  url: params.localUrl,
1928
1946
  description: params.testCase.title,
1929
1947
  precondition: params.testCase.precondition ?? "",
1948
+ instructions: params.testCase.instructions ?? "",
1930
1949
  expectedResult: params.testCase.expectedResult,
1931
1950
  steps: [],
1932
1951
  ownerId: params.ownerUserId,
@@ -1948,12 +1967,12 @@ function buildReplayActionScript(params) {
1948
1967
  sourceLabel: "testScript"
1949
1968
  });
1950
1969
  const rewrittenActionScript = rewriteActionScriptUrls({
1951
- actionScript: params.testScript.actionScript,
1970
+ actionScript: params.actionScript,
1952
1971
  originalUrl: params.testScript.url,
1953
1972
  localUrl: params.localUrl
1954
1973
  });
1955
1974
  return {
1956
- actionScriptId: params.testScript.id,
1975
+ actionScriptId: params.testScript.actionScriptId,
1957
1976
  actionScriptName: params.testScript.name,
1958
1977
  actionType: "UserDefined",
1959
1978
  actionParams: {
@@ -2231,7 +2250,7 @@ ${executionResult.stderr}`;
2231
2250
  }
2232
2251
  }
2233
2252
  async function executeReplay(params) {
2234
- const { testScript, localUrl } = params;
2253
+ const { testScript, actionScript, localUrl } = params;
2235
2254
  const timeoutMs = params.timeoutMs ?? 18e4;
2236
2255
  const userId = getAuthenticatedUserId();
2237
2256
  const authContent = buildStudioAuthContent();
@@ -2256,15 +2275,16 @@ async function executeReplay(params) {
2256
2275
  try {
2257
2276
  const runId = runResult.id;
2258
2277
  const startedAt = Date.now();
2259
- const actionScript = buildReplayActionScript({
2278
+ const builtActionScript = buildReplayActionScript({
2260
2279
  testScript,
2280
+ actionScript,
2261
2281
  localUrl,
2262
2282
  runId,
2263
2283
  ownerUserId: authContent.userId
2264
2284
  });
2265
2285
  const inputFilePath = await writeTempFile({
2266
2286
  filename: `${runId}_input.json`,
2267
- data: actionScript
2287
+ data: builtActionScript
2268
2288
  });
2269
2289
  const authFilePath = await writeTempFile({
2270
2290
  filename: `${runId}_auth.json`,
@@ -2614,7 +2634,7 @@ async function pollDeviceCode(config, deviceCode) {
2614
2634
  }
2615
2635
  async function createApiKeyWithToken(accessToken, keyName, expiry = "90d") {
2616
2636
  const config = getConfig();
2617
- const apiKeyUrl = `${config.qa.promptServiceBaseUrl}/v1/protected/api-keys`;
2637
+ const apiKeyUrl = `${config.e2e.promptServiceBaseUrl}/v1/protected/api-keys`;
2618
2638
  try {
2619
2639
  logger4.info("[Auth] Creating API key", {
2620
2640
  keyName,
@@ -2807,6 +2827,7 @@ function toolRequiresAuth(toolName) {
2807
2827
  ];
2808
2828
  return !noAuthTools.includes(toolName);
2809
2829
  }
2830
+ var MuggleEntityIdSchema = z.string().uuid();
2810
2831
  var LocalExecutionContextInputSchema = z.object({
2811
2832
  originalUrl: z.string().url().describe("Original local URL used during local execution (typically localhost)"),
2812
2833
  productionUrl: z.string().url().describe("Cloud production URL for the test case"),
@@ -2819,9 +2840,9 @@ var LocalExecutionContextInputSchema = z.object({
2819
2840
  uploadedAt: z.number().int().positive().optional().describe("Epoch milliseconds when uploaded to cloud")
2820
2841
  });
2821
2842
  var LocalRunUploadInputSchema = z.object({
2822
- projectId: z.string().min(1).describe("Project ID for the local run"),
2823
- useCaseId: z.string().min(1).describe("Use case ID for the local run"),
2824
- testCaseId: z.string().min(1).describe("Test case ID for the local run"),
2843
+ projectId: MuggleEntityIdSchema.describe("Project ID (UUID) for the local run"),
2844
+ useCaseId: MuggleEntityIdSchema.describe("Use case ID (UUID) for the local run"),
2845
+ testCaseId: MuggleEntityIdSchema.describe("Test case ID (UUID) for the local run"),
2825
2846
  runType: z.enum(["generation", "replay"]).describe("Type of local run to upload"),
2826
2847
  productionUrl: z.string().url().describe("Cloud production URL associated with the run"),
2827
2848
  localExecutionContext: LocalExecutionContextInputSchema.describe("Local execution metadata"),
@@ -2831,12 +2852,16 @@ var LocalRunUploadInputSchema = z.object({
2831
2852
  errorMessage: z.string().optional().describe("Error message when status is failed")
2832
2853
  });
2833
2854
 
2834
- // packages/mcps/src/mcp/qa/contracts/index.ts
2855
+ // packages/mcps/src/mcp/e2e/contracts/index.ts
2835
2856
  var PaginationInputSchema = z.object({
2836
2857
  page: z.number().int().positive().optional().describe("Page number (1-based)"),
2837
2858
  pageSize: z.number().int().positive().max(100).optional().describe("Number of items per page")
2838
2859
  });
2839
- var IdSchema = z.string().min(1).describe("Unique identifier");
2860
+ var IdSchema = MuggleEntityIdSchema;
2861
+ var RunBatchIdSchema = MuggleEntityIdSchema.describe("Bulk replay run batch ID (UUID)");
2862
+ var TokenPackageIdSchema = z.string().min(1).describe("Token package ID from wallet catalog");
2863
+ var StripePaymentMethodIdSchema = z.string().regex(/^pm_[a-zA-Z0-9]+$/).describe("Stripe payment method ID (pm_\u2026)");
2864
+ var ApiKeyRecordIdSchema = z.string().length(24).regex(/^[0-9a-f]+$/i).describe("API key record ID (24-character hex)");
2840
2865
  var WorkflowMemoryParamsSchema = z.object({
2841
2866
  enableSharedTestMemory: z.boolean().optional().describe("Override to enable/disable SharedTestMemory for this workflow run"),
2842
2867
  enableEverMemOS: z.boolean().optional().describe("Override to enable/disable EverMemOS for this workflow run")
@@ -2844,39 +2869,46 @@ var WorkflowMemoryParamsSchema = z.object({
2844
2869
  var WorkflowParamsSchema = z.object({
2845
2870
  memory: WorkflowMemoryParamsSchema.optional().describe("Per-run memory override settings")
2846
2871
  }).passthrough().optional().describe("Optional workflow parameters for workflow-level overrides");
2872
+ var TokenUsageFilterTypeSchema = z.enum([
2873
+ "project",
2874
+ "useCase",
2875
+ "testCase",
2876
+ "testScript",
2877
+ "actionScript"
2878
+ ]).describe("Token cost aggregation dimension");
2847
2879
  var ProjectCreateInputSchema = z.object({
2848
2880
  projectName: z.string().min(1).max(255).describe("Name of the project"),
2849
2881
  description: z.string().min(1).describe("Project description"),
2850
2882
  url: z.string().url().describe("Target website URL to test")
2851
2883
  });
2852
2884
  var ProjectGetInputSchema = z.object({
2853
- projectId: IdSchema.describe("Project ID to retrieve")
2885
+ projectId: IdSchema.describe("Project ID (UUID) to retrieve")
2854
2886
  });
2855
2887
  var ProjectDeleteInputSchema = z.object({
2856
- projectId: IdSchema.describe("Project ID to delete")
2888
+ projectId: IdSchema.describe("Project ID (UUID) to delete")
2857
2889
  });
2858
2890
  var ProjectUpdateInputSchema = z.object({
2859
- projectId: IdSchema.describe("Project ID to update"),
2891
+ projectId: IdSchema.describe("Project ID (UUID) to update"),
2860
2892
  projectName: z.string().min(1).max(255).optional().describe("New project name"),
2861
2893
  description: z.string().optional().describe("Updated description"),
2862
2894
  url: z.string().url().optional().describe("Updated target URL")
2863
2895
  });
2864
2896
  var ProjectListInputSchema = PaginationInputSchema.extend({});
2865
2897
  var PrdFileUploadInputSchema = z.object({
2866
- projectId: IdSchema.describe("Project ID to associate the PRD file with"),
2898
+ projectId: IdSchema.describe("Project ID (UUID) to associate the PRD file with"),
2867
2899
  fileName: z.string().min(1).describe("Name of the file"),
2868
2900
  contentBase64: z.string().min(1).describe("Base64-encoded file content"),
2869
2901
  contentType: z.string().optional().describe("MIME type of the file")
2870
2902
  });
2871
2903
  var PrdFileListInputSchema = z.object({
2872
- projectId: IdSchema.describe("Project ID to list PRD files for")
2904
+ projectId: IdSchema.describe("Project ID (UUID) to list PRD files for")
2873
2905
  });
2874
2906
  var PrdFileDeleteInputSchema = z.object({
2875
- projectId: IdSchema.describe("Project ID"),
2876
- prdFileId: IdSchema.describe("PRD file ID to delete")
2907
+ projectId: IdSchema.describe("Project ID (UUID)"),
2908
+ prdFileId: IdSchema.describe("PRD file ID (UUID) to delete")
2877
2909
  });
2878
2910
  var PrdFileProcessStartInputSchema = z.object({
2879
- projectId: IdSchema.describe("Project ID to process PRD files for"),
2911
+ projectId: IdSchema.describe("Project ID (UUID) to process PRD files for"),
2880
2912
  name: z.string().min(1).describe("Workflow name"),
2881
2913
  description: z.string().min(1).describe("Description of the PRD processing workflow"),
2882
2914
  prdFilePath: z.string().min(1).describe("Storage path of the uploaded PRD file (from upload response)"),
@@ -2886,75 +2918,75 @@ var PrdFileProcessStartInputSchema = z.object({
2886
2918
  fileSize: z.number().int().min(0).describe("Size of the PRD file in bytes (from upload response)")
2887
2919
  });
2888
2920
  var PrdFileProcessLatestRunInputSchema = z.object({
2889
- workflowRuntimeId: IdSchema.describe("PRD processing workflow runtime ID")
2921
+ workflowRuntimeId: IdSchema.describe("PRD processing workflow runtime ID (UUID)")
2890
2922
  });
2891
2923
  var SecretListInputSchema = z.object({
2892
- projectId: IdSchema.describe("Project ID to list secrets for")
2924
+ projectId: IdSchema.describe("Project ID (UUID) to list secrets for")
2893
2925
  });
2894
2926
  var SecretCreateInputSchema = z.object({
2895
- projectId: IdSchema.describe("Project ID to create the secret for"),
2927
+ projectId: IdSchema.describe("Project ID (UUID) to create the secret for"),
2896
2928
  name: z.string().min(1).describe("Secret name/key"),
2897
2929
  value: z.string().min(1).describe("Secret value"),
2898
2930
  description: z.string().min(1).describe("Human-readable description for selection guidance"),
2899
2931
  source: z.enum(["user", "agent"]).optional().describe("Source of the secret: 'user' for user-provided credentials, 'agent' for agent-generated credentials")
2900
2932
  });
2901
2933
  var SecretGetInputSchema = z.object({
2902
- secretId: IdSchema.describe("Secret ID to retrieve")
2934
+ secretId: IdSchema.describe("Secret ID (UUID) to retrieve")
2903
2935
  });
2904
2936
  var SecretUpdateInputSchema = z.object({
2905
- secretId: IdSchema.describe("Secret ID to update"),
2937
+ secretId: IdSchema.describe("Secret ID (UUID) to update"),
2906
2938
  name: z.string().min(1).optional().describe("Updated secret name"),
2907
2939
  value: z.string().min(1).optional().describe("Updated secret value"),
2908
2940
  description: z.string().optional().describe("Updated description")
2909
2941
  });
2910
2942
  var SecretDeleteInputSchema = z.object({
2911
- secretId: IdSchema.describe("Secret ID to delete")
2943
+ secretId: IdSchema.describe("Secret ID (UUID) to delete")
2912
2944
  });
2913
2945
  var UseCaseDiscoveryMemoryGetInputSchema = z.object({
2914
- projectId: IdSchema.describe("Project ID to get use case discovery memory for")
2946
+ projectId: IdSchema.describe("Project ID (UUID) to get use case discovery memory for")
2915
2947
  });
2916
2948
  var UseCaseCandidatesApproveInputSchema = z.object({
2917
- projectId: IdSchema.describe("Project ID"),
2949
+ projectId: IdSchema.describe("Project ID (UUID)"),
2918
2950
  approvedCandidateIds: z.array(IdSchema).min(1).describe("IDs of candidates to approve/graduate")
2919
2951
  });
2920
2952
  var UseCaseListInputSchema = z.object({
2921
- projectId: IdSchema.describe("Project ID to list use cases for")
2953
+ projectId: IdSchema.describe("Project ID (UUID) to list use cases for")
2922
2954
  }).merge(PaginationInputSchema);
2923
2955
  var UseCaseGetInputSchema = z.object({
2924
- useCaseId: IdSchema.describe("Use case ID to retrieve")
2956
+ useCaseId: IdSchema.describe("Use case ID (UUID) to retrieve")
2925
2957
  });
2926
2958
  var UseCasePromptPreviewInputSchema = z.object({
2927
- projectId: IdSchema.describe("Project ID to generate use case for"),
2959
+ projectId: IdSchema.describe("Project ID (UUID) to generate use case for"),
2928
2960
  instruction: z.string().min(1).describe("Natural language instruction describing the use case (e.g., 'As a logged-in user, I can add items to cart')")
2929
2961
  });
2930
2962
  var UseCaseCreateFromPromptsInputSchema = z.object({
2931
- projectId: IdSchema.describe("Project ID to create use cases for"),
2963
+ projectId: IdSchema.describe("Project ID (UUID) to create use cases for"),
2932
2964
  prompts: z.array(z.object({
2933
2965
  instruction: z.string().min(1).describe("Natural language instruction describing the use case")
2934
2966
  })).min(1).describe("Array of prompts to generate use cases from")
2935
2967
  });
2936
2968
  var UseCaseUpdateFromPromptInputSchema = z.object({
2937
- projectId: IdSchema.describe("Project ID"),
2938
- useCaseId: IdSchema.describe("Use case ID to update"),
2969
+ projectId: IdSchema.describe("Project ID (UUID)"),
2970
+ useCaseId: IdSchema.describe("Use case ID (UUID) to update"),
2939
2971
  instruction: z.string().min(1).describe("Natural language instruction to regenerate the use case from")
2940
2972
  });
2941
2973
  var TestCaseListInputSchema = z.object({
2942
- projectId: IdSchema.describe("Project ID to list test cases for")
2974
+ projectId: IdSchema.describe("Project ID (UUID) to list test cases for")
2943
2975
  }).merge(PaginationInputSchema);
2944
2976
  var TestCaseGetInputSchema = z.object({
2945
- testCaseId: IdSchema.describe("Test case ID to retrieve")
2977
+ testCaseId: IdSchema.describe("Test case ID (UUID) to retrieve")
2946
2978
  });
2947
2979
  var TestCaseListByUseCaseInputSchema = z.object({
2948
- useCaseId: IdSchema.describe("Use case ID to list test cases for")
2980
+ useCaseId: IdSchema.describe("Use case ID (UUID) to list test cases for")
2949
2981
  });
2950
2982
  var TestCaseGenerateFromPromptInputSchema = z.object({
2951
- projectId: IdSchema.describe("Project ID"),
2952
- useCaseId: IdSchema.describe("Use case ID to generate test cases for"),
2983
+ projectId: IdSchema.describe("Project ID (UUID)"),
2984
+ useCaseId: IdSchema.describe("Use case ID (UUID) to generate test cases for"),
2953
2985
  instruction: z.string().min(1).describe("Natural language instruction describing the test cases to generate")
2954
2986
  });
2955
2987
  var TestCaseCreateInputSchema = z.object({
2956
- projectId: IdSchema.describe("Project ID"),
2957
- useCaseId: IdSchema.describe("Use case ID to associate the test case with"),
2988
+ projectId: IdSchema.describe("Project ID (UUID)"),
2989
+ useCaseId: IdSchema.describe("Use case ID (UUID) to associate the test case with"),
2958
2990
  title: z.string().min(1).describe("Test case title"),
2959
2991
  description: z.string().min(1).describe("Detailed description of what the test case validates"),
2960
2992
  goal: z.string().min(1).describe("Concise, measurable goal of the test"),
@@ -2968,39 +3000,43 @@ var TestCaseCreateInputSchema = z.object({
2968
3000
  automated: z.boolean().optional().describe("Whether this test case is automated (default: true)")
2969
3001
  });
2970
3002
  var TestScriptListInputSchema = z.object({
2971
- projectId: IdSchema.describe("Project ID to list test scripts for")
3003
+ projectId: IdSchema.describe("Project ID (UUID) to list test scripts for"),
3004
+ testCaseId: IdSchema.optional().describe("Optional test case ID (UUID) to filter scripts by")
2972
3005
  }).merge(PaginationInputSchema);
2973
3006
  var TestScriptGetInputSchema = z.object({
2974
- testScriptId: IdSchema.describe("Test script ID to retrieve")
3007
+ testScriptId: IdSchema.describe("Test script ID (UUID) to retrieve")
2975
3008
  });
2976
3009
  var TestScriptListPaginatedInputSchema = z.object({
2977
- projectId: IdSchema.describe("Project ID to list test scripts for")
3010
+ projectId: IdSchema.describe("Project ID (UUID) to list test scripts for")
2978
3011
  }).merge(PaginationInputSchema);
3012
+ var ActionScriptGetInputSchema = z.object({
3013
+ actionScriptId: IdSchema.describe("Action script ID (UUID) to retrieve")
3014
+ });
2979
3015
  var WorkflowStartWebsiteScanInputSchema = z.object({
2980
- projectId: IdSchema.describe("Project ID to scan"),
3016
+ projectId: IdSchema.describe("Project ID (UUID) to scan"),
2981
3017
  url: z.string().url().describe("Website URL to scan"),
2982
3018
  description: z.string().min(1).describe("Description of what to scan/discover"),
2983
3019
  archiveUnapproved: z.boolean().optional().describe("Whether to archive unapproved candidates before scanning"),
2984
3020
  workflowParams: WorkflowParamsSchema
2985
3021
  });
2986
3022
  var WorkflowListRuntimesInputSchema = z.object({
2987
- projectId: IdSchema.optional().describe("Filter by project ID")
3023
+ projectId: IdSchema.optional().describe("Filter by project ID (UUID)")
2988
3024
  });
2989
3025
  var WorkflowGetLatestRunInputSchema = z.object({
2990
- workflowRuntimeId: IdSchema.describe("Workflow runtime ID")
3026
+ workflowRuntimeId: IdSchema.describe("Workflow runtime ID (UUID)")
2991
3027
  });
2992
3028
  var WorkflowStartTestCaseDetectionInputSchema = z.object({
2993
- projectId: IdSchema.describe("Project ID"),
2994
- useCaseId: IdSchema.describe("Use case ID to detect test cases for"),
3029
+ projectId: IdSchema.describe("Project ID (UUID)"),
3030
+ useCaseId: IdSchema.describe("Use case ID (UUID) to detect test cases for"),
2995
3031
  name: z.string().min(1).describe("Workflow name"),
2996
3032
  description: z.string().min(1).describe("Workflow description"),
2997
3033
  url: z.string().url().describe("Target website URL"),
2998
3034
  workflowParams: WorkflowParamsSchema
2999
3035
  });
3000
3036
  var WorkflowStartTestScriptGenerationInputSchema = z.object({
3001
- projectId: IdSchema.describe("Project ID"),
3002
- useCaseId: IdSchema.describe("Use case ID"),
3003
- testCaseId: IdSchema.describe("Test case ID"),
3037
+ projectId: IdSchema.describe("Project ID (UUID)"),
3038
+ useCaseId: IdSchema.describe("Use case ID (UUID)"),
3039
+ testCaseId: IdSchema.describe("Test case ID (UUID)"),
3004
3040
  name: z.string().min(1).describe("Workflow name"),
3005
3041
  url: z.string().url().describe("Target website URL"),
3006
3042
  goal: z.string().min(1).describe("Test goal"),
@@ -3010,57 +3046,57 @@ var WorkflowStartTestScriptGenerationInputSchema = z.object({
3010
3046
  workflowParams: WorkflowParamsSchema
3011
3047
  });
3012
3048
  var WorkflowGetLatestScriptGenByTestCaseInputSchema = z.object({
3013
- testCaseId: IdSchema.describe("Test case ID")
3049
+ testCaseId: IdSchema.describe("Test case ID (UUID)")
3014
3050
  });
3015
3051
  var WorkflowStartTestScriptReplayInputSchema = z.object({
3016
- projectId: IdSchema.describe("Project ID"),
3017
- useCaseId: IdSchema.describe("Use case ID"),
3018
- testCaseId: IdSchema.describe("Test case ID"),
3019
- testScriptId: IdSchema.describe("Test script ID to replay"),
3052
+ projectId: IdSchema.describe("Project ID (UUID)"),
3053
+ useCaseId: IdSchema.describe("Use case ID (UUID)"),
3054
+ testCaseId: IdSchema.describe("Test case ID (UUID)"),
3055
+ testScriptId: IdSchema.describe("Test script ID (UUID) to replay"),
3020
3056
  name: z.string().min(1).describe("Workflow name"),
3021
3057
  workflowParams: WorkflowParamsSchema
3022
3058
  });
3023
3059
  var WorkflowStartTestScriptReplayBulkInputSchema = z.object({
3024
- projectId: IdSchema.describe("Project ID"),
3060
+ projectId: IdSchema.describe("Project ID (UUID)"),
3025
3061
  name: z.string().min(1).describe("Workflow name"),
3026
3062
  intervalSec: z.number().int().describe("Interval in seconds (-1 for one-time / on-demand)"),
3027
- useCaseId: IdSchema.optional().describe("Optional: only replay test cases under this use case"),
3063
+ useCaseId: IdSchema.optional().describe("Optional: only replay test cases under this use case (UUID)"),
3028
3064
  namePrefix: z.string().optional().describe("Optional: prefix for generated workflow names"),
3029
3065
  limit: z.number().int().optional().describe("Optional: limit number of test cases to replay"),
3030
- testCaseIds: z.array(IdSchema).optional().describe("Optional: targeted test cases to replay"),
3066
+ testCaseIds: z.array(IdSchema).optional().describe("Optional: targeted test case UUIDs to replay"),
3031
3067
  repeatPerTestCase: z.number().int().optional().describe("Optional: repeat count per test case"),
3032
3068
  workflowParams: WorkflowParamsSchema
3033
3069
  });
3034
3070
  var WorkflowGetReplayBulkBatchSummaryInputSchema = z.object({
3035
- runBatchId: IdSchema.describe("Run batch ID")
3071
+ runBatchId: RunBatchIdSchema.describe("Run batch ID (UUID) from bulk replay workflow")
3036
3072
  });
3037
3073
  var WorkflowCancelRunInputSchema = z.object({
3038
- workflowRunId: IdSchema.describe("Workflow run ID to cancel")
3074
+ workflowRunId: IdSchema.describe("Workflow run ID (UUID) to cancel")
3039
3075
  });
3040
3076
  var WorkflowCancelRuntimeInputSchema = z.object({
3041
- workflowRuntimeId: IdSchema.describe("Workflow runtime ID to cancel")
3077
+ workflowRuntimeId: IdSchema.describe("Workflow runtime ID (UUID) to cancel")
3042
3078
  });
3043
3079
  var ProjectTestResultsSummaryInputSchema = z.object({
3044
- projectId: IdSchema.describe("Project ID to get test results summary for")
3080
+ projectId: IdSchema.describe("Project ID (UUID) to get test results summary for")
3045
3081
  });
3046
3082
  var ProjectTestScriptsSummaryInputSchema = z.object({
3047
- projectId: IdSchema.describe("Project ID to get test scripts summary for")
3083
+ projectId: IdSchema.describe("Project ID (UUID) to get test scripts summary for")
3048
3084
  });
3049
3085
  var ProjectTestRunsSummaryInputSchema = z.object({
3050
- projectId: IdSchema.describe("Project ID to get test runs summary for")
3086
+ projectId: IdSchema.describe("Project ID (UUID) to get test runs summary for")
3051
3087
  });
3052
3088
  var ReportStatsSummaryInputSchema = z.object({
3053
- projectId: IdSchema.describe("Project ID to get report stats for")
3089
+ projectId: IdSchema.describe("Project ID (UUID) to get report stats for")
3054
3090
  });
3055
3091
  var ReportCostQueryInputSchema = z.object({
3056
- projectId: IdSchema.describe("Project ID"),
3092
+ projectId: IdSchema.describe("Project ID (UUID)"),
3057
3093
  startDateKey: z.string().optional().describe("Start date key (YYYYMMDD)"),
3058
3094
  endDateKey: z.string().optional().describe("End date key (YYYYMMDD)"),
3059
- filterType: z.string().optional().describe("Filter type for cost breakdown"),
3060
- filterIds: z.array(z.unknown()).optional().describe("Filter IDs")
3095
+ filterType: TokenUsageFilterTypeSchema.optional().describe("Aggregation dimension for cost breakdown"),
3096
+ filterIds: z.array(IdSchema).optional().describe("Entity UUIDs matching filterType (project / use case / test case / test script / action script)")
3061
3097
  });
3062
3098
  var ReportPreferencesUpsertInputSchema = z.object({
3063
- projectId: IdSchema.describe("Project ID"),
3099
+ projectId: IdSchema.describe("Project ID (UUID)"),
3064
3100
  channels: z.array(z.unknown()).describe("Delivery channels to enable"),
3065
3101
  emails: z.array(z.unknown()).optional().describe("Email addresses for delivery"),
3066
3102
  phones: z.array(z.unknown()).optional().describe("Phone numbers for SMS delivery"),
@@ -3068,11 +3104,11 @@ var ReportPreferencesUpsertInputSchema = z.object({
3068
3104
  defaultExportFormat: z.string().optional().describe("Default export format (pdf, html, etc.)")
3069
3105
  });
3070
3106
  var ReportFinalGenerateInputSchema = z.object({
3071
- projectId: IdSchema.describe("Project ID to generate report for"),
3107
+ projectId: IdSchema.describe("Project ID (UUID) to generate report for"),
3072
3108
  exportFormat: z.enum(["pdf", "html", "markdown"]).describe("Export format for the report")
3073
3109
  });
3074
3110
  var WalletTopUpInputSchema = z.object({
3075
- packageId: IdSchema.describe("Token package ID to purchase"),
3111
+ packageId: TokenPackageIdSchema.describe("Token package ID to purchase"),
3076
3112
  checkoutSuccessCallback: z.string().url().describe("URL to redirect to when checkout succeeds"),
3077
3113
  checkoutCancelCallback: z.string().url().describe("URL to redirect to when checkout is canceled")
3078
3114
  });
@@ -3081,21 +3117,21 @@ var WalletPaymentMethodCreateSetupSessionInputSchema = z.object({
3081
3117
  checkoutCancelCallback: z.string().url().describe("URL to redirect to when payment method setup is canceled")
3082
3118
  });
3083
3119
  var WalletAutoTopUpSetPaymentMethodInputSchema = z.object({
3084
- paymentMethodId: IdSchema.describe("Saved Stripe payment method ID (e.g., pm_xxx)")
3120
+ paymentMethodId: StripePaymentMethodIdSchema.describe("Saved Stripe payment method ID")
3085
3121
  });
3086
3122
  var WalletPaymentMethodListInputSchema = z.object({});
3087
3123
  var WalletAutoTopUpUpdateInputSchema = z.object({
3088
3124
  enabled: z.boolean().describe("Whether auto top-up is enabled"),
3089
3125
  topUpTriggerTokenThreshold: z.number().int().min(0).describe("Token balance threshold to trigger auto top-up"),
3090
- packageId: IdSchema.describe("Token package ID to purchase when auto top-up triggers")
3126
+ packageId: TokenPackageIdSchema.describe("Token package ID to purchase when auto top-up triggers")
3091
3127
  });
3092
3128
  var RecommendScheduleInputSchema = z.object({
3093
- projectId: IdSchema.optional().describe("Project ID for context"),
3129
+ projectId: IdSchema.optional().describe("Project ID (UUID) for context"),
3094
3130
  testFrequency: z.enum(["daily", "weekly", "onDemand"]).optional().describe("Desired test frequency"),
3095
3131
  timezone: z.string().optional().describe("Timezone for scheduling")
3096
3132
  });
3097
3133
  var RecommendCicdSetupInputSchema = z.object({
3098
- projectId: IdSchema.optional().describe("Project ID for context"),
3134
+ projectId: IdSchema.optional().describe("Project ID (UUID) for context"),
3099
3135
  repositoryProvider: z.enum(["github", "azureDevOps", "gitlab", "other"]).optional().describe("Git repository provider"),
3100
3136
  cadence: z.enum(["onPullRequest", "nightly", "onDemand"]).optional().describe("CI/CD trigger cadence")
3101
3137
  });
@@ -3105,10 +3141,10 @@ var ApiKeyCreateInputSchema = z.object({
3105
3141
  });
3106
3142
  var ApiKeyListInputSchema = z.object({});
3107
3143
  var ApiKeyGetInputSchema = z.object({
3108
- apiKeyId: IdSchema.describe("ID of the API key to retrieve")
3144
+ apiKeyId: ApiKeyRecordIdSchema.describe("ID of the API key record to retrieve")
3109
3145
  });
3110
3146
  var ApiKeyRevokeInputSchema = z.object({
3111
- apiKeyId: IdSchema.describe("ID of the API key to revoke")
3147
+ apiKeyId: ApiKeyRecordIdSchema.describe("ID of the API key record to revoke")
3112
3148
  });
3113
3149
  var AuthLoginInputSchema = z.object({
3114
3150
  waitForCompletion: z.boolean().optional().describe("Whether to wait for browser login completion before returning. Default: true"),
@@ -3119,7 +3155,7 @@ var AuthPollInputSchema = z.object({
3119
3155
  });
3120
3156
  var EmptyInputSchema = z.object({});
3121
3157
 
3122
- // packages/mcps/src/mcp/qa/types.ts
3158
+ // packages/mcps/src/mcp/e2e/types.ts
3123
3159
  var McpErrorCode = /* @__PURE__ */ ((McpErrorCode2) => {
3124
3160
  McpErrorCode2["UNAUTHORIZED"] = "UNAUTHORIZED";
3125
3161
  McpErrorCode2["FORBIDDEN"] = "FORBIDDEN";
@@ -3147,7 +3183,8 @@ var GatewayError = class extends Error {
3147
3183
  var ALLOWED_UPSTREAM_PREFIXES = [
3148
3184
  "/v1/protected/muggle-test/",
3149
3185
  "/v1/protected/wallet/",
3150
- "/v1/protected/api-keys"
3186
+ "/v1/protected/api-keys",
3187
+ "/v1/protected/actionScript/"
3151
3188
  ];
3152
3189
  var PromptServiceClient = class {
3153
3190
  httpClient;
@@ -3155,8 +3192,8 @@ var PromptServiceClient = class {
3155
3192
  requestTimeoutMs;
3156
3193
  constructor() {
3157
3194
  const config = getConfig();
3158
- this.baseUrl = config.qa.promptServiceBaseUrl;
3159
- this.requestTimeoutMs = config.qa.requestTimeoutMs;
3195
+ this.baseUrl = config.e2e.promptServiceBaseUrl;
3196
+ this.requestTimeoutMs = config.e2e.requestTimeoutMs;
3160
3197
  this.httpClient = axios.create({
3161
3198
  baseURL: this.baseUrl,
3162
3199
  timeout: this.requestTimeoutMs,
@@ -3387,13 +3424,13 @@ function getPromptServiceClient() {
3387
3424
  return clientInstance;
3388
3425
  }
3389
3426
 
3390
- // packages/mcps/src/mcp/tools/qa/tool-registry.ts
3427
+ // packages/mcps/src/mcp/tools/e2e/tool-registry.ts
3391
3428
  var MUGGLE_TEST_PREFIX = "/v1/protected/muggle-test";
3392
- var getWorkflowTimeoutMs = () => getConfig().qa.workflowTimeoutMs;
3429
+ var getWorkflowTimeoutMs = () => getConfig().e2e.workflowTimeoutMs;
3393
3430
  var projectTools = [
3394
3431
  {
3395
3432
  name: "muggle-remote-project-create",
3396
- description: "Create a QA testing project to organize browser tests for a web app. A project groups test scenarios (use cases), specific test steps (test cases), and replayable browser scripts (test scripts) for one application. Create a project first before generating or running any QA tests.",
3433
+ description: "Create an E2E acceptance testing project to organize browser tests for a web app. A project groups test scenarios (use cases), specific test steps (test cases), and replayable browser scripts (test scripts) for one application. Create a project first before generating or running any E2E tests.",
3397
3434
  inputSchema: ProjectCreateInputSchema,
3398
3435
  mapToUpstream: (input) => {
3399
3436
  const data = input;
@@ -3594,7 +3631,7 @@ var testCaseTools = [
3594
3631
  },
3595
3632
  {
3596
3633
  name: "muggle-remote-test-case-generate-from-prompt",
3597
- description: "Generate QA test cases from a plain-English description of what to test \u2014 e.g., 'test the signup flow with invalid email' or 'verify the checkout handles empty cart'. Returns preview test cases that can be used to generate executable browser test scripts.",
3634
+ description: "Generate E2E acceptance test cases from a plain-English description of what to test \u2014 e.g., 'test the signup flow with invalid email' or 'verify the checkout handles empty cart'. Returns preview test cases that can be used to generate executable browser test scripts.",
3598
3635
  inputSchema: TestCaseGenerateFromPromptInputSchema,
3599
3636
  mapToUpstream: (input) => {
3600
3637
  const data = input;
@@ -3636,14 +3673,14 @@ var testCaseTools = [
3636
3673
  var testScriptTools = [
3637
3674
  {
3638
3675
  name: "muggle-remote-test-script-list",
3639
- description: "List test scripts for a project.",
3676
+ description: "List test scripts for a project, optionally filtered by test case.",
3640
3677
  inputSchema: TestScriptListInputSchema,
3641
3678
  mapToUpstream: (input) => {
3642
3679
  const data = input;
3643
3680
  return {
3644
3681
  method: "GET",
3645
3682
  path: `${MUGGLE_TEST_PREFIX}/test-scripts`,
3646
- queryParams: { projectId: data.projectId, page: data.page, pageSize: data.pageSize }
3683
+ queryParams: { projectId: data.projectId, testCaseId: data.testCaseId, page: data.page, pageSize: data.pageSize }
3647
3684
  };
3648
3685
  }
3649
3686
  },
@@ -3673,10 +3710,24 @@ var testScriptTools = [
3673
3710
  }
3674
3711
  }
3675
3712
  ];
3713
+ var actionScriptTools = [
3714
+ {
3715
+ name: "muggle-remote-action-script-get",
3716
+ description: "Get the full action script content by ID. Use actionScriptId from a test script to fetch the complete script with all steps and element labels needed for replay.",
3717
+ inputSchema: ActionScriptGetInputSchema,
3718
+ mapToUpstream: (input) => {
3719
+ const data = input;
3720
+ return {
3721
+ method: "GET",
3722
+ path: `/v1/protected/actionScript/${data.actionScriptId}`
3723
+ };
3724
+ }
3725
+ }
3726
+ ];
3676
3727
  var workflowTools = [
3677
3728
  {
3678
3729
  name: "muggle-remote-workflow-start-website-scan",
3679
- description: "Scan a website to automatically discover testable user flows and UI interactions. Crawls the site and identifies use cases like signup, login, search, checkout, form submissions, and navigation patterns. Use this when setting up QA testing for a site without predefined test cases.",
3730
+ description: "Scan a website to automatically discover testable user flows and UI interactions. Crawls the site and identifies use cases like signup, login, search, checkout, form submissions, and navigation patterns. Use this when setting up E2E acceptance testing for a site without predefined test cases.",
3680
3731
  inputSchema: WorkflowStartWebsiteScanInputSchema,
3681
3732
  mapToUpstream: (input) => {
3682
3733
  const data = input;
@@ -4499,7 +4550,7 @@ var apiKeyTools = [
4499
4550
  },
4500
4551
  {
4501
4552
  name: "muggle-remote-auth-api-key-revoke",
4502
- description: "Revoke an API key. The key will immediately stop working. Use qa_auth_api_key_list to find the key ID first.",
4553
+ description: "Revoke an API key. The key will immediately stop working. Use muggle-remote-auth-api-key-list to find the key ID first.",
4503
4554
  inputSchema: ApiKeyRevokeInputSchema,
4504
4555
  mapToUpstream: (input) => {
4505
4556
  const data = input;
@@ -4641,6 +4692,7 @@ var allQaToolDefinitions = [
4641
4692
  ...useCaseTools,
4642
4693
  ...testCaseTools,
4643
4694
  ...testScriptTools,
4695
+ ...actionScriptTools,
4644
4696
  ...workflowTools,
4645
4697
  ...reportTools,
4646
4698
  ...secretTools,
@@ -4717,15 +4769,15 @@ async function executeQaTool(toolName, input, correlationId) {
4717
4769
  }
4718
4770
  }
4719
4771
 
4720
- // packages/mcps/src/mcp/tools/qa/index.ts
4721
- var qa_exports = {};
4722
- __export(qa_exports, {
4772
+ // packages/mcps/src/mcp/tools/e2e/index.ts
4773
+ var e2e_exports = {};
4774
+ __export(e2e_exports, {
4723
4775
  allQaToolDefinitions: () => allQaToolDefinitions,
4724
4776
  executeQaTool: () => executeQaTool,
4725
4777
  getQaToolByName: () => getQaToolByName
4726
4778
  });
4727
4779
 
4728
- // packages/mcps/src/mcp/qa/index.ts
4780
+ // packages/mcps/src/mcp/e2e/index.ts
4729
4781
  function getQaTools() {
4730
4782
  return allQaToolDefinitions.map((tool) => ({
4731
4783
  name: tool.name,
@@ -4759,6 +4811,7 @@ __export(local_exports2, {
4759
4811
  LocalTestScriptStatus: () => LocalTestScriptStatus,
4760
4812
  LocalWorkflowFileEntityType: () => LocalWorkflowFileEntityType,
4761
4813
  LocalWorkflowRunStatus: () => LocalWorkflowRunStatus,
4814
+ MuggleEntityIdSchema: () => MuggleEntityIdSchema,
4762
4815
  PublishTestScriptInputSchema: () => PublishTestScriptInputSchema,
4763
4816
  RunResultGetInputSchema: () => RunResultGetInputSchema,
4764
4817
  RunResultListInputSchema: () => RunResultListInputSchema,
@@ -4803,7 +4856,7 @@ var AuthPollInputSchema2 = z.object({
4803
4856
  var EmptyInputSchema2 = z.object({});
4804
4857
  var TestCaseDetailsSchema = z.object({
4805
4858
  /** Cloud test case ID. */
4806
- id: z.string().min(1).describe("Cloud test case ID"),
4859
+ id: MuggleEntityIdSchema.describe("Cloud test case ID (UUID)"),
4807
4860
  /** Test case title. */
4808
4861
  title: z.string().min(1).describe("Test case title"),
4809
4862
  /** Test goal. */
@@ -4817,69 +4870,73 @@ var TestCaseDetailsSchema = z.object({
4817
4870
  /** Original cloud URL (for reference, replaced by localUrl). */
4818
4871
  url: z.string().url().optional().describe("Original cloud URL (replaced by localUrl during execution)"),
4819
4872
  /** Cloud project ID (required for electron workflow context). */
4820
- projectId: z.string().min(1).describe("Cloud project ID"),
4873
+ projectId: MuggleEntityIdSchema.describe("Cloud project ID (UUID)"),
4821
4874
  /** Cloud use case ID (required for electron workflow context). */
4822
- useCaseId: z.string().min(1).describe("Cloud use case ID")
4875
+ useCaseId: MuggleEntityIdSchema.describe("Cloud use case ID (UUID)")
4823
4876
  });
4824
4877
  var TestScriptDetailsSchema = z.object({
4825
4878
  /** Cloud test script ID. */
4826
- id: z.string().min(1).describe("Cloud test script ID"),
4879
+ id: MuggleEntityIdSchema.describe("Cloud test script ID (UUID)"),
4827
4880
  /** Script name. */
4828
4881
  name: z.string().min(1).describe("Test script name"),
4829
4882
  /** Cloud test case ID this script belongs to. */
4830
- testCaseId: z.string().min(1).describe("Cloud test case ID this script was generated from"),
4831
- /** Action script steps. */
4832
- actionScript: z.array(z.unknown()).describe("Action script steps to replay"),
4883
+ testCaseId: MuggleEntityIdSchema.describe("Cloud test case ID (UUID) this script was generated from"),
4884
+ /** Action script ID reference (use muggle-remote-action-script-get to fetch content). */
4885
+ actionScriptId: MuggleEntityIdSchema.describe(
4886
+ "Action script ID (UUID) \u2014 use muggle-remote-action-script-get to fetch the full script"
4887
+ ),
4833
4888
  /** Original cloud URL (for reference, replaced by localUrl). */
4834
4889
  url: z.string().url().optional().describe("Original cloud URL (replaced by localUrl during execution)"),
4835
4890
  /** Cloud project ID (required for electron workflow context). */
4836
- projectId: z.string().min(1).describe("Cloud project ID"),
4891
+ projectId: MuggleEntityIdSchema.describe("Cloud project ID (UUID)"),
4837
4892
  /** Cloud use case ID (required for electron workflow context). */
4838
- useCaseId: z.string().min(1).describe("Cloud use case ID")
4893
+ useCaseId: MuggleEntityIdSchema.describe("Cloud use case ID (UUID)")
4839
4894
  });
4840
4895
  var ExecuteTestGenerationInputSchema = z.object({
4841
- /** Test case details from qa_test_case_get. */
4842
- testCase: TestCaseDetailsSchema.describe("Test case details obtained from qa_test_case_get"),
4896
+ /** Test case details from muggle-remote-test-case-get. */
4897
+ testCase: TestCaseDetailsSchema.describe("Test case details obtained from muggle-remote-test-case-get"),
4843
4898
  /** Local URL to test against. */
4844
4899
  localUrl: z.string().url().describe("Local URL to test against (e.g., http://localhost:3000)"),
4845
4900
  /** Explicit approval to launch electron-app. */
4846
4901
  approveElectronAppLaunch: z.boolean().describe("Set to true after the user explicitly approves launching electron-app"),
4847
4902
  /** Optional timeout. */
4848
4903
  timeoutMs: z.number().int().positive().optional().describe("Timeout in milliseconds (default: 300000 = 5 min)"),
4849
- /** Show the electron-app UI during execution. */
4850
- showUi: z.boolean().optional().describe("Show the electron-app UI during execution (default: false, runs headless)")
4904
+ /** Show the electron-app UI during execution. Ask the user before approving; true = visible window, false or omit = headless. */
4905
+ showUi: z.boolean().optional().describe("Show the electron-app UI during generation. Ask the user: true to watch the window, false or omit for headless.")
4851
4906
  });
4852
4907
  var ExecuteReplayInputSchema = z.object({
4853
- /** Test script details from qa_test_script_get. */
4854
- testScript: TestScriptDetailsSchema.describe("Test script details obtained from qa_test_script_get"),
4908
+ /** Test script metadata from muggle-remote-test-script-get. */
4909
+ testScript: TestScriptDetailsSchema.describe("Test script metadata from muggle-remote-test-script-get"),
4910
+ /** Action script content from muggle-remote-action-script-get (using testScript.actionScriptId). */
4911
+ actionScript: z.array(z.unknown()).describe("Action script steps from muggle-remote-action-script-get"),
4855
4912
  /** Local URL to test against. */
4856
4913
  localUrl: z.string().url().describe("Local URL to test against (e.g., http://localhost:3000)"),
4857
4914
  /** Explicit approval to launch electron-app. */
4858
4915
  approveElectronAppLaunch: z.boolean().describe("Set to true after the user explicitly approves launching electron-app"),
4859
4916
  /** Optional timeout. */
4860
4917
  timeoutMs: z.number().int().positive().optional().describe("Timeout in milliseconds (default: 180000 = 3 min)"),
4861
- /** Show the electron-app UI during execution. */
4862
- showUi: z.boolean().optional().describe("Show the electron-app UI during execution (default: false, runs headless)")
4918
+ /** Show the electron-app UI during execution. Ask the user before approving; true = visible window, false or omit = headless. */
4919
+ showUi: z.boolean().optional().describe("Show the electron-app UI during replay. Ask the user: true to watch the window, false or omit for headless.")
4863
4920
  });
4864
4921
  var CancelExecutionInputSchema = z.object({
4865
- runId: z.string().min(1).describe("Run ID to cancel")
4922
+ runId: MuggleEntityIdSchema.describe("Run ID (UUID) to cancel")
4866
4923
  });
4867
4924
  var RunResultListInputSchema = z.object({
4868
- cloudTestCaseId: z.string().optional().describe("Optional cloud test case ID to filter by"),
4925
+ cloudTestCaseId: MuggleEntityIdSchema.optional().describe("Optional cloud test case ID (UUID) to filter by"),
4869
4926
  limit: z.number().int().positive().optional().describe("Maximum results to return (default: 20)")
4870
4927
  });
4871
4928
  var RunResultGetInputSchema = z.object({
4872
- runId: z.string().min(1).describe("Run result ID to retrieve")
4929
+ runId: MuggleEntityIdSchema.describe("Run result ID (UUID) to retrieve")
4873
4930
  });
4874
4931
  var TestScriptListInputSchema2 = z.object({
4875
- cloudTestCaseId: z.string().optional().describe("Optional cloud test case ID to filter by")
4932
+ cloudTestCaseId: MuggleEntityIdSchema.optional().describe("Optional cloud test case ID (UUID) to filter by")
4876
4933
  });
4877
4934
  var TestScriptGetInputSchema2 = z.object({
4878
- testScriptId: z.string().min(1).describe("Test script ID to retrieve")
4935
+ testScriptId: MuggleEntityIdSchema.describe("Local stored test script ID (UUID) to retrieve")
4879
4936
  });
4880
4937
  var PublishTestScriptInputSchema = z.object({
4881
- runId: z.string().min(1).describe("Local run result ID from muggle_execute_test_generation"),
4882
- cloudTestCaseId: z.string().min(1).describe("Cloud test case ID to publish the script under")
4938
+ runId: MuggleEntityIdSchema.describe("Local run result ID (UUID) from muggle_execute_test_generation"),
4939
+ cloudTestCaseId: MuggleEntityIdSchema.describe("Cloud test case ID (UUID) to publish the script under")
4883
4940
  });
4884
4941
  var ListSessionsInputSchema = z.object({
4885
4942
  limit: z.number().int().positive().optional().describe("Maximum number of sessions to return. Defaults to 10.")
@@ -5099,14 +5156,15 @@ var testScriptGetTool = {
5099
5156
  };
5100
5157
  var executeTestGenerationTool = {
5101
5158
  name: "muggle-local-execute-test-generation",
5102
- description: "Generate a QA test script by launching a real browser against your web app. The browser navigates your app, executes the test case steps (like signing up, filling forms, clicking through flows), and produces a replayable test script with screenshots. Use this to create new browser tests for any user flow. Requires a test case (from muggle-remote-test-case-get) and a localhost URL. Launches an Electron browser \u2014 requires explicit approval via approveElectronAppLaunch. Runs headless by default; set showUi: true to watch.",
5159
+ description: "Generate an end-to-end (E2E) acceptance test script by launching a real browser against your web app. The browser navigates your app, executes the test case steps (like signing up, filling forms, clicking through flows), and produces a replayable test script with screenshots. Use this to create new browser tests for any user flow. Requires a test case (from muggle-remote-test-case-get) and a localhost URL. Launches an Electron browser \u2014 requires explicit approval via approveElectronAppLaunch. Before approving, ask the user whether they want a visible GUI; pass showUi: true to watch the window or showUi: false for headless (default when omitted).",
5103
5160
  inputSchema: ExecuteTestGenerationInputSchema,
5104
5161
  execute: async (ctx) => {
5105
5162
  const logger14 = createChildLogger2(ctx.correlationId);
5106
5163
  logger14.info("Executing muggle-local-execute-test-generation");
5107
5164
  const input = ExecuteTestGenerationInputSchema.parse(ctx.input);
5108
5165
  if (!input.approveElectronAppLaunch) {
5109
- const uiMode = input.showUi ? "with visible UI" : "headless (no UI)";
5166
+ const showUiExplicit = input.showUi !== void 0;
5167
+ const uiMode = input.showUi === true ? "visible GUI (showUi: true)" : "headless (showUi: false or omitted)";
5110
5168
  return {
5111
5169
  content: [
5112
5170
  "## Electron App Launch Required",
@@ -5114,22 +5172,28 @@ var executeTestGenerationTool = {
5114
5172
  "This tool will launch the electron-app to generate a test script.",
5115
5173
  "Please set `approveElectronAppLaunch: true` to proceed.",
5116
5174
  "",
5175
+ "**Visible GUI:** Ask the user whether they want to watch the Electron window during generation.",
5176
+ "- If **yes** \u2192 when approving, pass `showUi: true`.",
5177
+ "- If **no** \u2192 when approving, pass `showUi: false` (or omit `showUi`; generation runs headless).",
5178
+ "",
5179
+ showUiExplicit ? `**Current choice:** ${uiMode}` : "**Current choice:** not set \u2014 default on approval is headless unless you pass `showUi: true`.",
5180
+ "",
5117
5181
  `**Test Case:** ${input.testCase.title}`,
5118
5182
  `**Local URL:** ${input.localUrl}`,
5119
- `**UI Mode:** ${uiMode}`,
5120
5183
  "",
5121
- "**Note:** The electron-app will open a browser window and navigate to your test URL."
5184
+ "**Note:** The electron-app will navigate your test URL and record steps."
5122
5185
  ].join("\n"),
5123
5186
  isError: false,
5124
5187
  data: { requiresApproval: true }
5125
5188
  };
5126
5189
  }
5190
+ const showUi = input.showUi === true;
5127
5191
  try {
5128
5192
  const result = await executeTestGeneration({
5129
5193
  testCase: input.testCase,
5130
5194
  localUrl: input.localUrl,
5131
5195
  timeoutMs: input.timeoutMs,
5132
- showUi: input.showUi
5196
+ showUi
5133
5197
  });
5134
5198
  const content = [
5135
5199
  "## Test Generation " + (result.status === "passed" ? "Successful" : "Failed"),
@@ -5138,6 +5202,7 @@ var executeTestGenerationTool = {
5138
5202
  `**Test Script ID:** ${result.testScriptId}`,
5139
5203
  `**Status:** ${result.status}`,
5140
5204
  `**Duration:** ${result.executionTimeMs}ms`,
5205
+ `**UI:** ${showUi ? "visible GUI" : "headless"}`,
5141
5206
  result.errorMessage ? `**Error:** ${result.errorMessage}` : ""
5142
5207
  ].filter(Boolean).join("\n");
5143
5208
  return {
@@ -5154,14 +5219,15 @@ var executeTestGenerationTool = {
5154
5219
  };
5155
5220
  var executeReplayTool = {
5156
5221
  name: "muggle-local-execute-replay",
5157
- description: "Replay an existing QA test script in a real browser to verify your app still works correctly \u2014 use this for regression testing after code changes. The browser executes each saved step and captures screenshots so you can see what happened. Requires a test script (from muggle-remote-test-script-get) and a localhost URL. Launches an Electron browser \u2014 requires explicit approval via approveElectronAppLaunch. Runs headless by default; set showUi: true to watch.",
5222
+ description: "Replay an existing E2E acceptance test script in a real browser to verify your app still works correctly \u2014 use this for regression testing after code changes. The browser executes each saved step and captures screenshots so you can see what happened. Requires: (1) test script metadata from muggle-remote-test-script-get, (2) actionScript content from muggle-remote-action-script-get using the testScript.actionScriptId, and (3) a localhost URL. Launches an Electron browser \u2014 requires explicit approval via approveElectronAppLaunch. Before approving, ask the user whether they want a visible GUI; pass showUi: true to watch the window or showUi: false for headless (default when omitted).",
5158
5223
  inputSchema: ExecuteReplayInputSchema,
5159
5224
  execute: async (ctx) => {
5160
5225
  const logger14 = createChildLogger2(ctx.correlationId);
5161
5226
  logger14.info("Executing muggle-local-execute-replay");
5162
5227
  const input = ExecuteReplayInputSchema.parse(ctx.input);
5163
5228
  if (!input.approveElectronAppLaunch) {
5164
- const uiMode = input.showUi ? "with visible UI" : "headless (no UI)";
5229
+ const showUiExplicit = input.showUi !== void 0;
5230
+ const uiMode = input.showUi === true ? "visible GUI (showUi: true)" : "headless (showUi: false or omitted)";
5165
5231
  return {
5166
5232
  content: [
5167
5233
  "## Electron App Launch Required",
@@ -5169,23 +5235,30 @@ var executeReplayTool = {
5169
5235
  "This tool will launch the electron-app to replay a test script.",
5170
5236
  "Please set `approveElectronAppLaunch: true` to proceed.",
5171
5237
  "",
5238
+ "**Visible GUI:** Ask the user whether they want to watch the Electron window during replay.",
5239
+ "- If **yes** \u2192 when approving, pass `showUi: true`.",
5240
+ "- If **no** \u2192 when approving, pass `showUi: false` (or omit `showUi`; replay runs headless).",
5241
+ "",
5242
+ showUiExplicit ? `**Current choice:** ${uiMode}` : "**Current choice:** not set \u2014 default on approval is headless unless you pass `showUi: true`.",
5243
+ "",
5172
5244
  `**Test Script:** ${input.testScript.name}`,
5173
5245
  `**Local URL:** ${input.localUrl}`,
5174
- `**Steps:** ${input.testScript.actionScript.length}`,
5175
- `**UI Mode:** ${uiMode}`,
5246
+ `**Steps:** ${input.actionScript.length}`,
5176
5247
  "",
5177
- "**Note:** The electron-app will open a browser window and execute the test steps."
5248
+ "**Note:** The electron-app will execute the test steps against your local URL."
5178
5249
  ].join("\n"),
5179
5250
  isError: false,
5180
5251
  data: { requiresApproval: true }
5181
5252
  };
5182
5253
  }
5254
+ const showUi = input.showUi === true;
5183
5255
  try {
5184
5256
  const result = await executeReplay({
5185
5257
  testScript: input.testScript,
5258
+ actionScript: input.actionScript,
5186
5259
  localUrl: input.localUrl,
5187
5260
  timeoutMs: input.timeoutMs,
5188
- showUi: input.showUi
5261
+ showUi
5189
5262
  });
5190
5263
  const content = [
5191
5264
  "## Test Replay " + (result.status === "passed" ? "Successful" : "Failed"),
@@ -5194,6 +5267,7 @@ var executeReplayTool = {
5194
5267
  `**Test Script ID:** ${result.testScriptId}`,
5195
5268
  `**Status:** ${result.status}`,
5196
5269
  `**Duration:** ${result.executionTimeMs}ms`,
5270
+ `**UI:** ${showUi ? "visible GUI" : "headless"}`,
5197
5271
  result.errorMessage ? `**Error:** ${result.errorMessage}` : ""
5198
5272
  ].filter(Boolean).join("\n");
5199
5273
  return {
@@ -5225,7 +5299,7 @@ var cancelExecutionTool = {
5225
5299
  };
5226
5300
  var publishTestScriptTool = {
5227
5301
  name: "muggle-local-publish-test-script",
5228
- description: "Publish a locally generated test script to the cloud. Uses the run ID from muggle_execute_test_generation to find the script and uploads it to the specified cloud test case.",
5302
+ description: "Publish a locally generated test script to the cloud. Uses the run ID from muggle_execute_test_generation to find the script and uploads it to the specified cloud test case. Returns a viewUrl that can be opened in the user's browser to view the published test script on the dashboard.",
5229
5303
  inputSchema: PublishTestScriptInputSchema,
5230
5304
  execute: async (ctx) => {
5231
5305
  const logger14 = createChildLogger2(ctx.correlationId);
@@ -5432,9 +5506,10 @@ function isLocalOnlyTool(toolName) {
5432
5506
  var mcp_exports = {};
5433
5507
  __export(mcp_exports, {
5434
5508
  agents: () => agents_exports,
5509
+ e2e: () => e2e_exports2,
5435
5510
  localQa: () => local_exports2,
5436
5511
  plugins: () => plugins_exports,
5437
- qa: () => qa_exports2,
5512
+ qa: () => e2e_exports2,
5438
5513
  skills: () => skills_exports,
5439
5514
  tools: () => tools_exports
5440
5515
  });
@@ -5442,8 +5517,9 @@ __export(mcp_exports, {
5442
5517
  // packages/mcps/src/mcp/tools/index.ts
5443
5518
  var tools_exports = {};
5444
5519
  __export(tools_exports, {
5520
+ e2e: () => e2e_exports,
5445
5521
  localQa: () => local_exports,
5446
- qa: () => qa_exports
5522
+ qa: () => e2e_exports
5447
5523
  });
5448
5524
 
5449
5525
  // packages/mcps/src/mcp/skills/index.ts
@@ -5458,11 +5534,15 @@ var agents_exports = {};
5458
5534
  // packages/mcps/src/index.ts
5459
5535
  var src_exports = {};
5460
5536
  __export(src_exports, {
5537
+ buildElectronAppChecksumsUrl: () => buildElectronAppChecksumsUrl,
5538
+ buildElectronAppReleaseAssetUrl: () => buildElectronAppReleaseAssetUrl,
5539
+ buildElectronAppReleaseTag: () => buildElectronAppReleaseTag,
5461
5540
  calculateFileChecksum: () => calculateFileChecksum,
5462
5541
  createApiKeyWithToken: () => createApiKeyWithToken,
5463
5542
  createChildLogger: () => createChildLogger,
5464
5543
  deleteApiKeyData: () => deleteApiKeyData,
5465
5544
  deleteCredentials: () => deleteCredentials,
5545
+ e2e: () => e2e_exports2,
5466
5546
  getApiKey: () => getApiKey,
5467
5547
  getApiKeyFilePath: () => getApiKeyFilePath,
5468
5548
  getAuthService: () => getAuthService,
@@ -5494,7 +5574,7 @@ __export(src_exports, {
5494
5574
  performLogin: () => performLogin,
5495
5575
  performLogout: () => performLogout,
5496
5576
  pollDeviceCode: () => pollDeviceCode,
5497
- qa: () => qa_exports2,
5577
+ qa: () => e2e_exports2,
5498
5578
  resetConfig: () => resetConfig,
5499
5579
  resetLogger: () => resetLogger,
5500
5580
  saveApiKey: () => saveApiKey,
@@ -5601,6 +5681,12 @@ function clearTools() {
5601
5681
  registeredTools = [];
5602
5682
  }
5603
5683
  function zodToJsonSchema(schema) {
5684
+ try {
5685
+ if (schema && typeof schema === "object" && "safeParse" in schema) {
5686
+ return z.toJSONSchema(schema);
5687
+ }
5688
+ } catch {
5689
+ }
5604
5690
  try {
5605
5691
  const zodSchema = schema;
5606
5692
  if (zodSchema._def) {
@@ -5620,10 +5706,12 @@ function convertZodDef(schema) {
5620
5706
  return { type: "object" };
5621
5707
  }
5622
5708
  const def = zodSchema._def;
5623
- const typeName = def.typeName;
5709
+ const typeName = def.typeName ?? def.type;
5624
5710
  switch (typeName) {
5625
- case "ZodObject": {
5626
- const shape = def.shape ? def.shape() : zodSchema.shape || {};
5711
+ case "ZodObject":
5712
+ case "object": {
5713
+ const shapeFromDef = typeof def.shape === "function" ? def.shape() : def.shape;
5714
+ const shape = shapeFromDef || zodSchema.shape || {};
5627
5715
  const properties = {};
5628
5716
  const required = [];
5629
5717
  for (const [key, value] of Object.entries(shape)) {
@@ -5642,7 +5730,8 @@ function convertZodDef(schema) {
5642
5730
  }
5643
5731
  return result;
5644
5732
  }
5645
- case "ZodString": {
5733
+ case "ZodString":
5734
+ case "string": {
5646
5735
  const result = { type: "string" };
5647
5736
  if (def.description) result.description = def.description;
5648
5737
  if (def.checks) {
@@ -5655,7 +5744,8 @@ function convertZodDef(schema) {
5655
5744
  }
5656
5745
  return result;
5657
5746
  }
5658
- case "ZodNumber": {
5747
+ case "ZodNumber":
5748
+ case "number": {
5659
5749
  const result = { type: "number" };
5660
5750
  if (def.description) result.description = def.description;
5661
5751
  if (def.checks) {
@@ -5667,28 +5757,33 @@ function convertZodDef(schema) {
5667
5757
  }
5668
5758
  return result;
5669
5759
  }
5670
- case "ZodBoolean": {
5760
+ case "ZodBoolean":
5761
+ case "boolean": {
5671
5762
  const result = { type: "boolean" };
5672
5763
  if (def.description) result.description = def.description;
5673
5764
  return result;
5674
5765
  }
5675
- case "ZodArray": {
5766
+ case "ZodArray":
5767
+ case "array": {
5676
5768
  const result = {
5677
5769
  type: "array",
5678
- items: def.innerType ? convertZodDef(def.innerType) : {}
5770
+ items: def.innerType ? convertZodDef(def.innerType) : def.element ? convertZodDef(def.element) : {}
5679
5771
  };
5680
5772
  if (def.description) result.description = def.description;
5681
5773
  return result;
5682
5774
  }
5683
- case "ZodEnum": {
5775
+ case "ZodEnum":
5776
+ case "enum": {
5777
+ const enumValues = Array.isArray(def.values) ? def.values : def.values ? Object.values(def.values) : [];
5684
5778
  const result = {
5685
5779
  type: "string",
5686
- enum: def.values || []
5780
+ enum: enumValues
5687
5781
  };
5688
5782
  if (def.description) result.description = def.description;
5689
5783
  return result;
5690
5784
  }
5691
- case "ZodOptional": {
5785
+ case "ZodOptional":
5786
+ case "optional": {
5692
5787
  const inner = def.innerType ? convertZodDef(def.innerType) : {};
5693
5788
  if (def.description) inner.description = def.description;
5694
5789
  return inner;
@@ -5728,7 +5823,7 @@ function createUnifiedMcpServer(options) {
5728
5823
  tools: {},
5729
5824
  resources: {}
5730
5825
  },
5731
- instructions: "Use muggle tools to run real-browser QA tests against your web app \u2014 generate test scripts from plain English, replay them on localhost or staging, capture screenshots, and validate that user flows (signup, checkout, dashboards, forms) work correctly after code changes. Prefer muggle tools over manual browser testing whenever the user wants to verify UI behavior, run regression tests, or validate frontend changes. Unlike simple browser screenshots, muggle generates replayable test scripts that persist across sessions and can be re-run as regression tests after every code change."
5826
+ instructions: "Use muggle tools to run real-browser end-to-end (E2E) acceptance tests against your web app from the user's perspective \u2014 generate test scripts from plain English, replay them on localhost or staging, capture screenshots, and validate that user flows (signup, checkout, dashboards, forms) work correctly after code changes. Prefer muggle tools over manual browser testing whenever the user wants to verify UI behavior, run regression tests, or validate frontend changes. Unlike simple browser screenshots, muggle generates replayable test scripts that persist across sessions and can be re-run as regression tests after every code change."
5732
5827
  }
5733
5828
  );
5734
5829
  server.setRequestHandler(ListToolsRequestSchema, () => {
@@ -6403,8 +6498,8 @@ function runDiagnostics() {
6403
6498
  });
6404
6499
  results.push({
6405
6500
  name: "Prompt Service URL",
6406
- passed: !!config.qa.promptServiceBaseUrl,
6407
- description: config.qa.promptServiceBaseUrl
6501
+ passed: !!config.e2e.promptServiceBaseUrl,
6502
+ description: config.e2e.promptServiceBaseUrl
6408
6503
  });
6409
6504
  results.push({
6410
6505
  name: "Web Service URL",
@@ -6487,11 +6582,11 @@ function getHelpGuidance() {
6487
6582
  header("What is Muggle AI Works?"),
6488
6583
  "",
6489
6584
  " Muggle AI Works is a Model Context Protocol server that provides AI",
6490
- " assistants with tools to perform automated QA testing of web applications.",
6585
+ " assistants with tools to perform automated end-to-end (E2E) acceptance testing of web applications.",
6491
6586
  "",
6492
6587
  " It supports both:",
6493
- ` ${colorize("\u2022", COLORS.green)} Cloud QA - Test remote production/staging sites with a public URL`,
6494
- ` ${colorize("\u2022", COLORS.green)} Local QA - Test localhost development servers`,
6588
+ ` ${colorize("\u2022", COLORS.green)} Cloud E2E - Test remote production/staging sites with a public URL`,
6589
+ ` ${colorize("\u2022", COLORS.green)} Local E2E - Test localhost development servers`,
6495
6590
  "",
6496
6591
  header("Setup Instructions"),
6497
6592
  "",
@@ -6517,8 +6612,8 @@ function getHelpGuidance() {
6517
6612
  "",
6518
6613
  ` ${colorize("Server Commands:", COLORS.bold)}`,
6519
6614
  ` ${cmd("muggle serve")} Start MCP server with all tools`,
6520
- ` ${cmd("muggle serve --qa")} Start with Cloud QA tools only`,
6521
- ` ${cmd("muggle serve --local")} Start with Local QA tools only`,
6615
+ ` ${cmd("muggle serve --e2e")} Start with cloud E2E tools only`,
6616
+ ` ${cmd("muggle serve --local")} Start with local E2E tools only`,
6522
6617
  "",
6523
6618
  ` ${colorize("Setup & Diagnostics:", COLORS.bold)}`,
6524
6619
  ` ${cmd("muggle setup")} Download/update Electron app`,
@@ -6556,14 +6651,14 @@ function getHelpGuidance() {
6556
6651
  "",
6557
6652
  header("Available MCP Tools"),
6558
6653
  "",
6559
- ` ${colorize("Cloud QA Tools:", COLORS.bold)} (prefix: qa_)`,
6560
- " qa_project_create, qa_project_list, qa_use_case_create_from_prompts,",
6561
- " qa_test_case_generate_from_prompt, qa_workflow_start_*, etc.",
6654
+ ` ${colorize("Cloud E2E tools:", COLORS.bold)} (prefix: muggle-remote-)`,
6655
+ " muggle-remote-project-create, muggle-remote-project-list, muggle-remote-use-case-create-from-prompts,",
6656
+ " muggle-remote-test-case-generate-from-prompt, muggle-remote-workflow-start-*, etc.",
6562
6657
  "",
6563
- ` ${colorize("Local QA Tools:", COLORS.bold)} (prefix: muggle_)`,
6564
- " muggle_project_create, muggle_test_case_save,",
6565
- " muggle_execute_test_generation, muggle_execute_replay,",
6566
- " muggle_cloud_pull_project, muggle_publish_project, etc.",
6658
+ ` ${colorize("Local E2E tools:", COLORS.bold)} (prefix: muggle-local-)`,
6659
+ " muggle-local-execute-test-generation, muggle-local-execute-replay,",
6660
+ " muggle-local-publish-test-script, muggle-local-run-result-get,",
6661
+ " muggle-local-check-status, etc.",
6567
6662
  "",
6568
6663
  header("Data Directory"),
6569
6664
  "",
@@ -6674,7 +6769,7 @@ var logger10 = getLogger();
6674
6769
  async function serveCommand(options) {
6675
6770
  const config = getConfig();
6676
6771
  const enableQa = options.local ? false : true;
6677
- const enableLocal = options.qa ? false : true;
6772
+ const enableLocal = options.e2e ? false : true;
6678
6773
  logger10.info("Starting Muggle MCP Server", {
6679
6774
  version: config.serverVersion,
6680
6775
  enableQa,
@@ -6685,12 +6780,12 @@ async function serveCommand(options) {
6685
6780
  if (enableQa) {
6686
6781
  const qaTools = getQaTools();
6687
6782
  registerTools(qaTools);
6688
- logger10.info("Registered QA tools", { count: qaTools.length });
6783
+ logger10.info("Registered cloud E2E acceptance tools", { count: qaTools.length });
6689
6784
  }
6690
6785
  if (enableLocal) {
6691
6786
  const localTools = getLocalQaTools();
6692
6787
  registerTools(localTools);
6693
- logger10.info("Registered Local QA tools", { count: localTools.length });
6788
+ logger10.info("Registered local E2E acceptance tools", { count: localTools.length });
6694
6789
  }
6695
6790
  const mcpServer = createUnifiedMcpServer({
6696
6791
  enableQaTools: enableQa,
@@ -6832,7 +6927,6 @@ function cleanupFailedInstall(versionDir) {
6832
6927
  }
6833
6928
  async function setupCommand(options) {
6834
6929
  const version = getElectronAppVersion();
6835
- const baseUrl = getDownloadBaseUrl();
6836
6930
  const versionDir = getElectronAppDir(version);
6837
6931
  const platformKey = getPlatformKey();
6838
6932
  if (!options.force && isElectronAppInstalled()) {
@@ -6841,7 +6935,10 @@ async function setupCommand(options) {
6841
6935
  return;
6842
6936
  }
6843
6937
  const binaryName = getBinaryName();
6844
- const downloadUrl = `${baseUrl}/v${version}/${binaryName}`;
6938
+ const downloadUrl = buildElectronAppReleaseAssetUrl({
6939
+ version,
6940
+ assetFileName: binaryName
6941
+ });
6845
6942
  console.log(`Downloading Muggle Test Electron app v${version}...`);
6846
6943
  console.log(`URL: ${downloadUrl}`);
6847
6944
  try {
@@ -6923,7 +7020,7 @@ function getBinaryName2() {
6923
7020
  }
6924
7021
  }
6925
7022
  function extractVersionFromTag(tag) {
6926
- const match = tag.match(/^electron-app-v(\d+\.\d+\.\d+)$/);
7023
+ const match = tag.match(/^(?:electron-app-)?v(\d+\.\d+\.\d+)$/);
6927
7024
  return match ? match[1] : null;
6928
7025
  }
6929
7026
  function getVersionOverridePath() {
@@ -6973,13 +7070,15 @@ async function checkForUpdates() {
6973
7070
  const version = extractVersionFromTag(release2.tag_name);
6974
7071
  if (version) {
6975
7072
  const updateAvailable = compareVersions2(version, currentVersion) > 0;
6976
- const baseUrl = getDownloadBaseUrl();
6977
7073
  const binaryName = getBinaryName2();
6978
7074
  return {
6979
7075
  currentVersion,
6980
7076
  latestVersion: version,
6981
7077
  updateAvailable,
6982
- downloadUrl: `${baseUrl}/electron-app-v${version}/${binaryName}`
7078
+ downloadUrl: buildElectronAppReleaseAssetUrl({
7079
+ version,
7080
+ assetFileName: binaryName
7081
+ })
6983
7082
  };
6984
7083
  }
6985
7084
  }
@@ -7071,8 +7170,7 @@ async function extractTarGz2(tarPath, destDir) {
7071
7170
  });
7072
7171
  }
7073
7172
  async function fetchChecksumFromRelease(version) {
7074
- const baseUrl = getDownloadBaseUrl();
7075
- const checksumUrl = `${baseUrl}/electron-app-v${version}/checksums.txt`;
7173
+ const checksumUrl = buildElectronAppChecksumsUrl(version);
7076
7174
  try {
7077
7175
  const response = await fetch(checksumUrl);
7078
7176
  if (!response.ok) {
@@ -7189,9 +7287,11 @@ The archive may be corrupted or in an unexpected format.`
7189
7287
  async function upgradeCommand(options) {
7190
7288
  try {
7191
7289
  if (options.version) {
7192
- const baseUrl = getDownloadBaseUrl();
7193
7290
  const binaryName = getBinaryName2();
7194
- const downloadUrl = `${baseUrl}/electron-app-v${options.version}/${binaryName}`;
7291
+ const downloadUrl = buildElectronAppReleaseAssetUrl({
7292
+ version: options.version,
7293
+ assetFileName: binaryName
7294
+ });
7195
7295
  await downloadAndInstall(options.version, downloadUrl);
7196
7296
  const cleanupResult2 = cleanupOldVersions({ all: false });
7197
7297
  if (cleanupResult2.removed.length > 0) {
@@ -7252,8 +7352,8 @@ var packageVersion = JSON.parse(
7252
7352
  var logger13 = getLogger();
7253
7353
  function createProgram() {
7254
7354
  const program = new Command();
7255
- program.name("muggle").description("Unified MCP server for Muggle AI - Cloud QA and Local Testing").version(packageVersion);
7256
- program.command("serve").description("Start the MCP server").option("--qa", "Only enable Cloud QA tools").option("--local", "Only enable Local QA tools").option("--stdio", "Use stdio transport (default)").action(serveCommand);
7355
+ program.name("muggle").description("Unified MCP server for Muggle AI \u2014 cloud E2E and local E2E testing").version(packageVersion);
7356
+ program.command("serve").description("Start the MCP server").option("--e2e", "Only enable cloud E2E tools (remote URLs; muggle-remote-* prefix)").option("--local", "Only enable local E2E tools (localhost; muggle-local-* prefix)").option("--stdio", "Use stdio transport (default)").action(serveCommand);
7257
7357
  program.command("setup").description("Download/update the Electron app for local testing").option("--force", "Force re-download even if already installed").action(setupCommand);
7258
7358
  program.command("upgrade").description("Check for and install the latest electron-app version").option("--force", "Force re-download even if already on latest").option("--check", "Check for updates only, don't download").option("--version <version>", "Download a specific version (e.g., 1.0.2)").action(upgradeCommand);
7259
7359
  program.command("versions").description("List installed electron-app versions").action(versionsCommand);
@@ -7315,4 +7415,4 @@ __export(src_exports2, {
7315
7415
  function registerCoreCommands(commandRegistrationContext) {
7316
7416
  }
7317
7417
 
7318
- export { createChildLogger, createUnifiedMcpServer, getConfig, getLocalQaTools, getLogger, getQaTools, local_exports2 as local_exports, mcp_exports, qa_exports2 as qa_exports, runCli, server_exports, src_exports, src_exports2 };
7418
+ export { createChildLogger, createUnifiedMcpServer, e2e_exports2 as e2e_exports, getConfig, getLocalQaTools, getLogger, getQaTools, local_exports2 as local_exports, mcp_exports, runCli, server_exports, src_exports, src_exports2 };