zephyr-scale-mcp-server 0.0.4 → 0.1.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.
- package/README.md +34 -52
- package/build/index.js +171 -0
- package/package.json +1 -1
- package/src/index.ts +180 -0
package/README.md
CHANGED
|
@@ -4,35 +4,23 @@ Model Context Protocol server for Zephyr Scale test management. Create, read, an
|
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
|
-
### Option 1:
|
|
8
|
-
|
|
9
|
-
npm install -g zephyr-scale-mcp-server
|
|
10
|
-
```
|
|
7
|
+
### Option 1: Using npx (Recommended - No installation required)
|
|
8
|
+
Just configure your MCP client with the npx command below.
|
|
11
9
|
|
|
12
|
-
### Option 2:
|
|
10
|
+
### Option 2: Install from npm
|
|
13
11
|
```bash
|
|
14
|
-
|
|
15
|
-
git clone <repository-url>
|
|
16
|
-
cd zephyr-scale-mcp-server
|
|
17
|
-
npm install
|
|
18
|
-
npm run build
|
|
19
|
-
|
|
20
|
-
# Configure environment
|
|
21
|
-
export ZEPHYR_API_KEY="your-api-token"
|
|
22
|
-
export ZEPHYR_BASE_URL="https://your-company.atlassian.net"
|
|
23
|
-
|
|
24
|
-
# Test the server
|
|
25
|
-
node build/index.js
|
|
12
|
+
npm install -g zephyr-scale-mcp-server
|
|
26
13
|
```
|
|
27
14
|
|
|
28
15
|
## MCP Configuration
|
|
29
16
|
|
|
30
|
-
###
|
|
17
|
+
### Option 1: Using npx (Recommended - No installation required)
|
|
31
18
|
```json
|
|
32
19
|
{
|
|
33
20
|
"mcpServers": {
|
|
34
21
|
"zephyr-server": {
|
|
35
|
-
"command": "
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["zephyr-scale-mcp-server@latest"],
|
|
36
24
|
"env": {
|
|
37
25
|
"ZEPHYR_API_KEY": "your-api-token",
|
|
38
26
|
"ZEPHYR_BASE_URL": "https://your-company.atlassian.net"
|
|
@@ -42,13 +30,18 @@ node build/index.js
|
|
|
42
30
|
}
|
|
43
31
|
```
|
|
44
32
|
|
|
45
|
-
###
|
|
33
|
+
### Option 2: Using global npm installation
|
|
34
|
+
First install the package globally:
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g zephyr-scale-mcp-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then configure:
|
|
46
40
|
```json
|
|
47
41
|
{
|
|
48
42
|
"mcpServers": {
|
|
49
43
|
"zephyr-server": {
|
|
50
|
-
"command": "
|
|
51
|
-
"args": ["/path/to/zephyr-scale-mcp-server/build/index.js"],
|
|
44
|
+
"command": "zephyr-scale-mcp",
|
|
52
45
|
"env": {
|
|
53
46
|
"ZEPHYR_API_KEY": "your-api-token",
|
|
54
47
|
"ZEPHYR_BASE_URL": "https://your-company.atlassian.net"
|
|
@@ -60,13 +53,15 @@ node build/index.js
|
|
|
60
53
|
|
|
61
54
|
## Available Tools
|
|
62
55
|
|
|
63
|
-
- `
|
|
64
|
-
- `
|
|
65
|
-
- `
|
|
66
|
-
- `update_test_case_bdd` - Update
|
|
56
|
+
- `get_test_case` - Get detailed information about a specific test case
|
|
57
|
+
- `create_test_case` - Create a new test case with STEP_BY_STEP or PLAIN_TEXT content
|
|
58
|
+
- `create_test_case_with_bdd` - Create a new test case with BDD content
|
|
59
|
+
- `update_test_case_bdd` - Update an existing test case with BDD content
|
|
67
60
|
- `delete_test_case` - Delete a specific test case
|
|
68
|
-
- `create_folder` - Create
|
|
69
|
-
- `get_test_run_cases` - Get test
|
|
61
|
+
- `create_folder` - Create a new folder in Zephyr Scale
|
|
62
|
+
- `get_test_run_cases` - Get test case keys from a test run
|
|
63
|
+
- `create_test_run` - Create a new test run
|
|
64
|
+
- `get_test_run` - Get detailed information about a specific test run
|
|
70
65
|
|
|
71
66
|
## Examples
|
|
72
67
|
|
|
@@ -110,37 +105,24 @@ node build/index.js
|
|
|
110
105
|
}
|
|
111
106
|
```
|
|
112
107
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# Test with environment variables
|
|
123
|
-
export ZEPHYR_API_KEY="your-api-token"
|
|
124
|
-
export ZEPHYR_BASE_URL="https://your-company.atlassian.net"
|
|
125
|
-
zephyr-scale-mcp
|
|
126
|
-
# Should start the MCP server (Ctrl+C to exit)
|
|
108
|
+
### Create Test Run
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"project_key": "PROJ",
|
|
112
|
+
"name": "Sprint 1 Test Run",
|
|
113
|
+
"test_case_keys": ["PROJ-T123", "PROJ-T124", "PROJ-T125"],
|
|
114
|
+
"environment": "Production",
|
|
115
|
+
"description": "Testing core functionality for Sprint 1"
|
|
116
|
+
}
|
|
127
117
|
```
|
|
128
118
|
|
|
129
|
-
###
|
|
130
|
-
|
|
131
|
-
Once configured in your MCP client, test with:
|
|
132
|
-
|
|
119
|
+
### Get Test Run
|
|
133
120
|
```json
|
|
134
121
|
{
|
|
135
|
-
"
|
|
136
|
-
"arguments": {
|
|
137
|
-
"test_case_key": "PROJ-T123"
|
|
138
|
-
}
|
|
122
|
+
"test_run_key": "PROJ-R456"
|
|
139
123
|
}
|
|
140
124
|
```
|
|
141
125
|
|
|
142
|
-
Expected response includes test case details, BDD scripts, and metadata.
|
|
143
|
-
|
|
144
126
|
## Authentication
|
|
145
127
|
|
|
146
128
|
Get your API token from:
|
package/build/index.js
CHANGED
|
@@ -249,6 +249,71 @@ class ZephyrServer {
|
|
|
249
249
|
required: ['test_case_key'],
|
|
250
250
|
},
|
|
251
251
|
},
|
|
252
|
+
{
|
|
253
|
+
name: 'create_test_run',
|
|
254
|
+
description: 'Create a new test run',
|
|
255
|
+
inputSchema: {
|
|
256
|
+
type: 'object',
|
|
257
|
+
properties: {
|
|
258
|
+
project_key: {
|
|
259
|
+
type: 'string',
|
|
260
|
+
description: 'Project key (required)',
|
|
261
|
+
},
|
|
262
|
+
name: {
|
|
263
|
+
type: 'string',
|
|
264
|
+
description: 'Test run name (required)',
|
|
265
|
+
},
|
|
266
|
+
test_case_keys: {
|
|
267
|
+
type: 'array',
|
|
268
|
+
description: 'Array of test case keys to include in the test run',
|
|
269
|
+
items: { type: 'string' }
|
|
270
|
+
},
|
|
271
|
+
folder: {
|
|
272
|
+
type: 'string',
|
|
273
|
+
description: 'Folder path (optional)',
|
|
274
|
+
},
|
|
275
|
+
planned_start_date: {
|
|
276
|
+
type: 'string',
|
|
277
|
+
description: 'Planned start date in ISO format (optional)',
|
|
278
|
+
},
|
|
279
|
+
planned_end_date: {
|
|
280
|
+
type: 'string',
|
|
281
|
+
description: 'Planned end date in ISO format (optional)',
|
|
282
|
+
},
|
|
283
|
+
description: {
|
|
284
|
+
type: 'string',
|
|
285
|
+
description: 'Test run description (optional)',
|
|
286
|
+
},
|
|
287
|
+
owner: {
|
|
288
|
+
type: 'string',
|
|
289
|
+
description: 'Test run owner (optional)',
|
|
290
|
+
},
|
|
291
|
+
environment: {
|
|
292
|
+
type: 'string',
|
|
293
|
+
description: 'Test environment (optional)',
|
|
294
|
+
},
|
|
295
|
+
custom_fields: {
|
|
296
|
+
type: 'object',
|
|
297
|
+
description: 'Custom fields object (optional)',
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
required: ['project_key', 'name'],
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: 'get_test_run',
|
|
305
|
+
description: 'Get detailed information about a specific test run',
|
|
306
|
+
inputSchema: {
|
|
307
|
+
type: 'object',
|
|
308
|
+
properties: {
|
|
309
|
+
test_run_key: {
|
|
310
|
+
type: 'string',
|
|
311
|
+
description: 'Test run key (e.g., PROJ-R123)',
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
required: ['test_run_key'],
|
|
315
|
+
},
|
|
316
|
+
},
|
|
252
317
|
],
|
|
253
318
|
}));
|
|
254
319
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -268,6 +333,10 @@ class ZephyrServer {
|
|
|
268
333
|
return await this.getTestRunCases(request.params.arguments);
|
|
269
334
|
case 'delete_test_case':
|
|
270
335
|
return await this.deleteTestCase(request.params.arguments);
|
|
336
|
+
case 'create_test_run':
|
|
337
|
+
return await this.createTestRun(request.params.arguments);
|
|
338
|
+
case 'get_test_run':
|
|
339
|
+
return await this.getTestRun(request.params.arguments);
|
|
271
340
|
default:
|
|
272
341
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
273
342
|
}
|
|
@@ -605,6 +674,108 @@ class ZephyrServer {
|
|
|
605
674
|
throw new McpError(ErrorCode.InternalError, `Failed to delete test case: ${errorMessage}`);
|
|
606
675
|
}
|
|
607
676
|
}
|
|
677
|
+
async createTestRun(args) {
|
|
678
|
+
const { project_key, name, test_case_keys, folder, planned_start_date, planned_end_date, description, owner, environment, custom_fields } = args;
|
|
679
|
+
// Build the basic payload
|
|
680
|
+
const payload = {
|
|
681
|
+
projectKey: project_key,
|
|
682
|
+
name: name,
|
|
683
|
+
};
|
|
684
|
+
// Add optional fields
|
|
685
|
+
if (test_case_keys && test_case_keys.length > 0) {
|
|
686
|
+
payload.items = test_case_keys.map((testCaseKey) => ({
|
|
687
|
+
testCaseKey: testCaseKey
|
|
688
|
+
}));
|
|
689
|
+
}
|
|
690
|
+
if (folder)
|
|
691
|
+
payload.folder = folder;
|
|
692
|
+
if (planned_start_date)
|
|
693
|
+
payload.plannedStartDate = planned_start_date;
|
|
694
|
+
if (planned_end_date)
|
|
695
|
+
payload.plannedEndDate = planned_end_date;
|
|
696
|
+
if (description)
|
|
697
|
+
payload.description = description;
|
|
698
|
+
if (owner)
|
|
699
|
+
payload.owner = owner;
|
|
700
|
+
if (environment)
|
|
701
|
+
payload.environment = environment;
|
|
702
|
+
if (custom_fields)
|
|
703
|
+
payload.customFields = custom_fields;
|
|
704
|
+
try {
|
|
705
|
+
const response = await this.axiosInstance.post('/rest/atm/1.0/testrun', payload);
|
|
706
|
+
if (response.status === 201) {
|
|
707
|
+
const testRunKey = response.data.key || 'Unknown';
|
|
708
|
+
return {
|
|
709
|
+
content: [
|
|
710
|
+
{
|
|
711
|
+
type: 'text',
|
|
712
|
+
text: `✅ Test run created successfully: ${testRunKey}\n${JSON.stringify({
|
|
713
|
+
key: testRunKey,
|
|
714
|
+
name: name,
|
|
715
|
+
testCaseCount: test_case_keys?.length || 0,
|
|
716
|
+
environment: environment || 'Not specified'
|
|
717
|
+
}, null, 2)}`,
|
|
718
|
+
},
|
|
719
|
+
],
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
throw new Error(`Unexpected status code: ${response.status}`);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
catch (error) {
|
|
727
|
+
let errorMessage = 'Unknown error';
|
|
728
|
+
if (error instanceof Error && 'response' in error) {
|
|
729
|
+
const axiosError = error;
|
|
730
|
+
errorMessage = `Status: ${axiosError.response?.status}, Data: ${JSON.stringify(axiosError.response?.data)}`;
|
|
731
|
+
}
|
|
732
|
+
else if (error instanceof Error) {
|
|
733
|
+
errorMessage = error.message;
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
errorMessage = String(error);
|
|
737
|
+
}
|
|
738
|
+
throw new McpError(ErrorCode.InternalError, `Failed to create test run: ${errorMessage}`);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
async getTestRun(args) {
|
|
742
|
+
const { test_run_key } = args;
|
|
743
|
+
try {
|
|
744
|
+
const response = await this.axiosInstance.get(`/rest/atm/1.0/testrun/${test_run_key}`);
|
|
745
|
+
if (response.status === 200) {
|
|
746
|
+
return {
|
|
747
|
+
content: [
|
|
748
|
+
{
|
|
749
|
+
type: 'text',
|
|
750
|
+
text: JSON.stringify(response.data, null, 2),
|
|
751
|
+
},
|
|
752
|
+
],
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
throw new Error(`Failed to retrieve test run: ${response.status}`);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
let errorMessage = 'Unknown error';
|
|
761
|
+
if (error instanceof Error && 'response' in error) {
|
|
762
|
+
const axiosError = error;
|
|
763
|
+
if (axiosError.response?.status === 404) {
|
|
764
|
+
errorMessage = `Test run ${test_run_key} not found`;
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
errorMessage = `Status: ${axiosError.response?.status}, Data: ${JSON.stringify(axiosError.response?.data)}`;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
else if (error instanceof Error) {
|
|
771
|
+
errorMessage = error.message;
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
errorMessage = String(error);
|
|
775
|
+
}
|
|
776
|
+
throw new McpError(ErrorCode.InternalError, `Failed to get test run: ${errorMessage}`);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
608
779
|
async run() {
|
|
609
780
|
const transport = new StdioServerTransport();
|
|
610
781
|
await this.server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zephyr-scale-mcp-server",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for Zephyr Scale test case management with comprehensive STEP_BY_STEP, PLAIN_TEXT, and BDD support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./build/index.js",
|
package/src/index.ts
CHANGED
|
@@ -266,6 +266,71 @@ class ZephyrServer {
|
|
|
266
266
|
required: ['test_case_key'],
|
|
267
267
|
},
|
|
268
268
|
},
|
|
269
|
+
{
|
|
270
|
+
name: 'create_test_run',
|
|
271
|
+
description: 'Create a new test run',
|
|
272
|
+
inputSchema: {
|
|
273
|
+
type: 'object',
|
|
274
|
+
properties: {
|
|
275
|
+
project_key: {
|
|
276
|
+
type: 'string',
|
|
277
|
+
description: 'Project key (required)',
|
|
278
|
+
},
|
|
279
|
+
name: {
|
|
280
|
+
type: 'string',
|
|
281
|
+
description: 'Test run name (required)',
|
|
282
|
+
},
|
|
283
|
+
test_case_keys: {
|
|
284
|
+
type: 'array',
|
|
285
|
+
description: 'Array of test case keys to include in the test run',
|
|
286
|
+
items: { type: 'string' }
|
|
287
|
+
},
|
|
288
|
+
folder: {
|
|
289
|
+
type: 'string',
|
|
290
|
+
description: 'Folder path (optional)',
|
|
291
|
+
},
|
|
292
|
+
planned_start_date: {
|
|
293
|
+
type: 'string',
|
|
294
|
+
description: 'Planned start date in ISO format (optional)',
|
|
295
|
+
},
|
|
296
|
+
planned_end_date: {
|
|
297
|
+
type: 'string',
|
|
298
|
+
description: 'Planned end date in ISO format (optional)',
|
|
299
|
+
},
|
|
300
|
+
description: {
|
|
301
|
+
type: 'string',
|
|
302
|
+
description: 'Test run description (optional)',
|
|
303
|
+
},
|
|
304
|
+
owner: {
|
|
305
|
+
type: 'string',
|
|
306
|
+
description: 'Test run owner (optional)',
|
|
307
|
+
},
|
|
308
|
+
environment: {
|
|
309
|
+
type: 'string',
|
|
310
|
+
description: 'Test environment (optional)',
|
|
311
|
+
},
|
|
312
|
+
custom_fields: {
|
|
313
|
+
type: 'object',
|
|
314
|
+
description: 'Custom fields object (optional)',
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
required: ['project_key', 'name'],
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
name: 'get_test_run',
|
|
322
|
+
description: 'Get detailed information about a specific test run',
|
|
323
|
+
inputSchema: {
|
|
324
|
+
type: 'object',
|
|
325
|
+
properties: {
|
|
326
|
+
test_run_key: {
|
|
327
|
+
type: 'string',
|
|
328
|
+
description: 'Test run key (e.g., PROJ-R123)',
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
required: ['test_run_key'],
|
|
332
|
+
},
|
|
333
|
+
},
|
|
269
334
|
],
|
|
270
335
|
}));
|
|
271
336
|
|
|
@@ -286,6 +351,10 @@ class ZephyrServer {
|
|
|
286
351
|
return await this.getTestRunCases(request.params.arguments);
|
|
287
352
|
case 'delete_test_case':
|
|
288
353
|
return await this.deleteTestCase(request.params.arguments);
|
|
354
|
+
case 'create_test_run':
|
|
355
|
+
return await this.createTestRun(request.params.arguments);
|
|
356
|
+
case 'get_test_run':
|
|
357
|
+
return await this.getTestRun(request.params.arguments);
|
|
289
358
|
default:
|
|
290
359
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
291
360
|
}
|
|
@@ -660,6 +729,117 @@ class ZephyrServer {
|
|
|
660
729
|
}
|
|
661
730
|
}
|
|
662
731
|
|
|
732
|
+
private async createTestRun(args: any) {
|
|
733
|
+
const {
|
|
734
|
+
project_key,
|
|
735
|
+
name,
|
|
736
|
+
test_case_keys,
|
|
737
|
+
folder,
|
|
738
|
+
planned_start_date,
|
|
739
|
+
planned_end_date,
|
|
740
|
+
description,
|
|
741
|
+
owner,
|
|
742
|
+
environment,
|
|
743
|
+
custom_fields
|
|
744
|
+
} = args;
|
|
745
|
+
|
|
746
|
+
// Build the basic payload
|
|
747
|
+
const payload: any = {
|
|
748
|
+
projectKey: project_key,
|
|
749
|
+
name: name,
|
|
750
|
+
};
|
|
751
|
+
|
|
752
|
+
// Add optional fields
|
|
753
|
+
if (test_case_keys && test_case_keys.length > 0) {
|
|
754
|
+
payload.items = test_case_keys.map((testCaseKey: string) => ({
|
|
755
|
+
testCaseKey: testCaseKey
|
|
756
|
+
}));
|
|
757
|
+
}
|
|
758
|
+
if (folder) payload.folder = folder;
|
|
759
|
+
if (planned_start_date) payload.plannedStartDate = planned_start_date;
|
|
760
|
+
if (planned_end_date) payload.plannedEndDate = planned_end_date;
|
|
761
|
+
if (description) payload.description = description;
|
|
762
|
+
if (owner) payload.owner = owner;
|
|
763
|
+
if (environment) payload.environment = environment;
|
|
764
|
+
if (custom_fields) payload.customFields = custom_fields;
|
|
765
|
+
|
|
766
|
+
try {
|
|
767
|
+
const response = await this.axiosInstance.post('/rest/atm/1.0/testrun', payload);
|
|
768
|
+
|
|
769
|
+
if (response.status === 201) {
|
|
770
|
+
const testRunKey = response.data.key || 'Unknown';
|
|
771
|
+
return {
|
|
772
|
+
content: [
|
|
773
|
+
{
|
|
774
|
+
type: 'text',
|
|
775
|
+
text: `✅ Test run created successfully: ${testRunKey}\n${JSON.stringify({
|
|
776
|
+
key: testRunKey,
|
|
777
|
+
name: name,
|
|
778
|
+
testCaseCount: test_case_keys?.length || 0,
|
|
779
|
+
environment: environment || 'Not specified'
|
|
780
|
+
}, null, 2)}`,
|
|
781
|
+
},
|
|
782
|
+
],
|
|
783
|
+
};
|
|
784
|
+
} else {
|
|
785
|
+
throw new Error(`Unexpected status code: ${response.status}`);
|
|
786
|
+
}
|
|
787
|
+
} catch (error) {
|
|
788
|
+
let errorMessage = 'Unknown error';
|
|
789
|
+
if (error instanceof Error && 'response' in error) {
|
|
790
|
+
const axiosError = error as any;
|
|
791
|
+
errorMessage = `Status: ${axiosError.response?.status}, Data: ${JSON.stringify(axiosError.response?.data)}`;
|
|
792
|
+
} else if (error instanceof Error) {
|
|
793
|
+
errorMessage = error.message;
|
|
794
|
+
} else {
|
|
795
|
+
errorMessage = String(error);
|
|
796
|
+
}
|
|
797
|
+
throw new McpError(
|
|
798
|
+
ErrorCode.InternalError,
|
|
799
|
+
`Failed to create test run: ${errorMessage}`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
private async getTestRun(args: any) {
|
|
805
|
+
const { test_run_key } = args;
|
|
806
|
+
|
|
807
|
+
try {
|
|
808
|
+
const response = await this.axiosInstance.get(`/rest/atm/1.0/testrun/${test_run_key}`);
|
|
809
|
+
|
|
810
|
+
if (response.status === 200) {
|
|
811
|
+
return {
|
|
812
|
+
content: [
|
|
813
|
+
{
|
|
814
|
+
type: 'text',
|
|
815
|
+
text: JSON.stringify(response.data, null, 2),
|
|
816
|
+
},
|
|
817
|
+
],
|
|
818
|
+
};
|
|
819
|
+
} else {
|
|
820
|
+
throw new Error(`Failed to retrieve test run: ${response.status}`);
|
|
821
|
+
}
|
|
822
|
+
} catch (error) {
|
|
823
|
+
let errorMessage = 'Unknown error';
|
|
824
|
+
if (error instanceof Error && 'response' in error) {
|
|
825
|
+
const axiosError = error as any;
|
|
826
|
+
if (axiosError.response?.status === 404) {
|
|
827
|
+
errorMessage = `Test run ${test_run_key} not found`;
|
|
828
|
+
} else {
|
|
829
|
+
errorMessage = `Status: ${axiosError.response?.status}, Data: ${JSON.stringify(axiosError.response?.data)}`;
|
|
830
|
+
}
|
|
831
|
+
} else if (error instanceof Error) {
|
|
832
|
+
errorMessage = error.message;
|
|
833
|
+
} else {
|
|
834
|
+
errorMessage = String(error);
|
|
835
|
+
}
|
|
836
|
+
throw new McpError(
|
|
837
|
+
ErrorCode.InternalError,
|
|
838
|
+
`Failed to get test run: ${errorMessage}`
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
663
843
|
async run() {
|
|
664
844
|
const transport = new StdioServerTransport();
|
|
665
845
|
await this.server.connect(transport);
|