@qualitas-id/mcp 1.0.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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +262 -0
  3. package/dist/constants.d.ts +18 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +18 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/index.d.ts +10 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +82 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/schemas/common.d.ts +20 -0
  12. package/dist/schemas/common.d.ts.map +1 -0
  13. package/dist/schemas/common.js +10 -0
  14. package/dist/schemas/common.js.map +1 -0
  15. package/dist/schemas/flow.d.ts +358 -0
  16. package/dist/schemas/flow.d.ts.map +1 -0
  17. package/dist/schemas/flow.js +72 -0
  18. package/dist/schemas/flow.js.map +1 -0
  19. package/dist/schemas/project.d.ts +70 -0
  20. package/dist/schemas/project.d.ts.map +1 -0
  21. package/dist/schemas/project.js +26 -0
  22. package/dist/schemas/project.js.map +1 -0
  23. package/dist/schemas/run.d.ts +54 -0
  24. package/dist/schemas/run.d.ts.map +1 -0
  25. package/dist/schemas/run.js +20 -0
  26. package/dist/schemas/run.js.map +1 -0
  27. package/dist/schemas/variable.d.ts +91 -0
  28. package/dist/schemas/variable.d.ts.map +1 -0
  29. package/dist/schemas/variable.js +30 -0
  30. package/dist/schemas/variable.js.map +1 -0
  31. package/dist/services/api-client.d.ts +101 -0
  32. package/dist/services/api-client.d.ts.map +1 -0
  33. package/dist/services/api-client.js +184 -0
  34. package/dist/services/api-client.js.map +1 -0
  35. package/dist/services/flow-generator.d.ts +31 -0
  36. package/dist/services/flow-generator.d.ts.map +1 -0
  37. package/dist/services/flow-generator.js +638 -0
  38. package/dist/services/flow-generator.js.map +1 -0
  39. package/dist/shared-types.d.ts +579 -0
  40. package/dist/shared-types.d.ts.map +1 -0
  41. package/dist/shared-types.js +12 -0
  42. package/dist/shared-types.js.map +1 -0
  43. package/dist/tools/flows.d.ts +13 -0
  44. package/dist/tools/flows.d.ts.map +1 -0
  45. package/dist/tools/flows.js +458 -0
  46. package/dist/tools/flows.js.map +1 -0
  47. package/dist/tools/projects.d.ts +13 -0
  48. package/dist/tools/projects.d.ts.map +1 -0
  49. package/dist/tools/projects.js +381 -0
  50. package/dist/tools/projects.js.map +1 -0
  51. package/dist/tools/runs.d.ts +9 -0
  52. package/dist/tools/runs.d.ts.map +1 -0
  53. package/dist/tools/runs.js +342 -0
  54. package/dist/tools/runs.js.map +1 -0
  55. package/dist/tools/utils.d.ts +12 -0
  56. package/dist/tools/utils.d.ts.map +1 -0
  57. package/dist/tools/utils.js +144 -0
  58. package/dist/tools/utils.js.map +1 -0
  59. package/dist/tools/variables.d.ts +9 -0
  60. package/dist/tools/variables.d.ts.map +1 -0
  61. package/dist/tools/variables.js +316 -0
  62. package/dist/tools/variables.js.map +1 -0
  63. package/dist/types.d.ts +117 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +8 -0
  66. package/dist/types.js.map +1 -0
  67. package/dist/utils/flow-layout.d.ts +34 -0
  68. package/dist/utils/flow-layout.d.ts.map +1 -0
  69. package/dist/utils/flow-layout.js +109 -0
  70. package/dist/utils/flow-layout.js.map +1 -0
  71. package/dist/utils/flow-validation.d.ts +74 -0
  72. package/dist/utils/flow-validation.d.ts.map +1 -0
  73. package/dist/utils/flow-validation.js +386 -0
  74. package/dist/utils/flow-validation.js.map +1 -0
  75. package/dist/utils/ocr.d.ts +25 -0
  76. package/dist/utils/ocr.d.ts.map +1 -0
  77. package/dist/utils/ocr.js +88 -0
  78. package/dist/utils/ocr.js.map +1 -0
  79. package/package.json +65 -0
  80. package/skills/qualitas.md +253 -0
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Qualitas MCP Server - Run Tools
3
+ *
4
+ * Tools for triggering flow execution, checking run status, and listing run history.
5
+ */
6
+ import { handleApiError } from "../services/api-client.js";
7
+ import { RunFlowSchema, GetRunStatusSchema, ListRunsSchema, } from "../schemas/run.js";
8
+ import { APP_URL } from "../constants.js";
9
+ // ===========================================
10
+ // Helpers
11
+ // ===========================================
12
+ const STATUS_ICON = {
13
+ passed: "✅",
14
+ failed: "❌",
15
+ running: "🔄",
16
+ pending: "⏳",
17
+ error: "⚠️",
18
+ cancelled: "🚫",
19
+ };
20
+ function statusIcon(status) {
21
+ return STATUS_ICON[status] ?? "❓";
22
+ }
23
+ function formatDuration(ms) {
24
+ if (ms == null)
25
+ return "N/A";
26
+ if (ms < 1000)
27
+ return `${ms}ms`;
28
+ const seconds = (ms / 1000).toFixed(1);
29
+ return `${seconds}s`;
30
+ }
31
+ function formatRunMarkdown(run) {
32
+ const icon = statusIcon(run.status);
33
+ const lines = [];
34
+ lines.push(`## ${icon} Run \`${run.id}\``);
35
+ lines.push("");
36
+ lines.push(`- **Status:** ${run.status}`);
37
+ lines.push(`- **Flow ID:** \`${run.flow_id}\``);
38
+ if (run.environment)
39
+ lines.push(`- **Environment:** ${run.environment}`);
40
+ lines.push(`- **Duration:** ${formatDuration(run.duration_ms)}`);
41
+ lines.push(`- **Executed at:** ${run.executed_at}`);
42
+ if (run.executed_by)
43
+ lines.push(`- **Executed by:** ${run.executed_by}`);
44
+ if (run.steps_total != null) {
45
+ lines.push("");
46
+ lines.push("### Step Results");
47
+ lines.push("");
48
+ lines.push(`- **Total:** ${run.steps_total}`);
49
+ lines.push(`- **Passed:** ${run.steps_passed ?? 0}`);
50
+ lines.push(`- **Failed:** ${run.steps_failed ?? 0}`);
51
+ }
52
+ // Display step details from run_steps table (preferred) or steps_result (fallback)
53
+ const steps = run.steps && run.steps.length > 0
54
+ ? run.steps
55
+ : (run.steps_result && Array.isArray(run.steps_result) && run.steps_result.length > 0)
56
+ ? run.steps_result
57
+ : [];
58
+ if (steps.length > 0) {
59
+ lines.push("");
60
+ lines.push("### Step Details");
61
+ lines.push("");
62
+ lines.push("| # | Step | Type | Status | Duration | Log |");
63
+ lines.push("|---|------|------|--------|----------|-----|");
64
+ for (const step of steps) {
65
+ const idx = step.sequenceOrder ?? "?";
66
+ const name = step.nodeId ?? "unknown";
67
+ const type = step.type ?? "unknown";
68
+ const stepStatus = statusIcon(step.status);
69
+ const dur = formatDuration(step.durationMs);
70
+ const log = step.logs
71
+ ? (step.logs.length > 60 ? step.logs.substring(0, 57) + "..." : step.logs)
72
+ : (step.errorMessage ? `❌ ${step.errorMessage}` : "-");
73
+ lines.push(`| ${idx} | ${name} | ${type} | ${stepStatus} | ${dur} | ${log} |`);
74
+ }
75
+ }
76
+ if (run.video_url) {
77
+ lines.push("");
78
+ lines.push(`- **Video:** ${run.video_url}`);
79
+ }
80
+ return lines.join("\n");
81
+ }
82
+ function formatRunsTableMarkdown(runs, projectId, flowId) {
83
+ if (runs.length === 0) {
84
+ return "No runs found for this flow.";
85
+ }
86
+ const lines = [];
87
+ lines.push("## Run History");
88
+ lines.push("");
89
+ lines.push("| Status | Run ID | Environment | Duration | Executed At |");
90
+ lines.push("|--------|--------|-------------|----------|-------------|");
91
+ for (const run of runs) {
92
+ const icon = statusIcon(run.status);
93
+ const env = run.environment ?? "-";
94
+ const dur = formatDuration(run.duration_ms);
95
+ const shortId = run.id.length > 8 ? run.id.slice(0, 8) + "…" : run.id;
96
+ lines.push(`| ${icon} ${run.status} | \`${shortId}\` | ${env} | ${dur} | ${run.executed_at} |`);
97
+ }
98
+ lines.push("");
99
+ lines.push(`> View full run history: [${APP_URL}/projects/${projectId}/flows/${flowId}](${APP_URL}/projects/${projectId}/flows/${flowId})`);
100
+ return lines.join("\n");
101
+ }
102
+ // ===========================================
103
+ // Tool Registration
104
+ // ===========================================
105
+ export function registerRunTools(server, apiClient) {
106
+ // ------------------------------------------
107
+ // 1. qualitas_run_flow
108
+ // ------------------------------------------
109
+ server.registerTool("run_flow", {
110
+ title: "Run Flow",
111
+ description: [
112
+ "Trigger a flow execution on the Qualitas test automation platform.",
113
+ "",
114
+ "**Arguments:**",
115
+ "- `project_id` (UUID, required): The project containing the flow.",
116
+ "- `flow_id` (UUID, required): The flow to execute.",
117
+ "- `environment` (\"dev\" | \"staging\" | \"prod\", optional): Override the flow's default environment for this run.",
118
+ "- `headless` (boolean, default `true`): Whether to run the browser in headless mode.",
119
+ "",
120
+ "**Returns:**",
121
+ "- Markdown with the run ID, initial status, and a link to monitor execution.",
122
+ "- The run executes asynchronously — use `get_run_status` to poll for completion.",
123
+ "",
124
+ "**Example:**",
125
+ "```",
126
+ 'qualitas_run_flow({ project_id: "abc-123", flow_id: "def-456", environment: "staging" })',
127
+ "```",
128
+ "",
129
+ "**Errors:**",
130
+ "- 404: Project or flow not found.",
131
+ "- 422: Flow has no nodes or is misconfigured.",
132
+ "- 401: Invalid or expired API key.",
133
+ ].join("\n"),
134
+ inputSchema: RunFlowSchema.shape,
135
+ annotations: {
136
+ title: "Run Flow",
137
+ readOnlyHint: false,
138
+ destructiveHint: false,
139
+ idempotentHint: false,
140
+ openWorldHint: true,
141
+ },
142
+ }, async (args) => {
143
+ try {
144
+ const response = await apiClient.runFlow(args.project_id, args.flow_id, {
145
+ environment: args.environment,
146
+ headless: args.headless,
147
+ });
148
+ const run = response.data;
149
+ const lines = [];
150
+ lines.push(`## 🚀 Flow Execution Started`);
151
+ lines.push("");
152
+ lines.push(`- **Run ID:** \`${run.id}\``);
153
+ lines.push(`- **Flow ID:** \`${run.flow_id}\``);
154
+ lines.push(`- **Status:** ${statusIcon(run.status)} ${run.status}`);
155
+ if (run.environment)
156
+ lines.push(`- **Environment:** ${run.environment}`);
157
+ lines.push("");
158
+ lines.push(`> Monitor progress: [${APP_URL}/projects/${args.project_id}/flows/${args.flow_id}/runs/${run.id}](${APP_URL}/projects/${args.project_id}/flows/${args.flow_id}/runs/${run.id})`);
159
+ lines.push("");
160
+ lines.push("Use `get_run_status` with this run ID to check execution results.");
161
+ return {
162
+ content: [{ type: "text", text: lines.join("\n") }],
163
+ };
164
+ }
165
+ catch (error) {
166
+ return {
167
+ content: [{ type: "text", text: handleApiError(error) }],
168
+ isError: true,
169
+ };
170
+ }
171
+ });
172
+ // ------------------------------------------
173
+ // 2. qualitas_get_run_status
174
+ // ------------------------------------------
175
+ server.registerTool("get_run_status", {
176
+ title: "Get Run Status",
177
+ description: [
178
+ "Get the status and results of a flow run.",
179
+ "",
180
+ "**Arguments:**",
181
+ "- `project_id` (UUID, required): The project containing the flow.",
182
+ "- `flow_id` (UUID, required): The flow that was executed.",
183
+ "- `run_id` (UUID, required): The run to check.",
184
+ "- `response_format` (\"markdown\" | \"json\", default \"markdown\"): Output format.",
185
+ "",
186
+ "**Returns (markdown):**",
187
+ "- Run status, duration, step pass/fail counts, and a detailed step results table.",
188
+ "",
189
+ "**Returns (json):**",
190
+ "```json",
191
+ '{',
192
+ ' "id": "run-uuid",',
193
+ ' "flow_id": "flow-uuid",',
194
+ ' "status": "passed",',
195
+ ' "environment": "dev",',
196
+ ' "duration_ms": 4523,',
197
+ ' "steps_total": 5,',
198
+ ' "steps_passed": 5,',
199
+ ' "steps_failed": 0,',
200
+ ' "steps_result": [...],',
201
+ ' "video_url": "https://...",',
202
+ ' "executed_at": "2025-01-15T10:30:00Z"',
203
+ '}',
204
+ "```",
205
+ "",
206
+ "**Example:**",
207
+ "```",
208
+ 'qualitas_get_run_status({ project_id: "abc-123", flow_id: "def-456", run_id: "ghi-789" })',
209
+ "```",
210
+ "",
211
+ "**Errors:**",
212
+ "- 404: Project, flow, or run not found.",
213
+ "- 401: Invalid or expired API key.",
214
+ ].join("\n"),
215
+ inputSchema: GetRunStatusSchema.shape,
216
+ annotations: {
217
+ title: "Get Run Status",
218
+ readOnlyHint: true,
219
+ destructiveHint: false,
220
+ idempotentHint: true,
221
+ openWorldHint: true,
222
+ },
223
+ }, async (args) => {
224
+ try {
225
+ // Fetch run details and step details in parallel
226
+ const [runResponse, stepsResponse] = await Promise.all([
227
+ apiClient.getRunStatus(args.project_id, args.flow_id, args.run_id),
228
+ apiClient.getRunSteps(args.run_id),
229
+ ]);
230
+ const run = runResponse.data;
231
+ const steps = stepsResponse.data || [];
232
+ // Merge steps into run object
233
+ const enrichedRun = {
234
+ ...run,
235
+ steps,
236
+ };
237
+ if (args.response_format === "json") {
238
+ return {
239
+ content: [{ type: "text", text: JSON.stringify(enrichedRun, null, 2) }],
240
+ };
241
+ }
242
+ return {
243
+ content: [{ type: "text", text: formatRunMarkdown(enrichedRun) }],
244
+ };
245
+ }
246
+ catch (error) {
247
+ return {
248
+ content: [{ type: "text", text: handleApiError(error) }],
249
+ isError: true,
250
+ };
251
+ }
252
+ });
253
+ // ------------------------------------------
254
+ // 3. qualitas_list_runs
255
+ // ------------------------------------------
256
+ server.registerTool("list_runs", {
257
+ title: "List Runs",
258
+ description: [
259
+ "List the execution history for a flow, ordered by most recent first.",
260
+ "",
261
+ "**Arguments:**",
262
+ "- `project_id` (UUID, required): The project containing the flow.",
263
+ "- `flow_id` (UUID, required): The flow whose runs to list.",
264
+ "- `limit` (1–100, default 20): Maximum number of runs to return.",
265
+ "- `offset` (default 0): Number of runs to skip for pagination.",
266
+ "- `response_format` (\"markdown\" | \"json\", default \"markdown\"): Output format.",
267
+ "",
268
+ "**Returns (markdown):**",
269
+ "- A table with status indicators, run IDs, environment, duration, and execution time.",
270
+ "",
271
+ "**Returns (json):**",
272
+ "```json",
273
+ '{',
274
+ ' "runs": [',
275
+ ' {',
276
+ ' "id": "run-uuid",',
277
+ ' "flow_id": "flow-uuid",',
278
+ ' "status": "passed",',
279
+ ' "environment": "dev",',
280
+ ' "duration_ms": 4523,',
281
+ ' "executed_at": "2025-01-15T10:30:00Z"',
282
+ ' }',
283
+ ' ],',
284
+ ' "meta": { "page": 1, "limit": 20, "total": 42 }',
285
+ '}',
286
+ "```",
287
+ "",
288
+ "**Example:**",
289
+ "```",
290
+ 'qualitas_list_runs({ project_id: "abc-123", flow_id: "def-456", limit: 10 })',
291
+ "```",
292
+ "",
293
+ "**Errors:**",
294
+ "- 404: Project or flow not found.",
295
+ "- 401: Invalid or expired API key.",
296
+ ].join("\n"),
297
+ inputSchema: ListRunsSchema.shape,
298
+ annotations: {
299
+ title: "List Runs",
300
+ readOnlyHint: true,
301
+ destructiveHint: false,
302
+ idempotentHint: true,
303
+ openWorldHint: true,
304
+ },
305
+ }, async (args) => {
306
+ try {
307
+ const limit = args.limit ?? 20;
308
+ const offset = args.offset ?? 0;
309
+ const page = Math.floor(offset / limit) + 1;
310
+ const response = await apiClient.listRuns(args.project_id, args.flow_id, {
311
+ limit,
312
+ page,
313
+ });
314
+ const runs = response.data;
315
+ if (args.response_format === "json") {
316
+ return {
317
+ content: [
318
+ {
319
+ type: "text",
320
+ text: JSON.stringify({ runs, meta: response.meta }, null, 2),
321
+ },
322
+ ],
323
+ };
324
+ }
325
+ return {
326
+ content: [
327
+ {
328
+ type: "text",
329
+ text: formatRunsTableMarkdown(runs, args.project_id, args.flow_id),
330
+ },
331
+ ],
332
+ };
333
+ }
334
+ catch (error) {
335
+ return {
336
+ content: [{ type: "text", text: handleApiError(error) }],
337
+ isError: true,
338
+ };
339
+ }
340
+ });
341
+ }
342
+ //# sourceMappingURL=runs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/tools/runs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Utility Tools
3
+ *
4
+ * MCP tools for utility functions like OCR, screenshots, etc.
5
+ */
6
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import type { QualitasApiClient } from "../services/api-client.js";
8
+ /**
9
+ * Register utility tools with the MCP server
10
+ */
11
+ export declare function registerUtilityTools(server: McpServer, apiClient: QualitasApiClient): void;
12
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAInE;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,iBAAiB,GAC3B,IAAI,CA2JN"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Utility Tools
3
+ *
4
+ * MCP tools for utility functions like OCR, screenshots, etc.
5
+ */
6
+ import { z } from "zod";
7
+ import { handleApiError } from "../services/api-client.js";
8
+ import { extractTextFromImageUrl, extractErrorMessage } from "../utils/ocr.js";
9
+ /**
10
+ * Register utility tools with the MCP server
11
+ */
12
+ export function registerUtilityTools(server, apiClient) {
13
+ // ===========================================
14
+ // 1. extract_screenshot_text
15
+ // ===========================================
16
+ server.tool("extract_screenshot_text", `Extract text from a screenshot image using OCR. Useful for reading error messages from test failure screenshots.
17
+
18
+ **Use cases:**
19
+ - Read error messages from failed test screenshots
20
+ - Extract text from any image URL
21
+ - Debug test failures by understanding what's shown on screen
22
+
23
+ **Arguments:**
24
+ - \`image_url\` (string, required): URL of the image to extract text from
25
+ - \`extract_error\` (boolean, optional, default true): Try to extract error message from the text
26
+
27
+ **Returns:**
28
+ - Extracted text from the image
29
+ - Confidence score (0-100)
30
+ - Error message if extract_error is true`, {
31
+ image_url: z.string().url("Invalid image URL").describe("URL of the image to extract text from"),
32
+ extract_error: z.boolean().default(true).describe("Try to extract error message from the text"),
33
+ }, async (params) => {
34
+ try {
35
+ const result = await extractTextFromImageUrl(params.image_url);
36
+ if (result.error) {
37
+ return {
38
+ content: [
39
+ {
40
+ type: "text",
41
+ text: [
42
+ `# OCR Failed`,
43
+ "",
44
+ `**Error:** ${result.error}`,
45
+ "",
46
+ `The image could not be processed. Make sure the URL is accessible.`,
47
+ ].join("\n"),
48
+ },
49
+ ],
50
+ isError: true,
51
+ };
52
+ }
53
+ const lines = [];
54
+ lines.push(`# Screenshot Text Extracted`);
55
+ lines.push("");
56
+ lines.push(`**Confidence:** ${result.confidence.toFixed(1)}%`);
57
+ lines.push("");
58
+ if (params.extract_error && result.text) {
59
+ const errorMessage = extractErrorMessage(result.text);
60
+ if (errorMessage) {
61
+ lines.push(`**Error Message:**`);
62
+ lines.push(`\`\`\``);
63
+ lines.push(errorMessage);
64
+ lines.push(`\`\`\``);
65
+ lines.push("");
66
+ }
67
+ }
68
+ lines.push(`**Full Text:**`);
69
+ lines.push(`\`\`\``);
70
+ lines.push(result.text || "(No text detected)");
71
+ lines.push(`\`\`\``);
72
+ return {
73
+ content: [{ type: "text", text: lines.join("\n") }],
74
+ };
75
+ }
76
+ catch (error) {
77
+ return {
78
+ content: [{ type: "text", text: handleApiError(error) }],
79
+ isError: true,
80
+ };
81
+ }
82
+ });
83
+ // ===========================================
84
+ // 2. get_run_screenshot
85
+ // ===========================================
86
+ server.tool("get_run_screenshot", `Get the screenshot URL for a specific step in a test run. Useful for debugging failed steps.
87
+
88
+ **Arguments:**
89
+ - \`run_id\` (UUID, required): The run ID
90
+ - \`node_id\` (string, optional): The node ID to get screenshot for. If not specified, returns all screenshots.
91
+
92
+ **Returns:**
93
+ - Screenshot URL(s) for the specified step or all failed steps`, {
94
+ run_id: z.string().uuid("Invalid run ID").describe("The run ID"),
95
+ node_id: z.string().optional().describe("The node ID to get screenshot for"),
96
+ }, async (params) => {
97
+ try {
98
+ // Fetch run steps
99
+ const stepsResponse = await apiClient.getRunSteps(params.run_id);
100
+ const steps = stepsResponse.data || [];
101
+ // Filter steps with screenshots
102
+ let stepsWithScreenshots = steps.filter((s) => s.screenshotUrl);
103
+ // Filter by node_id if specified
104
+ if (params.node_id) {
105
+ stepsWithScreenshots = stepsWithScreenshots.filter((s) => s.nodeId === params.node_id);
106
+ }
107
+ if (stepsWithScreenshots.length === 0) {
108
+ return {
109
+ content: [
110
+ {
111
+ type: "text",
112
+ text: `No screenshots found for run \`${params.run_id}\`${params.node_id ? ` and node \`${params.node_id}\`` : ""}.`,
113
+ },
114
+ ],
115
+ };
116
+ }
117
+ const lines = [];
118
+ lines.push(`# Run Screenshots`);
119
+ lines.push("");
120
+ lines.push(`**Run ID:** \`${params.run_id}\``);
121
+ lines.push("");
122
+ for (const step of stepsWithScreenshots) {
123
+ lines.push(`### Step: ${step.nodeId} (${step.type})`);
124
+ lines.push(`- **Status:** ${step.status}`);
125
+ lines.push(`- **Sequence:** ${step.sequenceOrder}`);
126
+ if (step.errorMessage) {
127
+ lines.push(`- **Error:** ${step.errorMessage}`);
128
+ }
129
+ lines.push(`- **Screenshot:** ${step.screenshotUrl}`);
130
+ lines.push("");
131
+ }
132
+ return {
133
+ content: [{ type: "text", text: lines.join("\n") }],
134
+ };
135
+ }
136
+ catch (error) {
137
+ return {
138
+ content: [{ type: "text", text: handleApiError(error) }],
139
+ isError: true,
140
+ };
141
+ }
142
+ });
143
+ }
144
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Qualitas MCP Server - Variable Tools
3
+ *
4
+ * Tools for managing project-level environment variables (CRUD).
5
+ */
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import type { QualitasApiClient } from "../services/api-client.js";
8
+ export declare function registerVariableTools(server: McpServer, apiClient: QualitasApiClient): void;
9
+ //# sourceMappingURL=variables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../src/tools/variables.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAoEnE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,iBAAiB,GAC3B,IAAI,CAgSN"}