zephyr-scale-mcp-server 0.3.0 → 0.3.2
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 +3 -2
- package/build/index.js +3 -1
- package/build/tool-handlers.js +31 -41
- package/build/tool-schemas.js +15 -1
- package/package.json +2 -1
- package/src/index.ts +3 -1
- package/src/tool-handlers.ts +34 -41
- package/src/tool-schemas.ts +15 -1
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ The server automatically detects your Jira environment and uses the appropriate
|
|
|
68
68
|
- **Jira Cloud**: Uses Zephyr Scale API v2.
|
|
69
69
|
- **Jira Data Center**: Uses Zephyr Scale API v1.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
Some tools are platform-specific. For example, `add_test_cases_to_run` is only available on Cloud, as the Data Center API (v1) does not support modifying test runs after creation.
|
|
72
72
|
|
|
73
73
|
### Resource System
|
|
74
74
|
The server provides access to various resources through URI schemes:
|
|
@@ -88,11 +88,12 @@ The server provides access to various resources through URI schemes:
|
|
|
88
88
|
- `create_test_run`: Create a new test run.
|
|
89
89
|
- `get_test_run`: Get detailed information about a specific test run.
|
|
90
90
|
- `get_test_run_cases`: Get test case keys from a test run.
|
|
91
|
-
- `add_test_cases_to_run`: Add test cases to an existing test run.
|
|
91
|
+
- `add_test_cases_to_run`: Add test cases to an existing test run. *(Cloud only)*
|
|
92
92
|
|
|
93
93
|
### Test Execution & Search
|
|
94
94
|
- `get_test_execution`: Get detailed individual test execution results.
|
|
95
95
|
- `search_test_cases_by_folder`: Search for test cases in a specific folder.
|
|
96
|
+
- `search_test_runs`: Search for test runs by project key and/or folder path.
|
|
96
97
|
|
|
97
98
|
### Organization
|
|
98
99
|
- `create_folder`: Create a new folder in Zephyr Scale.
|
package/build/index.js
CHANGED
|
@@ -14,7 +14,7 @@ class ZephyrServer {
|
|
|
14
14
|
const jiraConfig = createJiraConfig();
|
|
15
15
|
this.server = new Server({
|
|
16
16
|
name: 'zephyr-server',
|
|
17
|
-
version: '0.3.
|
|
17
|
+
version: '0.3.1',
|
|
18
18
|
}, {
|
|
19
19
|
capabilities: {
|
|
20
20
|
tools: {},
|
|
@@ -55,6 +55,8 @@ class ZephyrServer {
|
|
|
55
55
|
return await this.toolHandlers.getTestRunCases(args);
|
|
56
56
|
case 'delete_test_case':
|
|
57
57
|
return await this.toolHandlers.deleteTestCase(args);
|
|
58
|
+
case 'delete_test_run':
|
|
59
|
+
return await this.toolHandlers.deleteTestRun(args);
|
|
58
60
|
case 'create_test_run':
|
|
59
61
|
return await this.toolHandlers.createTestRun(args);
|
|
60
62
|
case 'get_test_run':
|
package/build/tool-handlers.js
CHANGED
|
@@ -273,6 +273,26 @@ export class ZephyrToolHandlers {
|
|
|
273
273
|
throw new McpError(ErrorCode.InternalError, `Failed to delete test case: ${error instanceof Error ? error.message : String(error)}`);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
|
+
async deleteTestRun(args) {
|
|
277
|
+
const { test_run_key } = args;
|
|
278
|
+
try {
|
|
279
|
+
const response = await this.axiosInstance.delete(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}`);
|
|
280
|
+
if (response.status === 204) {
|
|
281
|
+
return {
|
|
282
|
+
content: [{ type: 'text', text: `Test run ${test_run_key} deleted successfully.` }],
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
return {
|
|
287
|
+
content: [{ type: 'text', text: `Failed to delete test run. Status: ${response.status}` }],
|
|
288
|
+
isError: true,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
throw new McpError(ErrorCode.InternalError, `Failed to delete test run: ${error instanceof Error ? error.message : String(error)}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
276
296
|
async createTestRun(args) {
|
|
277
297
|
const { project_key, name, test_case_keys, test_plan_key, folder, planned_start_date, planned_end_date, description, owner, environment, issue_key, issue_links, custom_fields } = args;
|
|
278
298
|
// Build the basic payload
|
|
@@ -557,48 +577,18 @@ export class ZephyrToolHandlers {
|
|
|
557
577
|
}
|
|
558
578
|
async addTestCasesToRun(args) {
|
|
559
579
|
const { test_run_key, test_case_keys } = args;
|
|
580
|
+
if (this.jiraConfig.type === 'datacenter') {
|
|
581
|
+
throw new McpError(ErrorCode.InvalidRequest, 'add_test_cases_to_run is only supported on Zephyr Scale Cloud. The Data Center API (v1) does not provide an endpoint to modify test runs after creation.');
|
|
582
|
+
}
|
|
560
583
|
try {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
.
|
|
568
|
-
|
|
569
|
-
if (newItems.length > 0) {
|
|
570
|
-
let response;
|
|
571
|
-
if (this.jiraConfig.type === 'datacenter') {
|
|
572
|
-
const minimalPayload = {
|
|
573
|
-
items: [...existingItems, ...newItems]
|
|
574
|
-
};
|
|
575
|
-
response = await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}`, minimalPayload);
|
|
576
|
-
}
|
|
577
|
-
else {
|
|
578
|
-
const postPayload = { items: newItems.map(item => item.testCaseKey) };
|
|
579
|
-
response = await this.axiosInstance.post(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}/testcases`, postPayload);
|
|
580
|
-
}
|
|
581
|
-
if (response.status === 200 || response.status === 201 || response.status === 204) {
|
|
582
|
-
return {
|
|
583
|
-
content: [{ type: 'text', text: `Added ${newItems.length} new test cases to test run ${test_run_key}.` }],
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
else {
|
|
588
|
-
return {
|
|
589
|
-
content: [{ type: 'text', text: 'All specified test cases are already in the test run.' }],
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
else {
|
|
594
|
-
// For Cloud, we can just post the new test case keys
|
|
595
|
-
const fullPayload = { items: test_case_keys };
|
|
596
|
-
const response = await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}`, fullPayload);
|
|
597
|
-
if (response.status === 200 || response.status === 204) {
|
|
598
|
-
return {
|
|
599
|
-
content: [{ type: 'text', text: `Successfully updated test cases for test run ${test_run_key}.` }],
|
|
600
|
-
};
|
|
601
|
-
}
|
|
584
|
+
const payload = {
|
|
585
|
+
items: test_case_keys.map(key => ({ testCaseKey: key }))
|
|
586
|
+
};
|
|
587
|
+
const response = await this.axiosInstance.post(`/testcycles/${test_run_key}/testcases`, payload);
|
|
588
|
+
if (response.status === 200 || response.status === 201 || response.status === 204) {
|
|
589
|
+
return {
|
|
590
|
+
content: [{ type: 'text', text: `Added ${test_case_keys.length} test case(s) to test run ${test_run_key}.` }],
|
|
591
|
+
};
|
|
602
592
|
}
|
|
603
593
|
}
|
|
604
594
|
catch (error) {
|
package/build/tool-schemas.js
CHANGED
|
@@ -373,9 +373,23 @@ export const toolSchemas = [
|
|
|
373
373
|
},
|
|
374
374
|
},
|
|
375
375
|
},
|
|
376
|
+
{
|
|
377
|
+
name: 'delete_test_run',
|
|
378
|
+
description: 'Delete a specific test run',
|
|
379
|
+
inputSchema: {
|
|
380
|
+
type: 'object',
|
|
381
|
+
properties: {
|
|
382
|
+
test_run_key: {
|
|
383
|
+
type: 'string',
|
|
384
|
+
description: 'Test run key to delete (e.g., PROJ-R123)',
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
required: ['test_run_key'],
|
|
388
|
+
},
|
|
389
|
+
},
|
|
376
390
|
{
|
|
377
391
|
name: 'add_test_cases_to_run',
|
|
378
|
-
description: 'Add test cases to an existing test run',
|
|
392
|
+
description: 'Add test cases to an existing test run (Cloud only — not supported on Data Center)',
|
|
379
393
|
inputSchema: {
|
|
380
394
|
type: 'object',
|
|
381
395
|
properties: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zephyr-scale-mcp-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
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",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"test": "node test/run-tests.cjs",
|
|
23
23
|
"test:unit": "node test/zephyr-server.test.cjs",
|
|
24
24
|
"test:integration": "node test/integration.test.cjs",
|
|
25
|
+
"report:weekly": "node scripts/weekly-report.cjs",
|
|
25
26
|
"prepublishOnly": "npm run build"
|
|
26
27
|
},
|
|
27
28
|
"keywords": [
|
package/src/index.ts
CHANGED
|
@@ -25,7 +25,7 @@ class ZephyrServer {
|
|
|
25
25
|
this.server = new Server(
|
|
26
26
|
{
|
|
27
27
|
name: 'zephyr-server',
|
|
28
|
-
version: '0.3.
|
|
28
|
+
version: '0.3.1',
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
capabilities: {
|
|
@@ -75,6 +75,8 @@ class ZephyrServer {
|
|
|
75
75
|
return await this.toolHandlers.getTestRunCases(args);
|
|
76
76
|
case 'delete_test_case':
|
|
77
77
|
return await this.toolHandlers.deleteTestCase(args);
|
|
78
|
+
case 'delete_test_run':
|
|
79
|
+
return await this.toolHandlers.deleteTestRun(args);
|
|
78
80
|
case 'create_test_run':
|
|
79
81
|
return await this.toolHandlers.createTestRun(args as any);
|
|
80
82
|
case 'get_test_run':
|
package/src/tool-handlers.ts
CHANGED
|
@@ -301,6 +301,25 @@ export class ZephyrToolHandlers {
|
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
async deleteTestRun(args: any) {
|
|
305
|
+
const { test_run_key } = args;
|
|
306
|
+
try {
|
|
307
|
+
const response = await this.axiosInstance.delete(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}`);
|
|
308
|
+
if (response.status === 204) {
|
|
309
|
+
return {
|
|
310
|
+
content: [{ type: 'text', text: `Test run ${test_run_key} deleted successfully.` }],
|
|
311
|
+
};
|
|
312
|
+
} else {
|
|
313
|
+
return {
|
|
314
|
+
content: [{ type: 'text', text: `Failed to delete test run. Status: ${response.status}` }],
|
|
315
|
+
isError: true,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
throw new McpError(ErrorCode.InternalError, `Failed to delete test run: ${error instanceof Error ? error.message : String(error)}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
304
323
|
async createTestRun(args: TestRunArgs) {
|
|
305
324
|
const {
|
|
306
325
|
project_key,
|
|
@@ -611,49 +630,23 @@ export class ZephyrToolHandlers {
|
|
|
611
630
|
async addTestCasesToRun(args: AddTestCasesToRunArgs) {
|
|
612
631
|
const { test_run_key, test_case_keys } = args;
|
|
613
632
|
|
|
633
|
+
if (this.jiraConfig.type === 'datacenter') {
|
|
634
|
+
throw new McpError(
|
|
635
|
+
ErrorCode.InvalidRequest,
|
|
636
|
+
'add_test_cases_to_run is only supported on Zephyr Scale Cloud. The Data Center API (v1) does not provide an endpoint to modify test runs after creation.'
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
|
|
614
640
|
try {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const existingKeys = new Set(existingItems.map((item: any) => item.testCaseKey));
|
|
620
|
-
|
|
621
|
-
const newItems = test_case_keys
|
|
622
|
-
.filter(key => !existingKeys.has(key))
|
|
623
|
-
.map(key => ({ testCaseKey: key, testResultStatus: 'Not Executed' }));
|
|
624
|
-
|
|
625
|
-
if (newItems.length > 0) {
|
|
626
|
-
let response;
|
|
627
|
-
if (this.jiraConfig.type === 'datacenter') {
|
|
628
|
-
const minimalPayload = {
|
|
629
|
-
items: [...existingItems, ...newItems]
|
|
630
|
-
};
|
|
631
|
-
response = await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}`, minimalPayload);
|
|
632
|
-
} else {
|
|
633
|
-
const postPayload = { items: newItems.map(item => item.testCaseKey) };
|
|
634
|
-
response = await this.axiosInstance.post(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}/testcases`, postPayload);
|
|
635
|
-
}
|
|
641
|
+
const payload = {
|
|
642
|
+
items: test_case_keys.map(key => ({ testCaseKey: key }))
|
|
643
|
+
};
|
|
644
|
+
const response = await this.axiosInstance.post(`/testcycles/${test_run_key}/testcases`, payload);
|
|
636
645
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
}
|
|
642
|
-
} else {
|
|
643
|
-
return {
|
|
644
|
-
content: [{ type: 'text', text: 'All specified test cases are already in the test run.' }],
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
|
-
} else {
|
|
648
|
-
// For Cloud, we can just post the new test case keys
|
|
649
|
-
const fullPayload = { items: test_case_keys };
|
|
650
|
-
const response = await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testrun}/${test_run_key}`, fullPayload);
|
|
651
|
-
|
|
652
|
-
if (response.status === 200 || response.status === 204) {
|
|
653
|
-
return {
|
|
654
|
-
content: [{ type: 'text', text: `Successfully updated test cases for test run ${test_run_key}.` }],
|
|
655
|
-
};
|
|
656
|
-
}
|
|
646
|
+
if (response.status === 200 || response.status === 201 || response.status === 204) {
|
|
647
|
+
return {
|
|
648
|
+
content: [{ type: 'text', text: `Added ${test_case_keys.length} test case(s) to test run ${test_run_key}.` }],
|
|
649
|
+
};
|
|
657
650
|
}
|
|
658
651
|
} catch (error) {
|
|
659
652
|
throw new McpError(ErrorCode.InternalError, `Failed to add test cases: ${error instanceof Error ? error.message : String(error)}`);
|
package/src/tool-schemas.ts
CHANGED
|
@@ -373,9 +373,23 @@ export const toolSchemas = [
|
|
|
373
373
|
},
|
|
374
374
|
},
|
|
375
375
|
},
|
|
376
|
+
{
|
|
377
|
+
name: 'delete_test_run',
|
|
378
|
+
description: 'Delete a specific test run',
|
|
379
|
+
inputSchema: {
|
|
380
|
+
type: 'object',
|
|
381
|
+
properties: {
|
|
382
|
+
test_run_key: {
|
|
383
|
+
type: 'string',
|
|
384
|
+
description: 'Test run key to delete (e.g., PROJ-R123)',
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
required: ['test_run_key'],
|
|
388
|
+
},
|
|
389
|
+
},
|
|
376
390
|
{
|
|
377
391
|
name: 'add_test_cases_to_run',
|
|
378
|
-
description: 'Add test cases to an existing test run',
|
|
392
|
+
description: 'Add test cases to an existing test run (Cloud only — not supported on Data Center)',
|
|
379
393
|
inputSchema: {
|
|
380
394
|
type: 'object',
|
|
381
395
|
properties: {
|