@muuktest/maintenance-mcp 0.1.7

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MuukTest
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # MuukTest Maintenance MCP
2
+ MCP server for analyzing and repairing E2E test failures (Playwright) with AI-powered suggestions.
3
+
4
+ ## Requirements
5
+
6
+
7
+ Before you begin, make sure you have:
8
+
9
+ - **Node.js 24+** — Check with `node --version`
10
+
11
+ - **npm** — Comes with Node.js, check with `npm --version`
12
+
13
+ - **MuukTest Key** — Available in MuukTest Portal. If you don't have one yet, request access at [MuukTest](https://muuktest.com).
14
+
15
+ ---
16
+
17
+ ## Setup
18
+
19
+
20
+ **Open:** Command Palette → "MCP: Open User Configuration"
21
+ ### VSCode:
22
+ ```
23
+ {
24
+ "inputs": [
25
+ {
26
+ "id": "muuk_key",
27
+ "type": "promptString",
28
+ "description": "MuukTest Key (from your MuukTest Portal)",
29
+ "password": true
30
+ }
31
+ ],
32
+ "servers": {
33
+ "muuk-maintenance": {
34
+ "command": "npx",
35
+ "args": ["-y", "@muuktest/maintenance-mcp"],
36
+ "env": {
37
+ "MUUK_KEY": "${input:muuk_key}"
38
+ }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ ### Claude Desktop
45
+ **File**: `~/.config/claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
46
+ ```
47
+ {
48
+ "mcpServers": {
49
+ "muuk-maintenance": {
50
+ "command": "npx",
51
+ "args": ["-y", "@muuktest/maintenance-mcp"],
52
+ "env": {
53
+ "MUUK_KEY": "their-muuktest-key-here"
54
+ }
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+
61
+ ### Cursor
62
+ **Settings** → Search "MCP"
63
+ ```json
64
+ {
65
+ "muuk-maintenance": {
66
+ "command": "npx",
67
+ "args": ["-y", "@muuktest/maintenance-mcp"],
68
+ "env": {
69
+ "MUUK_KEY": "their-key-here"
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ---
76
+ ## Supported Tools
77
+
78
+ - `fix_selectors`: Fixes selector issues in E2E tests. Returns suggested fixes by generating an updated selector.
79
+
80
+ - `fix_ui_flow`: Fixes UI/flow issues in E2E tests. Returns suggested fixes by removing unnecessary steps or adding missing ones. (NOT YET IMPLEMENTED)
81
+
82
+ - `fix_data_dependance`: Fixes data dependence issues in E2E tests. Returns suggested fixes by updating test data used in a step. (NOT YET IMPLEMENTED)
83
+
84
+ ---
85
+
86
+ ## Support
87
+
88
+ - Contact [MuukTest](https://muuktest.com)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MuukTest Maintenance MCP Server
4
+ * Analyzes E2E test failures and provides repair suggestions.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG"}
package/build/index.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MuukTest Maintenance MCP Server
4
+ * Analyzes E2E test failures and provides repair suggestions.
5
+ */
6
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
9
+ import { analyzeImpl, } from "./server.js";
10
+ const API_URL = process.env.MUUK_API_URL ||
11
+ "https://bm5s428g6e.execute-api.us-east-2.amazonaws.com/staging";
12
+ const MUUK_KEY = process.env.MUUK_KEY || "";
13
+ const REQUEST_TIMEOUT_SECS = parseInt(process.env.MUUK_TIMEOUT_SECS || "300", 10);
14
+ const SIGNED_URL_ENDPOINT = process.env.MUUK_SIGNED_URL_ENDPOINT ||
15
+ "https://bm5s428g6e.execute-api.us-east-2.amazonaws.com/v1/mcp/getSignedUrl";
16
+ // Create server instance
17
+ const server = new Server({
18
+ name: "muuk-maintenance",
19
+ version: "0.1.7",
20
+ }, {
21
+ capabilities: {
22
+ tools: {},
23
+ },
24
+ });
25
+ // Define input schema for tools
26
+ const INPUT_SCHEMA = {
27
+ type: "object",
28
+ properties: {
29
+ workspace_path: {
30
+ type: "string",
31
+ description: "REQUIRED: The absolute path to the current workspace/project root. You must always provide this - get it from the current working directory.",
32
+ },
33
+ test_files_path: {
34
+ type: "array",
35
+ items: { type: "string" },
36
+ description: "Array of test file paths, relative to workspace (e.g., [./tests/a.spec.ts, ./foo/bar.json]). Allowed: .ts/.tsx/.js/.jsx, .spec.* variants, .json, .mjs/.cjs/.mts/.cts, .feature, .yaml/.yml, .txt/.csv, .xml, .env, .graphql/.gql",
37
+ },
38
+ failure_data_path: {
39
+ type: "string",
40
+ description: "Path to failure data directory, relative to workspace (e.g., ./failure-data/)",
41
+ },
42
+ },
43
+ required: ["workspace_path", "test_files_path", "failure_data_path"],
44
+ };
45
+ // List available tools
46
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
47
+ return {
48
+ tools: [
49
+ {
50
+ name: "fix_selectors",
51
+ description: "Fixes selector issues in E2E tests. Returns suggested fixes by generating an updated selector.",
52
+ inputSchema: INPUT_SCHEMA,
53
+ }
54
+ ],
55
+ };
56
+ });
57
+ // Handle tool calls
58
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
59
+ const { name, arguments: args } = request.params;
60
+ if (!["fix_selectors"].includes(name)) {
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: JSON.stringify({ error: `Unknown tool: ${name}` }),
66
+ },
67
+ ],
68
+ };
69
+ }
70
+ if (!args) {
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text",
75
+ text: JSON.stringify({ error: "Missing arguments" }, null, 2),
76
+ },
77
+ ],
78
+ };
79
+ }
80
+ const scenario = name;
81
+ const required = ["workspace_path", "test_files_path", "failure_data_path"];
82
+ const missing = required.filter((k) => !args[k]);
83
+ if (missing.length > 0) {
84
+ return {
85
+ content: [
86
+ {
87
+ type: "text",
88
+ text: JSON.stringify({
89
+ error: "Missing required arguments",
90
+ missing,
91
+ hint: "workspace_path must be the absolute path to your project root",
92
+ }, null, 2),
93
+ },
94
+ ],
95
+ };
96
+ }
97
+ try {
98
+ const result = await analyzeImpl(scenario, args.test_files_path, args.failure_data_path, args.workspace_path, {
99
+ apiUrl: API_URL,
100
+ muukKey: MUUK_KEY,
101
+ signedUrlEndpoint: SIGNED_URL_ENDPOINT,
102
+ timeoutSecs: REQUEST_TIMEOUT_SECS,
103
+ });
104
+ return {
105
+ content: [
106
+ {
107
+ type: "text",
108
+ text: result,
109
+ },
110
+ ],
111
+ };
112
+ }
113
+ catch (error) {
114
+ return {
115
+ content: [
116
+ {
117
+ type: "text",
118
+ text: JSON.stringify({
119
+ error: "Execution failed",
120
+ details: error instanceof Error ? error.message : String(error),
121
+ }, null, 2),
122
+ },
123
+ ],
124
+ };
125
+ }
126
+ });
127
+ // Start the server
128
+ async function main() {
129
+ const transport = new StdioServerTransport();
130
+ await server.connect(transport);
131
+ }
132
+ main().catch((error) => {
133
+ console.error("Server error:", error);
134
+ process.exit(1);
135
+ });
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Core server logic for analyzing test failures
3
+ */
4
+ interface AnalyzeConfig {
5
+ apiUrl: string;
6
+ muukKey: string;
7
+ signedUrlEndpoint: string;
8
+ timeoutSecs: number;
9
+ }
10
+ /**
11
+ * Validate and normalize input paths
12
+ */
13
+ export declare function validateInputs(testFilesPaths: string[], failureDataPath: string, workspace?: string): Promise<{
14
+ testPaths: string[];
15
+ failurePath: string;
16
+ }>;
17
+ /**
18
+ * Authenticate using Muuk Key
19
+ */
20
+ export declare function authenticateMuukKey(muukKey: string): Promise<boolean>;
21
+ /**
22
+ * Execute test failure analysis
23
+ */
24
+ export declare function analyzeImpl(scenario: string, testFilesPath: string[], failureDataPath: string, workspacePath: string, config: AnalyzeConfig): Promise<string>;
25
+ export {};
26
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AA8CD;;GAEG;AACH,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,EAAE,EACxB,eAAe,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CA8CvD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAc3E;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EAAE,EACvB,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC,CAgJjB"}
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Core server logic for analyzing test failures
3
+ */
4
+ import * as path from "path";
5
+ import * as fs from "fs/promises";
6
+ import axios from "axios";
7
+ import { createTempZip, requestSignedUrl, uploadZipToS3, buildS3Path } from "./utils.js";
8
+ const MUUK_AUTH_URL = "https://portal.muuktest.com:8081/generate_token_executer?=";
9
+ /**
10
+ * Normalize path to absolute, using workspace as base for relative paths
11
+ */
12
+ function normPath(p, workspace) {
13
+ const expanded = p.replace(/^~/, process.env.HOME || "");
14
+ if (path.isAbsolute(expanded)) {
15
+ return path.resolve(expanded);
16
+ }
17
+ const base = workspace || process.cwd();
18
+ return path.resolve(base, expanded);
19
+ }
20
+ /**
21
+ * Check if file is an allowed test file type
22
+ */
23
+ function isAllowedTestFile(filePath) {
24
+ const name = path.basename(filePath).toLowerCase();
25
+ const allowedExtensions = [
26
+ ".spec.ts",
27
+ ".spec.tsx",
28
+ ".spec.js",
29
+ ".spec.jsx",
30
+ ".ts",
31
+ ".tsx",
32
+ ".js",
33
+ ".jsx",
34
+ ".json",
35
+ ".mjs",
36
+ ".cjs",
37
+ ".mts",
38
+ ".cts",
39
+ ".feature",
40
+ ".yaml",
41
+ ".yml",
42
+ ".txt",
43
+ ".csv",
44
+ ".xml",
45
+ ".env",
46
+ ".graphql",
47
+ ".gql",
48
+ ];
49
+ return allowedExtensions.some((ext) => name.endsWith(ext));
50
+ }
51
+ /**
52
+ * Validate and normalize input paths
53
+ */
54
+ export async function validateInputs(testFilesPaths, failureDataPath, workspace) {
55
+ if (!Array.isArray(testFilesPaths)) {
56
+ throw new Error("test_files_path must be an array of file paths");
57
+ }
58
+ const testPaths = testFilesPaths.map((p) => normPath(p, workspace));
59
+ const failurePath = normPath(failureDataPath, workspace);
60
+ // Check if files exist
61
+ const missing = [];
62
+ for (const p of testPaths) {
63
+ try {
64
+ const stat = await fs.stat(p);
65
+ if (!stat.isFile()) {
66
+ throw new Error(`test-files path must be a file: ${p}`);
67
+ }
68
+ if (!isAllowedTestFile(p)) {
69
+ throw new Error(`Unsupported test file type: ${p}`);
70
+ }
71
+ }
72
+ catch (error) {
73
+ if (error.code === "ENOENT") {
74
+ missing.push(p);
75
+ }
76
+ else {
77
+ throw error;
78
+ }
79
+ }
80
+ }
81
+ try {
82
+ const stat = await fs.stat(failurePath);
83
+ if (!stat.isDirectory()) {
84
+ throw new Error(`failure-data path must be a directory: ${failurePath}`);
85
+ }
86
+ }
87
+ catch (error) {
88
+ if (error.code === "ENOENT") {
89
+ missing.push(failurePath);
90
+ }
91
+ else {
92
+ throw error;
93
+ }
94
+ }
95
+ if (missing.length > 0) {
96
+ throw new Error(`Missing file(s): ${missing.join(", ")}`);
97
+ }
98
+ return { testPaths, failurePath };
99
+ }
100
+ /**
101
+ * Authenticate using Muuk Key
102
+ */
103
+ export async function authenticateMuukKey(muukKey) {
104
+ try {
105
+ const response = await axios.post(MUUK_AUTH_URL, { key: muukKey }, {
106
+ headers: { "Content-Type": "application/json" },
107
+ timeout: 30000,
108
+ });
109
+ return response.status !== 500;
110
+ }
111
+ catch (error) {
112
+ return false;
113
+ }
114
+ }
115
+ /**
116
+ * Execute test failure analysis
117
+ */
118
+ export async function analyzeImpl(scenario, testFilesPath, failureDataPath, workspacePath, config) {
119
+ if (!config.muukKey) {
120
+ return JSON.stringify({
121
+ error: "Muuk Key not configured",
122
+ hint: "Set MUUK_KEY environment variable",
123
+ }, null, 2);
124
+ }
125
+ // Authenticate
126
+ const isAuthenticated = await authenticateMuukKey(config.muukKey);
127
+ if (!isAuthenticated) {
128
+ return JSON.stringify({
129
+ error: "Invalid Muuk Key or authentication failed",
130
+ hint: "Verify your MUUK_KEY environment variable",
131
+ }, null, 2);
132
+ }
133
+ // Validate inputs
134
+ let testPaths;
135
+ let failurePath;
136
+ try {
137
+ const validated = await validateInputs(testFilesPath, failureDataPath, workspacePath);
138
+ testPaths = validated.testPaths;
139
+ failurePath = validated.failurePath;
140
+ }
141
+ catch (error) {
142
+ return JSON.stringify({
143
+ error: "Invalid input paths",
144
+ details: error instanceof Error ? error.message : String(error),
145
+ }, null, 2);
146
+ }
147
+ // Upload to S3
148
+ let zipPath = null;
149
+ let sourcePath;
150
+ let signedUrl;
151
+ try {
152
+ const signedUrlData = await requestSignedUrl(config.muukKey, config.signedUrlEndpoint);
153
+ sourcePath = signedUrlData.sourcePath;
154
+ signedUrl = signedUrlData.signedUrl;
155
+ zipPath = await createTempZip(testPaths, failurePath);
156
+ await uploadZipToS3(zipPath, signedUrl);
157
+ }
158
+ catch (error) {
159
+ if (axios.isAxiosError(error)) {
160
+ return JSON.stringify({
161
+ error: "S3 upload failed",
162
+ details: error.message,
163
+ }, null, 2);
164
+ }
165
+ return JSON.stringify({
166
+ error: "Upload preparation failed",
167
+ details: error instanceof Error ? error.message : String(error),
168
+ }, null, 2);
169
+ }
170
+ finally {
171
+ if (zipPath) {
172
+ try {
173
+ await fs.unlink(zipPath);
174
+ }
175
+ catch {
176
+ // Ignore cleanup errors
177
+ }
178
+ }
179
+ }
180
+ // Call API
181
+ const payload = {
182
+ config: {
183
+ muuk_key: config.muukKey,
184
+ },
185
+ s3_path: buildS3Path(sourcePath, signedUrl),
186
+ scenario: scenario,
187
+ };
188
+ try {
189
+ const response = await axios.post(config.apiUrl, payload, {
190
+ headers: { "Content-Type": "application/json" },
191
+ timeout: config.timeoutSecs * 1000,
192
+ });
193
+ if (response.status === 200) {
194
+ const data = response.data;
195
+ const report = data.report || data;
196
+ return typeof report === "string" ? report : JSON.stringify(report, null, 2);
197
+ }
198
+ return JSON.stringify({
199
+ error: `API error (${response.status})`,
200
+ details: JSON.stringify(response.data).substring(0, 2000),
201
+ payload_sent: payload,
202
+ }, null, 2);
203
+ }
204
+ catch (error) {
205
+ if (axios.isAxiosError(error)) {
206
+ if (error.code === "ECONNABORTED") {
207
+ return JSON.stringify({ error: "Request timed out" }, null, 2);
208
+ }
209
+ return JSON.stringify({
210
+ error: "Connection error",
211
+ details: error.message,
212
+ }, null, 2);
213
+ }
214
+ return JSON.stringify({
215
+ error: "Unexpected error",
216
+ details: error instanceof Error ? error.message : String(error),
217
+ }, null, 2);
218
+ }
219
+ }
220
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzF,MAAM,aAAa,GACjB,4DAA4D,CAAC;AAS/D;;GAEG;AACH,SAAS,QAAQ,CAAC,CAAS,EAAE,SAAkB;IAC7C,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,iBAAiB,GAAG;QACxB,UAAU;QACV,WAAW;QACX,UAAU;QACV,WAAW;QACX,KAAK;QACL,MAAM;QACN,KAAK;QACL,MAAM;QACN,OAAO;QACP,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,UAAU;QACV,OAAO;QACP,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,UAAU;QACV,MAAM;KACP,CAAC;IACF,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,cAAwB,EACxB,eAAuB,EACvB,SAAkB;IAElB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IACpE,MAAM,WAAW,GAAG,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAEzD,uBAAuB;IACvB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,EAAE,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,0CAA0C,WAAW,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAe;IACvD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,aAAa,EACb,EAAE,GAAG,EAAE,OAAO,EAAE,EAChB;YACE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,OAAO,EAAE,KAAK;SACf,CACF,CAAC;QACF,OAAO,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,aAAuB,EACvB,eAAuB,EACvB,aAAqB,EACrB,MAAqB;IAErB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,KAAK,EAAE,yBAAyB;YAChC,IAAI,EAAE,mCAAmC;SAC1C,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAED,eAAe;IACf,MAAM,eAAe,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClE,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,KAAK,EAAE,2CAA2C;YAClD,IAAI,EAAE,2CAA2C;SAClD,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,IAAI,SAAmB,CAAC;IACxB,IAAI,WAAmB,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,cAAc,CACpC,aAAa,EACb,eAAe,EACf,aAAa,CACd,CAAC;QACF,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;QAChC,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,KAAK,EAAE,qBAAqB;YAC5B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAED,eAAe;IACf,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,UAAkB,CAAC;IACvB,IAAI,SAAiB,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAC1C,MAAM,CAAC,OAAO,EACd,MAAM,CAAC,iBAAiB,CACzB,CAAC;QACF,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC;QACtC,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;QAEpC,OAAO,GAAG,MAAM,aAAa,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACtD,MAAM,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC,SAAS,CACnB;gBACE,KAAK,EAAE,kBAAkB;gBACzB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,EACD,IAAI,EACJ,CAAC,CACF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,KAAK,EAAE,2BAA2B;YAClC,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,WAAW;IACX,MAAM,OAAO,GAAG;QACd,MAAM,EAAE;YACN,QAAQ,EAAE,MAAM,CAAC,OAAO;SACzB;QACD,OAAO,EAAE,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC;QAC3C,QAAQ,EAAE,QAAQ;KACnB,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE;YACxD,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,OAAO,EAAE,MAAM,CAAC,WAAW,GAAG,IAAI;SACnC,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;YAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;YACnC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,KAAK,EAAE,cAAc,QAAQ,CAAC,MAAM,GAAG;YACvC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC;YACzD,YAAY,EAAE,OAAO;SACtB,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACjE,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CACnB;gBACE,KAAK,EAAE,kBAAkB;gBACzB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,EACD,IAAI,EACJ,CAAC,CACF,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CACnB;YACE,KAAK,EAAE,kBAAkB;YACzB,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAChE,EACD,IAAI,EACJ,CAAC,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Utility functions for file handling and S3 operations
3
+ */
4
+ /**
5
+ * Create a temporary zip file containing test files and failure data
6
+ */
7
+ export declare function createTempZip(testFiles: string[], failureDataDir: string, testRootName?: string, failureRootName?: string): Promise<string>;
8
+ /**
9
+ * Request a signed URL for S3 upload
10
+ */
11
+ export declare function requestSignedUrl(muukKey: string, endpoint: string): Promise<{
12
+ sourcePath: string;
13
+ signedUrl: string;
14
+ }>;
15
+ /**
16
+ * Upload a zip file to S3 using a signed URL
17
+ */
18
+ export declare function uploadZipToS3(zipPath: string, signedUrl: string): Promise<void>;
19
+ /**
20
+ * Build a full HTTPS path for the uploaded zip directory
21
+ */
22
+ export declare function buildS3Path(sourcePath: string, signedUrl: string): string;
23
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AA6BH;;GAEG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EAAE,EACnB,cAAc,EAAE,MAAM,EACtB,YAAY,GAAE,MAAqB,EACnC,eAAe,GAAE,MAAuB,GACvC,OAAO,CAAC,MAAM,CAAC,CAgCjB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBpD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAsBzE"}
package/build/utils.js ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Utility functions for file handling and S3 operations
3
+ */
4
+ import * as fs from "fs/promises";
5
+ import * as path from "path";
6
+ import * as os from "os";
7
+ import archiver from "archiver";
8
+ import axios from "axios";
9
+ import { createWriteStream, createReadStream } from "fs";
10
+ import { URL } from "url";
11
+ /**
12
+ * Create a unique filename if name already exists
13
+ */
14
+ function uniqueName(name, seen) {
15
+ const count = seen.get(name) || 0;
16
+ if (count === 0) {
17
+ seen.set(name, 1);
18
+ return name;
19
+ }
20
+ seen.set(name, count + 1);
21
+ const lastDot = name.lastIndexOf(".");
22
+ if (lastDot > 0) {
23
+ const base = name.substring(0, lastDot);
24
+ const ext = name.substring(lastDot);
25
+ return `${base}_${count + 1}${ext}`;
26
+ }
27
+ return `${name}_${count + 1}`;
28
+ }
29
+ /**
30
+ * Create a temporary zip file containing test files and failure data
31
+ */
32
+ export async function createTempZip(testFiles, failureDataDir, testRootName = "test-files", failureRootName = "failure-data") {
33
+ const tmpDir = os.tmpdir();
34
+ const zipPath = path.join(tmpDir, `muuk-${Date.now()}.zip`);
35
+ return new Promise((resolve, reject) => {
36
+ const output = createWriteStream(zipPath);
37
+ const archive = archiver("zip", {
38
+ zlib: { level: 9 },
39
+ });
40
+ output.on("close", () => {
41
+ resolve(zipPath);
42
+ });
43
+ archive.on("error", (err) => {
44
+ reject(err);
45
+ });
46
+ archive.pipe(output);
47
+ // Add test files
48
+ const nameCounts = new Map();
49
+ for (const testFile of testFiles) {
50
+ const name = uniqueName(path.basename(testFile), nameCounts);
51
+ archive.file(testFile, { name: `${testRootName}/${name}` });
52
+ }
53
+ // Add failure data directory
54
+ archive.directory(failureDataDir, failureRootName);
55
+ archive.finalize();
56
+ });
57
+ }
58
+ /**
59
+ * Request a signed URL for S3 upload
60
+ */
61
+ export async function requestSignedUrl(muukKey, endpoint) {
62
+ const response = await axios.post(endpoint, { key: muukKey }, {
63
+ headers: { "Content-Type": "application/json" },
64
+ timeout: 30000,
65
+ });
66
+ const data = response.data;
67
+ if (!data.sourcePath || !data.signedUrl) {
68
+ throw new Error("Signed URL response missing sourcePath or signedUrl");
69
+ }
70
+ return {
71
+ sourcePath: data.sourcePath,
72
+ signedUrl: data.signedUrl,
73
+ };
74
+ }
75
+ /**
76
+ * Upload a zip file to S3 using a signed URL
77
+ */
78
+ export async function uploadZipToS3(zipPath, signedUrl) {
79
+ const fileStream = createReadStream(zipPath);
80
+ const stats = await fs.stat(zipPath);
81
+ await axios.put(signedUrl, fileStream, {
82
+ headers: {
83
+ "Content-Type": "application/zip",
84
+ "Content-Length": stats.size,
85
+ "x-amz-meta-purpose": "muukmcp",
86
+ "x-amz-server-side-encryption": "AES256",
87
+ },
88
+ timeout: 300000,
89
+ maxContentLength: Infinity,
90
+ maxBodyLength: Infinity,
91
+ });
92
+ }
93
+ /**
94
+ * Build a full HTTPS path for the uploaded zip directory
95
+ */
96
+ export function buildS3Path(sourcePath, signedUrl) {
97
+ try {
98
+ const parsed = new URL(signedUrl);
99
+ const base = `${parsed.protocol}//${parsed.hostname}`;
100
+ const signedPath = parsed.pathname;
101
+ const normalizedSource = sourcePath.replace(/^\/+|\/+$/g, "");
102
+ if (normalizedSource && signedPath.includes(normalizedSource)) {
103
+ const [prefix] = signedPath.split(normalizedSource);
104
+ return `${base}${prefix}${normalizedSource}/`;
105
+ }
106
+ const lastSlash = signedPath.lastIndexOf("/");
107
+ if (lastSlash > 0) {
108
+ const dirPath = signedPath.substring(0, lastSlash);
109
+ return `${base}${dirPath}/`;
110
+ }
111
+ return `${base}/`;
112
+ }
113
+ catch {
114
+ return sourcePath;
115
+ }
116
+ }
117
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY,EAAE,IAAyB;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACpC,OAAO,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,SAAmB,EACnB,cAAsB,EACtB,eAAuB,YAAY,EACnC,kBAA0B,cAAc;IAExC,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAE5D,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE;YAC9B,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;SACnB,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,OAAO,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErB,iBAAiB;QACjB,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC7C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,YAAY,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,6BAA6B;QAC7B,OAAO,CAAC,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;QAEnD,OAAO,CAAC,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,QAAgB;IAEhB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAC/B,QAAQ,EACR,EAAE,GAAG,EAAE,OAAO,EAAE,EAChB;QACE,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,OAAO,EAAE,KAAK;KACf,CACF,CAAC;IAEF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,SAAiB;IAEjB,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE;QACrC,OAAO,EAAE;YACP,cAAc,EAAE,iBAAiB;YACjC,gBAAgB,EAAE,KAAK,CAAC,IAAI;YAC5B,oBAAoB,EAAE,SAAS;YAC/B,8BAA8B,EAAE,QAAQ;SACzC;QACD,OAAO,EAAE,MAAM;QACf,gBAAgB,EAAE,QAAQ;QAC1B,aAAa,EAAE,QAAQ;KACxB,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,SAAiB;IAC/D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC;QACnC,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAE9D,IAAI,gBAAgB,IAAI,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC9D,MAAM,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpD,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,gBAAgB,GAAG,CAAC;QAChD,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YACnD,OAAO,GAAG,IAAI,GAAG,OAAO,GAAG,CAAC;QAC9B,CAAC;QAED,OAAO,GAAG,IAAI,GAAG,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAC;IACpB,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@muuktest/maintenance-mcp",
3
+ "version": "0.1.7",
4
+ "description": "MCP server for analyzing and repairing E2E test failures",
5
+ "type": "module",
6
+ "bin": {
7
+ "maintenance-mcp": "build/index.js"
8
+ },
9
+ "files": [
10
+ "build/**/*",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "prepare": "npm run build",
17
+ "watch": "tsc --watch"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "testing",
22
+ "playwright",
23
+ "e2e",
24
+ "test-repair",
25
+ "ai",
26
+ "automation",
27
+ "muuktest",
28
+ "maintenance"
29
+ ],
30
+ "author": "MuukTest <support@muuktest.com>",
31
+ "license": "MIT",
32
+ "homepage": "https://muuktest.com",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/muuklabs/muukAgents-mcp.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/muuklabs/muukAgents-mcp/issues"
39
+ },
40
+ "dependencies": {
41
+ "@modelcontextprotocol/sdk": "^0.5.0",
42
+ "archiver": "^7.0.1",
43
+ "axios": "^1.6.5"
44
+ },
45
+ "devDependencies": {
46
+ "@types/archiver": "^6.0.2",
47
+ "@types/node": "^24.0.0",
48
+ "typescript": "^5.3.3"
49
+ },
50
+ "engines": {
51
+ "node": ">=24"
52
+ }
53
+ }