@muggleai/mcp 1.0.19 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/muggle-mcp.js +0 -0
- package/dist/{chunk-UKMTQHS2.js → chunk-DGEO3CP2.js} +3345 -2489
- package/dist/chunk-DGEO3CP2.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/login.d.ts.map +1 -1
- package/dist/cli.js +15 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/local-qa/contracts/auth-schemas.d.ts +2 -2
- package/dist/local-qa/contracts/project-schemas.d.ts +66 -26
- package/dist/local-qa/contracts/project-schemas.d.ts.map +1 -1
- package/dist/local-qa/services/auth-service.d.ts +17 -0
- package/dist/local-qa/services/auth-service.d.ts.map +1 -1
- package/dist/local-qa/services/execution-service.d.ts.map +1 -1
- package/dist/local-qa/services/run-result-storage-service.d.ts +37 -0
- package/dist/local-qa/services/run-result-storage-service.d.ts.map +1 -1
- package/dist/local-qa/tools/tool-registry.d.ts.map +1 -1
- package/dist/qa/contracts/index.d.ts +394 -74
- package/dist/qa/contracts/index.d.ts.map +1 -1
- package/dist/qa/contracts/local-run-schemas.d.ts +123 -0
- package/dist/qa/contracts/local-run-schemas.d.ts.map +1 -0
- package/dist/qa/tools/tool-registry.d.ts.map +1 -1
- package/dist/shared/auth.d.ts +15 -6
- package/dist/shared/auth.d.ts.map +1 -1
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/credentials.d.ts +19 -10
- package/dist/shared/credentials.d.ts.map +1 -1
- package/dist/shared/types.d.ts +2 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/scripts/postinstall.mjs +268 -9
- package/dist/chunk-UKMTQHS2.js.map +0 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Local execution context schema for local-run upload.
|
|
4
|
+
*/
|
|
5
|
+
export declare const LocalExecutionContextInputSchema: z.ZodObject<{
|
|
6
|
+
originalUrl: z.ZodString;
|
|
7
|
+
productionUrl: z.ZodString;
|
|
8
|
+
runByUserId: z.ZodString;
|
|
9
|
+
machineHostname: z.ZodOptional<z.ZodString>;
|
|
10
|
+
osInfo: z.ZodOptional<z.ZodString>;
|
|
11
|
+
electronAppVersion: z.ZodOptional<z.ZodString>;
|
|
12
|
+
mcpServerVersion: z.ZodOptional<z.ZodString>;
|
|
13
|
+
localExecutionCompletedAt: z.ZodNumber;
|
|
14
|
+
uploadedAt: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
productionUrl: string;
|
|
17
|
+
originalUrl: string;
|
|
18
|
+
runByUserId: string;
|
|
19
|
+
localExecutionCompletedAt: number;
|
|
20
|
+
electronAppVersion?: string | undefined;
|
|
21
|
+
osInfo?: string | undefined;
|
|
22
|
+
mcpServerVersion?: string | undefined;
|
|
23
|
+
machineHostname?: string | undefined;
|
|
24
|
+
uploadedAt?: number | undefined;
|
|
25
|
+
}, {
|
|
26
|
+
productionUrl: string;
|
|
27
|
+
originalUrl: string;
|
|
28
|
+
runByUserId: string;
|
|
29
|
+
localExecutionCompletedAt: number;
|
|
30
|
+
electronAppVersion?: string | undefined;
|
|
31
|
+
osInfo?: string | undefined;
|
|
32
|
+
mcpServerVersion?: string | undefined;
|
|
33
|
+
machineHostname?: string | undefined;
|
|
34
|
+
uploadedAt?: number | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Input schema for remote local-run upload tool.
|
|
38
|
+
*/
|
|
39
|
+
export declare const LocalRunUploadInputSchema: z.ZodObject<{
|
|
40
|
+
projectId: z.ZodString;
|
|
41
|
+
useCaseId: z.ZodString;
|
|
42
|
+
testCaseId: z.ZodString;
|
|
43
|
+
runType: z.ZodEnum<["generation", "replay"]>;
|
|
44
|
+
productionUrl: z.ZodString;
|
|
45
|
+
localExecutionContext: z.ZodObject<{
|
|
46
|
+
originalUrl: z.ZodString;
|
|
47
|
+
productionUrl: z.ZodString;
|
|
48
|
+
runByUserId: z.ZodString;
|
|
49
|
+
machineHostname: z.ZodOptional<z.ZodString>;
|
|
50
|
+
osInfo: z.ZodOptional<z.ZodString>;
|
|
51
|
+
electronAppVersion: z.ZodOptional<z.ZodString>;
|
|
52
|
+
mcpServerVersion: z.ZodOptional<z.ZodString>;
|
|
53
|
+
localExecutionCompletedAt: z.ZodNumber;
|
|
54
|
+
uploadedAt: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
}, "strip", z.ZodTypeAny, {
|
|
56
|
+
productionUrl: string;
|
|
57
|
+
originalUrl: string;
|
|
58
|
+
runByUserId: string;
|
|
59
|
+
localExecutionCompletedAt: number;
|
|
60
|
+
electronAppVersion?: string | undefined;
|
|
61
|
+
osInfo?: string | undefined;
|
|
62
|
+
mcpServerVersion?: string | undefined;
|
|
63
|
+
machineHostname?: string | undefined;
|
|
64
|
+
uploadedAt?: number | undefined;
|
|
65
|
+
}, {
|
|
66
|
+
productionUrl: string;
|
|
67
|
+
originalUrl: string;
|
|
68
|
+
runByUserId: string;
|
|
69
|
+
localExecutionCompletedAt: number;
|
|
70
|
+
electronAppVersion?: string | undefined;
|
|
71
|
+
osInfo?: string | undefined;
|
|
72
|
+
mcpServerVersion?: string | undefined;
|
|
73
|
+
machineHostname?: string | undefined;
|
|
74
|
+
uploadedAt?: number | undefined;
|
|
75
|
+
}>;
|
|
76
|
+
actionScript: z.ZodArray<z.ZodUnknown, "many">;
|
|
77
|
+
status: z.ZodEnum<["passed", "failed"]>;
|
|
78
|
+
executionTimeMs: z.ZodNumber;
|
|
79
|
+
errorMessage: z.ZodOptional<z.ZodString>;
|
|
80
|
+
}, "strip", z.ZodTypeAny, {
|
|
81
|
+
status: "failed" | "passed";
|
|
82
|
+
runType: "generation" | "replay";
|
|
83
|
+
projectId: string;
|
|
84
|
+
useCaseId: string;
|
|
85
|
+
productionUrl: string;
|
|
86
|
+
localExecutionContext: {
|
|
87
|
+
productionUrl: string;
|
|
88
|
+
originalUrl: string;
|
|
89
|
+
runByUserId: string;
|
|
90
|
+
localExecutionCompletedAt: number;
|
|
91
|
+
electronAppVersion?: string | undefined;
|
|
92
|
+
osInfo?: string | undefined;
|
|
93
|
+
mcpServerVersion?: string | undefined;
|
|
94
|
+
machineHostname?: string | undefined;
|
|
95
|
+
uploadedAt?: number | undefined;
|
|
96
|
+
};
|
|
97
|
+
executionTimeMs: number;
|
|
98
|
+
actionScript: unknown[];
|
|
99
|
+
testCaseId: string;
|
|
100
|
+
errorMessage?: string | undefined;
|
|
101
|
+
}, {
|
|
102
|
+
status: "failed" | "passed";
|
|
103
|
+
runType: "generation" | "replay";
|
|
104
|
+
projectId: string;
|
|
105
|
+
useCaseId: string;
|
|
106
|
+
productionUrl: string;
|
|
107
|
+
localExecutionContext: {
|
|
108
|
+
productionUrl: string;
|
|
109
|
+
originalUrl: string;
|
|
110
|
+
runByUserId: string;
|
|
111
|
+
localExecutionCompletedAt: number;
|
|
112
|
+
electronAppVersion?: string | undefined;
|
|
113
|
+
osInfo?: string | undefined;
|
|
114
|
+
mcpServerVersion?: string | undefined;
|
|
115
|
+
machineHostname?: string | undefined;
|
|
116
|
+
uploadedAt?: number | undefined;
|
|
117
|
+
};
|
|
118
|
+
executionTimeMs: number;
|
|
119
|
+
actionScript: unknown[];
|
|
120
|
+
testCaseId: string;
|
|
121
|
+
errorMessage?: string | undefined;
|
|
122
|
+
}>;
|
|
123
|
+
//# sourceMappingURL=local-run-schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-run-schemas.d.ts","sourceRoot":"","sources":["../../../src/qa/contracts/local-run-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU3C,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWpC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../src/qa/tools/tool-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAgB,iBAAiB,EAAqB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-registry.d.ts","sourceRoot":"","sources":["../../../src/qa/tools/tool-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAgB,iBAAiB,EAAqB,MAAM,aAAa,CAAC;AA+1CjF,+BAA+B;AAC/B,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,EAanD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAE3E;AAWD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,CAAC,CAyEzB"}
|
package/dist/shared/auth.d.ts
CHANGED
|
@@ -42,10 +42,11 @@ export declare function createApiKeyWithToken(accessToken: string, keyName: stri
|
|
|
42
42
|
}>;
|
|
43
43
|
/**
|
|
44
44
|
* Complete the full device code login flow.
|
|
45
|
-
* Starts the flow, waits for user authorization, and
|
|
45
|
+
* Starts the flow, waits for user authorization, and stores credentials.
|
|
46
|
+
* API key creation is optional - only created when keyName is provided.
|
|
46
47
|
*
|
|
47
|
-
* @param keyName - Optional name for the API key.
|
|
48
|
-
* @param keyExpiry - Expiry option for API key.
|
|
48
|
+
* @param keyName - Optional name for the API key. If provided, creates an API key.
|
|
49
|
+
* @param keyExpiry - Expiry option for API key (only used if keyName is provided).
|
|
49
50
|
* @param timeoutMs - Maximum time to wait for authorization.
|
|
50
51
|
* @returns Result of the login flow.
|
|
51
52
|
*/
|
|
@@ -56,15 +57,23 @@ export declare function performLogin(keyName?: string, keyExpiry?: "30d" | "90d"
|
|
|
56
57
|
error?: string;
|
|
57
58
|
}>;
|
|
58
59
|
/**
|
|
59
|
-
* Perform logout by clearing credentials.
|
|
60
|
+
* Perform logout by clearing all credentials (auth tokens and API keys).
|
|
60
61
|
*/
|
|
61
62
|
export declare function performLogout(): void;
|
|
62
63
|
/**
|
|
63
|
-
* Get caller credentials for API requests.
|
|
64
|
-
*
|
|
64
|
+
* Get caller credentials for API requests (sync version).
|
|
65
|
+
* Checks for API key first, then falls back to access token.
|
|
66
|
+
* Does NOT auto-refresh - use getCallerCredentialsAsync() for that.
|
|
65
67
|
* @returns Caller credentials or empty object.
|
|
66
68
|
*/
|
|
67
69
|
export declare function getCallerCredentials(): ICallerCredentials;
|
|
70
|
+
/**
|
|
71
|
+
* Get caller credentials for API requests (async version with auto-refresh).
|
|
72
|
+
* This is the preferred method - automatically refreshes expired access tokens.
|
|
73
|
+
* Priority: 1) API key (if explicitly set), 2) Access token (with auto-refresh)
|
|
74
|
+
* @returns Caller credentials or empty object.
|
|
75
|
+
*/
|
|
76
|
+
export declare function getCallerCredentialsAsync(): Promise<ICallerCredentials>;
|
|
68
77
|
/**
|
|
69
78
|
* Check if authentication is required for the given tool.
|
|
70
79
|
* Local-only tools don't require auth.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/shared/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/shared/auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAIpB;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAkE5F;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,uBAAuB,CAAC,CA2ElC;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,MAAM,GAAE,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,OAAe,GAC7C,OAAO,CAAC;IACT,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC,CAyCD;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,OAAO,CAAC,EAAE,MAAM,EAChB,SAAS,GAAE,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,OAAe,EACjD,SAAS,GAAE,MAAe,GACzB,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;IACzC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA4FD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CASpC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,kBAAkB,CAiBzD;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAiB7E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAuD1D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAEV,OAAO,EAGP,sBAAsB,EAEvB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAEV,OAAO,EAGP,sBAAsB,EAEvB,MAAM,YAAY,CAAC;AAgKpB;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AA8QD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAenC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAGlC;AAQD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAuB9C;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,KAAK,GAAG,UAAU,GAAG,SAAS,CAqB5E;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,sBAAsB,GAAG,SAAS,CAE5E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAG1D"}
|
|
@@ -30,19 +30,28 @@ export declare function deleteCredentials(): void;
|
|
|
30
30
|
export declare function isCredentialsExpired(credentials: IStoredCredentials): boolean;
|
|
31
31
|
/**
|
|
32
32
|
* Get valid credentials if available.
|
|
33
|
-
*
|
|
33
|
+
* This is primarily used for API key storage.
|
|
34
|
+
* Access token authentication is handled by AuthService.
|
|
34
35
|
* @returns Valid credentials or null.
|
|
35
36
|
*/
|
|
36
37
|
export declare function getValidCredentials(): IStoredCredentials | null;
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
-
* @returns
|
|
39
|
+
* Check if an API key is stored.
|
|
40
|
+
* @returns True if API key exists.
|
|
40
41
|
*/
|
|
41
|
-
export declare function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
export declare function hasApiKey(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Get stored API key if available.
|
|
45
|
+
* @returns API key or null.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getApiKey(): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Save API key to credentials.
|
|
50
|
+
* @param apiKey - The API key to save.
|
|
51
|
+
* @param apiKeyId - The API key ID.
|
|
52
|
+
*/
|
|
53
|
+
export declare function saveApiKey(params: {
|
|
54
|
+
apiKey: string;
|
|
55
|
+
apiKeyId: string;
|
|
56
|
+
}): void;
|
|
48
57
|
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/shared/credentials.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAKrD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAYD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,kBAAkB,GAAG,IAAI,CA0B3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAiBrE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAcxC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAO7E;AAED
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/shared/credentials.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAKrD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAYD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,kBAAkB,GAAG,IAAI,CA0B3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,kBAAkB,GAAG,IAAI,CAiBrE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAcxC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAO7E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,kBAAkB,GAAG,IAAI,CAa/D;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAGnC;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,GAAG,IAAI,CAGzC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAwB7E"}
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface IMuggleConfig {
|
|
|
24
24
|
downloadBaseUrl: string;
|
|
25
25
|
/** SHA256 checksums for each platform binary. */
|
|
26
26
|
checksums?: IMuggleConfigChecksums;
|
|
27
|
+
/** Default runtime target baked into the package at build/publish time. */
|
|
28
|
+
runtimeTargetDefault?: "production" | "dev";
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
29
31
|
* Auth0 configuration for device code flow.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4BAA4B;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,eAAe,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,SAAS,CAAC,EAAE,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/shared/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muggleai/mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"description": "Unified MCP server for Muggle AI - Cloud QA and Local Testing tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
"test:watch": "vitest"
|
|
27
27
|
},
|
|
28
28
|
"muggleConfig": {
|
|
29
|
-
"electronAppVersion": "1.0.
|
|
29
|
+
"electronAppVersion": "1.0.8",
|
|
30
30
|
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download",
|
|
31
|
+
"runtimeTargetDefault": "production",
|
|
31
32
|
"checksums": {
|
|
32
33
|
"darwin-arm64": "",
|
|
33
34
|
"darwin-x64": "",
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
import { createHash } from "crypto";
|
|
8
8
|
import { exec } from "child_process";
|
|
9
9
|
import {
|
|
10
|
+
readFileSync,
|
|
10
11
|
createReadStream,
|
|
11
12
|
createWriteStream,
|
|
12
13
|
existsSync,
|
|
13
14
|
mkdirSync,
|
|
14
15
|
readdirSync,
|
|
15
16
|
rmSync,
|
|
17
|
+
writeFileSync,
|
|
16
18
|
} from "fs";
|
|
17
19
|
import { homedir, platform } from "os";
|
|
18
20
|
import { join } from "path";
|
|
@@ -21,6 +23,86 @@ import { createRequire } from "module";
|
|
|
21
23
|
|
|
22
24
|
const require = createRequire(import.meta.url);
|
|
23
25
|
const VERSION_DIRECTORY_NAME_PATTERN = /^\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/;
|
|
26
|
+
const CURSOR_SERVER_NAME = "muggle";
|
|
27
|
+
const INSTALL_METADATA_FILE_NAME = ".install-metadata.json";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the Cursor MCP config path.
|
|
31
|
+
* @returns {string} Path to ~/.cursor/mcp.json
|
|
32
|
+
*/
|
|
33
|
+
function getCursorMcpConfigPath() {
|
|
34
|
+
return join(homedir(), ".cursor", "mcp.json");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Build the default Cursor server configuration for this package.
|
|
39
|
+
* @returns {{command: string, args: string[]}} Server configuration
|
|
40
|
+
*/
|
|
41
|
+
function buildCursorServerConfig() {
|
|
42
|
+
const localCliPath = join(process.cwd(), "bin", "muggle-mcp.js");
|
|
43
|
+
return {
|
|
44
|
+
command: "node",
|
|
45
|
+
args: [localCliPath, "serve"],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Read and parse Cursor mcp.json.
|
|
51
|
+
* @param {string} configPath - Path to mcp.json
|
|
52
|
+
* @returns {Record<string, unknown>} Parsed config object
|
|
53
|
+
*/
|
|
54
|
+
function readCursorConfig(configPath) {
|
|
55
|
+
if (!existsSync(configPath)) {
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const rawConfig = readFileSync(configPath, "utf-8");
|
|
60
|
+
const parsedConfig = JSON.parse(rawConfig);
|
|
61
|
+
|
|
62
|
+
if (typeof parsedConfig !== "object" || parsedConfig === null || Array.isArray(parsedConfig)) {
|
|
63
|
+
throw new Error(`Invalid JSON structure in ${configPath}: expected an object at root`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return parsedConfig;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Update ~/.cursor/mcp.json with the muggle server entry.
|
|
71
|
+
* Existing server configurations are preserved.
|
|
72
|
+
*/
|
|
73
|
+
function updateCursorMcpConfig() {
|
|
74
|
+
const configPath = getCursorMcpConfigPath();
|
|
75
|
+
const cursorDir = join(homedir(), ".cursor");
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const parsedConfig = readCursorConfig(configPath);
|
|
79
|
+
const currentMcpServers = parsedConfig.mcpServers;
|
|
80
|
+
let normalizedMcpServers = {};
|
|
81
|
+
|
|
82
|
+
if (currentMcpServers !== undefined) {
|
|
83
|
+
if (typeof currentMcpServers !== "object" || currentMcpServers === null || Array.isArray(currentMcpServers)) {
|
|
84
|
+
throw new Error(`Invalid mcpServers in ${configPath}: expected an object`);
|
|
85
|
+
}
|
|
86
|
+
normalizedMcpServers = currentMcpServers;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
normalizedMcpServers[CURSOR_SERVER_NAME] = buildCursorServerConfig();
|
|
90
|
+
parsedConfig.mcpServers = normalizedMcpServers;
|
|
91
|
+
|
|
92
|
+
mkdirSync(cursorDir, { recursive: true });
|
|
93
|
+
const prettyJson = `${JSON.stringify(parsedConfig, null, 2)}\n`;
|
|
94
|
+
writeFileSync(configPath, prettyJson, "utf-8");
|
|
95
|
+
console.log(`Updated Cursor MCP config: ${configPath}`);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error("\n========================================");
|
|
98
|
+
console.error("ERROR: Failed to update Cursor MCP config");
|
|
99
|
+
console.error("========================================\n");
|
|
100
|
+
console.error("Path:", configPath);
|
|
101
|
+
console.error("\nFull error details:");
|
|
102
|
+
console.error(error instanceof Error ? error.stack || error : error);
|
|
103
|
+
console.error("");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
24
106
|
|
|
25
107
|
/**
|
|
26
108
|
* Get the Muggle AI data directory.
|
|
@@ -180,6 +262,141 @@ function getBinaryName() {
|
|
|
180
262
|
}
|
|
181
263
|
}
|
|
182
264
|
|
|
265
|
+
/**
|
|
266
|
+
* Get the expected extracted executable path for the current platform.
|
|
267
|
+
* @param {string} versionDir - Version directory path
|
|
268
|
+
* @returns {string} Expected executable path
|
|
269
|
+
*/
|
|
270
|
+
function getExpectedExecutablePath(versionDir) {
|
|
271
|
+
const os = platform();
|
|
272
|
+
|
|
273
|
+
switch (os) {
|
|
274
|
+
case "darwin":
|
|
275
|
+
return join(versionDir, "MuggleAI.app", "Contents", "MacOS", "MuggleAI");
|
|
276
|
+
case "win32":
|
|
277
|
+
return join(versionDir, "MuggleAI.exe");
|
|
278
|
+
case "linux":
|
|
279
|
+
return join(versionDir, "MuggleAI");
|
|
280
|
+
default:
|
|
281
|
+
throw new Error(`Unsupported platform: ${os}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Get the metadata file path for an installed version.
|
|
287
|
+
* @param {string} versionDir - Version directory path
|
|
288
|
+
* @returns {string} Metadata file path
|
|
289
|
+
*/
|
|
290
|
+
function getInstallMetadataPath(versionDir) {
|
|
291
|
+
return join(versionDir, INSTALL_METADATA_FILE_NAME);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Read install metadata from disk.
|
|
296
|
+
* @param {string} metadataPath - Metadata file path
|
|
297
|
+
* @returns {Record<string, unknown> | null} Parsed metadata, or null if missing/invalid
|
|
298
|
+
*/
|
|
299
|
+
function readInstallMetadata(metadataPath) {
|
|
300
|
+
if (!existsSync(metadataPath)) {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
const metadataContent = readFileSync(metadataPath, "utf-8");
|
|
306
|
+
const parsedMetadata = JSON.parse(metadataContent);
|
|
307
|
+
if (typeof parsedMetadata !== "object" || parsedMetadata === null || Array.isArray(parsedMetadata)) {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
return parsedMetadata;
|
|
311
|
+
} catch {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Persist install metadata to disk.
|
|
318
|
+
* @param {object} params - Metadata fields
|
|
319
|
+
* @param {string} params.metadataPath - Metadata file path
|
|
320
|
+
* @param {string} params.version - Installed version
|
|
321
|
+
* @param {string} params.binaryName - Archive filename
|
|
322
|
+
* @param {string} params.platformKey - Platform key
|
|
323
|
+
* @param {string} params.executableChecksum - Checksum of extracted executable
|
|
324
|
+
* @param {string} params.expectedArchiveChecksum - Configured archive checksum for platform
|
|
325
|
+
*/
|
|
326
|
+
function writeInstallMetadata({
|
|
327
|
+
metadataPath,
|
|
328
|
+
version,
|
|
329
|
+
binaryName,
|
|
330
|
+
platformKey,
|
|
331
|
+
executableChecksum,
|
|
332
|
+
expectedArchiveChecksum,
|
|
333
|
+
}) {
|
|
334
|
+
const metadata = {
|
|
335
|
+
version: version,
|
|
336
|
+
binaryName: binaryName,
|
|
337
|
+
platformKey: platformKey,
|
|
338
|
+
executableChecksum: executableChecksum,
|
|
339
|
+
expectedArchiveChecksum: expectedArchiveChecksum,
|
|
340
|
+
updatedAt: new Date().toISOString(),
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`, "utf-8");
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Verify existing installed executable and metadata.
|
|
348
|
+
* @param {object} params - Verification params
|
|
349
|
+
* @param {string} params.versionDir - Installed version directory
|
|
350
|
+
* @param {string} params.executablePath - Expected executable path
|
|
351
|
+
* @param {string} params.version - Version string
|
|
352
|
+
* @param {string} params.binaryName - Archive filename
|
|
353
|
+
* @param {string} params.platformKey - Platform key
|
|
354
|
+
* @param {string} params.expectedArchiveChecksum - Configured checksum for downloaded archive
|
|
355
|
+
* @returns {Promise<{valid: boolean, reason: string}>} Verification result
|
|
356
|
+
*/
|
|
357
|
+
async function verifyExistingInstall({
|
|
358
|
+
versionDir,
|
|
359
|
+
executablePath,
|
|
360
|
+
version,
|
|
361
|
+
binaryName,
|
|
362
|
+
platformKey,
|
|
363
|
+
expectedArchiveChecksum,
|
|
364
|
+
}) {
|
|
365
|
+
const metadataPath = getInstallMetadataPath(versionDir);
|
|
366
|
+
const metadata = readInstallMetadata(metadataPath);
|
|
367
|
+
|
|
368
|
+
if (!metadata) {
|
|
369
|
+
return { valid: false, reason: "install metadata is missing or invalid" };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (metadata.version !== version) {
|
|
373
|
+
return { valid: false, reason: "installed metadata version does not match configured version" };
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (metadata.binaryName !== binaryName) {
|
|
377
|
+
return { valid: false, reason: "installed metadata binary name does not match current platform archive" };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (metadata.platformKey !== platformKey) {
|
|
381
|
+
return { valid: false, reason: "installed metadata platform key does not match current platform" };
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if ((metadata.expectedArchiveChecksum || "") !== expectedArchiveChecksum) {
|
|
385
|
+
return { valid: false, reason: "configured archive checksum changed since previous install" };
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (typeof metadata.executableChecksum !== "string" || metadata.executableChecksum === "") {
|
|
389
|
+
return { valid: false, reason: "installed metadata executable checksum is missing" };
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const currentExecutableChecksum = await calculateFileChecksum(executablePath);
|
|
393
|
+
if (currentExecutableChecksum !== metadata.executableChecksum) {
|
|
394
|
+
return { valid: false, reason: "installed executable checksum does not match recorded checksum" };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return { valid: true, reason: "installed executable checksum is valid" };
|
|
398
|
+
}
|
|
399
|
+
|
|
183
400
|
/**
|
|
184
401
|
* Download and extract the Electron app.
|
|
185
402
|
*/
|
|
@@ -192,16 +409,44 @@ async function downloadElectronApp() {
|
|
|
192
409
|
const baseUrl = config.downloadBaseUrl || "https://github.com/multiplex-ai/muggle-ai-mcp/releases/download";
|
|
193
410
|
|
|
194
411
|
const binaryName = getBinaryName();
|
|
412
|
+
const checksums = config.checksums || {};
|
|
413
|
+
const platformKey = getPlatformKey();
|
|
414
|
+
const expectedChecksum = checksums[platformKey] || "";
|
|
195
415
|
const downloadUrl = `${baseUrl}/v${version}/${binaryName}`;
|
|
196
416
|
|
|
197
417
|
const appDir = getElectronAppDir();
|
|
198
418
|
const versionDir = join(appDir, version);
|
|
419
|
+
const metadataPath = getInstallMetadataPath(versionDir);
|
|
199
420
|
|
|
200
|
-
// Check if already downloaded
|
|
421
|
+
// Check if already downloaded and extracted correctly
|
|
422
|
+
const expectedExecutablePath = getExpectedExecutablePath(versionDir);
|
|
201
423
|
if (existsSync(versionDir)) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
424
|
+
if (existsSync(expectedExecutablePath)) {
|
|
425
|
+
const existingInstallVerification = await verifyExistingInstall({
|
|
426
|
+
versionDir: versionDir,
|
|
427
|
+
executablePath: expectedExecutablePath,
|
|
428
|
+
version: version,
|
|
429
|
+
binaryName: binaryName,
|
|
430
|
+
platformKey: platformKey,
|
|
431
|
+
expectedArchiveChecksum: expectedChecksum,
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
if (existingInstallVerification.valid) {
|
|
435
|
+
cleanupNonCurrentVersions({ appDir: appDir, currentVersion: version });
|
|
436
|
+
console.log(`Electron app v${version} already installed at ${versionDir}`);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
console.log(
|
|
441
|
+
`Installed Electron app v${version} failed verification (${existingInstallVerification.reason}). Re-downloading...`,
|
|
442
|
+
);
|
|
443
|
+
rmSync(versionDir, { recursive: true, force: true });
|
|
444
|
+
} else {
|
|
445
|
+
console.log(
|
|
446
|
+
`Electron app v${version} directory exists but executable is missing. Re-downloading...`,
|
|
447
|
+
);
|
|
448
|
+
rmSync(versionDir, { recursive: true, force: true });
|
|
449
|
+
}
|
|
205
450
|
}
|
|
206
451
|
|
|
207
452
|
console.log(`Downloading Muggle Test Electron app v${version}...`);
|
|
@@ -229,11 +474,6 @@ async function downloadElectronApp() {
|
|
|
229
474
|
|
|
230
475
|
console.log("Download complete, verifying checksum...");
|
|
231
476
|
|
|
232
|
-
// Get expected checksum from config
|
|
233
|
-
const checksums = config.checksums || {};
|
|
234
|
-
const platformKey = getPlatformKey();
|
|
235
|
-
const expectedChecksum = checksums[platformKey] || "";
|
|
236
|
-
|
|
237
477
|
// Verify checksum
|
|
238
478
|
const checksumResult = await verifyFileChecksum(tempFile, expectedChecksum);
|
|
239
479
|
|
|
@@ -265,6 +505,24 @@ async function downloadElectronApp() {
|
|
|
265
505
|
// Clean up temp file
|
|
266
506
|
rmSync(tempFile, { force: true });
|
|
267
507
|
|
|
508
|
+
if (!existsSync(expectedExecutablePath)) {
|
|
509
|
+
throw new Error(
|
|
510
|
+
`Extraction completed but executable was not found.\n` +
|
|
511
|
+
`Expected path: ${expectedExecutablePath}\n` +
|
|
512
|
+
`Version directory: ${versionDir}`,
|
|
513
|
+
);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const executableChecksum = await calculateFileChecksum(expectedExecutablePath);
|
|
517
|
+
writeInstallMetadata({
|
|
518
|
+
metadataPath: metadataPath,
|
|
519
|
+
version: version,
|
|
520
|
+
binaryName: binaryName,
|
|
521
|
+
platformKey: platformKey,
|
|
522
|
+
executableChecksum: executableChecksum,
|
|
523
|
+
expectedArchiveChecksum: expectedChecksum,
|
|
524
|
+
});
|
|
525
|
+
|
|
268
526
|
cleanupNonCurrentVersions({ appDir: appDir, currentVersion: version });
|
|
269
527
|
|
|
270
528
|
console.log(`Electron app installed to ${versionDir}`);
|
|
@@ -334,4 +592,5 @@ async function extractTarGz(tarPath, destDir) {
|
|
|
334
592
|
}
|
|
335
593
|
|
|
336
594
|
// Run postinstall
|
|
595
|
+
updateCursorMcpConfig();
|
|
337
596
|
downloadElectronApp().catch(console.error);
|