zephyr-scale-mcp-server 0.4.3 → 0.4.4
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/build/tool-handlers.js +65 -15
- package/build/tool-schemas.js +12 -10
- package/package.json +1 -1
- package/src/tool-handlers.ts +65 -15
- package/src/tool-schemas.ts +12 -10
- package/src/types.ts +2 -1
package/build/tool-handlers.js
CHANGED
|
@@ -108,13 +108,19 @@ export class ZephyrToolHandlers {
|
|
|
108
108
|
if (!test_script)
|
|
109
109
|
return;
|
|
110
110
|
if (test_script.type === 'STEP_BY_STEP' && test_script.steps && test_script.steps.length > 0) {
|
|
111
|
-
const items = test_script.steps.map((step) =>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
const items = test_script.steps.map((step) => {
|
|
112
|
+
// If step is a call-to-test (testCaseKey), use the testCase variant
|
|
113
|
+
if (step.testCaseKey) {
|
|
114
|
+
return { testCase: { testCaseKey: step.testCaseKey } };
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
inline: {
|
|
118
|
+
description: step.description || '',
|
|
119
|
+
testData: step.testData || null,
|
|
120
|
+
expectedResult: step.expectedResult || null,
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
});
|
|
118
124
|
await this.axiosInstance.post(`${this.jiraConfig.apiEndpoints.testcase}/${testKey}/teststeps`, { mode: 'OVERWRITE', items });
|
|
119
125
|
}
|
|
120
126
|
else if (test_script.type === 'BDD' && test_script.text) {
|
|
@@ -213,15 +219,25 @@ export class ZephyrToolHandlers {
|
|
|
213
219
|
const getResponse = await this.axiosInstance.get(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`);
|
|
214
220
|
const tc = getResponse.data;
|
|
215
221
|
// UpdateTestCaseInput requires: id, key, name, priority, project, status
|
|
216
|
-
//
|
|
217
|
-
|
|
222
|
+
// All optional fields must also be re-sent or the API will clear them
|
|
223
|
+
const putPayload = {
|
|
218
224
|
id: tc.id,
|
|
219
225
|
key: test_case_key,
|
|
220
226
|
name,
|
|
221
227
|
status: tc.status,
|
|
222
228
|
priority: tc.priority,
|
|
223
229
|
project: tc.project,
|
|
224
|
-
}
|
|
230
|
+
};
|
|
231
|
+
// Preserve all optional fields to avoid the API clearing them
|
|
232
|
+
for (const field of ['objective', 'precondition', 'estimatedTime', 'component', 'owner', 'folder']) {
|
|
233
|
+
if (tc[field] !== undefined && tc[field] !== null)
|
|
234
|
+
putPayload[field] = tc[field];
|
|
235
|
+
}
|
|
236
|
+
if (Array.isArray(tc.labels) && tc.labels.length > 0)
|
|
237
|
+
putPayload.labels = tc.labels;
|
|
238
|
+
if (tc.customFields && Object.keys(tc.customFields).length > 0)
|
|
239
|
+
putPayload.customFields = tc.customFields;
|
|
240
|
+
await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`, putPayload);
|
|
225
241
|
}
|
|
226
242
|
return {
|
|
227
243
|
content: [{
|
|
@@ -454,9 +470,10 @@ export class ZephyrToolHandlers {
|
|
|
454
470
|
return this.createTestRunDC(args);
|
|
455
471
|
}
|
|
456
472
|
async createTestRunCloud(args) {
|
|
457
|
-
const { project_key, name, test_case_keys, folder, planned_start_date, planned_end_date, description, owner, environment, custom_fields, } = args;
|
|
473
|
+
const { project_key, name, test_case_keys, folder, planned_start_date, planned_end_date, description, owner, environment, custom_fields, issue_links, issue_key, jira_project_version, } = args;
|
|
458
474
|
// Cloud v2 TestCycleInput: projectKey, name, description, plannedStartDate,
|
|
459
|
-
// plannedEndDate, statusName, folderId, ownerId, customFields
|
|
475
|
+
// plannedEndDate, statusName, folderId, ownerId, jiraProjectVersion, customFields
|
|
476
|
+
// Note: environment is NOT a TestCycleInput field on Cloud — it belongs on TestExecutionInput
|
|
460
477
|
const payload = { projectKey: project_key, name };
|
|
461
478
|
if (description)
|
|
462
479
|
payload.description = description;
|
|
@@ -469,6 +486,9 @@ export class ZephyrToolHandlers {
|
|
|
469
486
|
// Cloud v2 TestCycleInput supports ownerId (Jira Account ID)
|
|
470
487
|
if (owner)
|
|
471
488
|
payload.ownerId = owner;
|
|
489
|
+
// Link to a Jira project version/release (integer ID)
|
|
490
|
+
if (jira_project_version)
|
|
491
|
+
payload.jiraProjectVersion = jira_project_version;
|
|
472
492
|
if (folder) {
|
|
473
493
|
const folderId = await resolveFolderIdByPath(this.axiosInstance, project_key, folder, 'TEST_CYCLE');
|
|
474
494
|
if (folderId !== null)
|
|
@@ -483,14 +503,43 @@ export class ZephyrToolHandlers {
|
|
|
483
503
|
// Step 2: add test cases via test executions (Cloud v2 has no /testcycles/{key}/testcases)
|
|
484
504
|
if (test_case_keys && test_case_keys.length > 0) {
|
|
485
505
|
for (const testCaseKey of test_case_keys) {
|
|
486
|
-
|
|
506
|
+
const execPayload = {
|
|
487
507
|
projectKey: project_key,
|
|
488
508
|
testCaseKey,
|
|
489
509
|
testCycleKey: cycleKey,
|
|
490
510
|
statusName: 'Not Executed',
|
|
491
|
-
}
|
|
511
|
+
};
|
|
512
|
+
// environment is set at execution level on Cloud, not cycle level
|
|
513
|
+
if (environment)
|
|
514
|
+
execPayload.environmentName = environment;
|
|
515
|
+
await this.axiosInstance.post('/testexecutions', execPayload);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// Step 3: link Jira issues via POST /testcycles/{key}/links/issues
|
|
519
|
+
// Merge issue_key (single) and issue_links (array) into one list
|
|
520
|
+
const allIssueLinks = [
|
|
521
|
+
...(issue_key ? [issue_key] : []),
|
|
522
|
+
...(issue_links ?? []),
|
|
523
|
+
];
|
|
524
|
+
const linkWarnings = [];
|
|
525
|
+
if (allIssueLinks.length > 0) {
|
|
526
|
+
for (const ik of allIssueLinks) {
|
|
527
|
+
try {
|
|
528
|
+
const issueId = await this.resolveJiraIssueId(ik);
|
|
529
|
+
await this.axiosInstance.post(`${this.jiraConfig.apiEndpoints.testrun}/${cycleKey}/links/issues`, { issueId });
|
|
530
|
+
}
|
|
531
|
+
catch (e) {
|
|
532
|
+
linkWarnings.push(`${ik}: ${this.formatError(e)}`);
|
|
533
|
+
}
|
|
492
534
|
}
|
|
493
535
|
}
|
|
536
|
+
const missingCreds = !process.env.JIRA_USERNAME || !process.env.JIRA_API_TOKEN;
|
|
537
|
+
const credHint = missingCreds && linkWarnings.length > 0
|
|
538
|
+
? '\n💡 Tip: Set JIRA_USERNAME and JIRA_API_TOKEN env vars to enable issue linking on Cloud.'
|
|
539
|
+
: '';
|
|
540
|
+
const warningText = linkWarnings.length > 0
|
|
541
|
+
? `\n⚠️ Some issue links failed:\n${linkWarnings.map(w => ` - ${w}`).join('\n')}${credHint}`
|
|
542
|
+
: '';
|
|
494
543
|
return {
|
|
495
544
|
content: [{
|
|
496
545
|
type: 'text',
|
|
@@ -498,7 +547,8 @@ export class ZephyrToolHandlers {
|
|
|
498
547
|
key: cycleKey,
|
|
499
548
|
name,
|
|
500
549
|
testCaseCount: test_case_keys?.length || 0,
|
|
501
|
-
|
|
550
|
+
linkedIssues: allIssueLinks.length - linkWarnings.length,
|
|
551
|
+
}, null, 2)}${warningText}`,
|
|
502
552
|
}],
|
|
503
553
|
};
|
|
504
554
|
}
|
package/build/tool-schemas.js
CHANGED
|
@@ -74,14 +74,12 @@ export const toolSchemas = [
|
|
|
74
74
|
},
|
|
75
75
|
status: {
|
|
76
76
|
type: 'string',
|
|
77
|
-
description: 'Test case status (optional)',
|
|
78
|
-
enum: ['Draft', 'Approved', 'Deprecated'],
|
|
77
|
+
description: 'Test case status (optional, default: "Draft"). Value must match a status name configured in your Zephyr project (e.g. "Draft", "Approved", "Deprecated"). Note: always overridden to "Draft" on creation.',
|
|
79
78
|
default: 'Draft',
|
|
80
79
|
},
|
|
81
80
|
priority: {
|
|
82
81
|
type: 'string',
|
|
83
|
-
description: 'Test case priority (optional)',
|
|
84
|
-
enum: ['High', 'Normal', 'Low'],
|
|
82
|
+
description: 'Test case priority (optional). Value must match a priority name configured in your Zephyr project (e.g. "High", "Normal", "Low", "Critical"). Use zephyr://testcase/EXISTING-KEY to check your project\'s valid values.',
|
|
85
83
|
},
|
|
86
84
|
precondition: {
|
|
87
85
|
type: 'string',
|
|
@@ -206,7 +204,7 @@ export const toolSchemas = [
|
|
|
206
204
|
properties: {
|
|
207
205
|
test_run_key: {
|
|
208
206
|
type: 'string',
|
|
209
|
-
description: 'Test run key (e.g., PROJ-
|
|
207
|
+
description: 'Test run key (e.g., PROJ-R123)',
|
|
210
208
|
},
|
|
211
209
|
},
|
|
212
210
|
required: ['test_run_key'],
|
|
@@ -271,17 +269,21 @@ export const toolSchemas = [
|
|
|
271
269
|
},
|
|
272
270
|
environment: {
|
|
273
271
|
type: 'string',
|
|
274
|
-
description: 'Test environment (optional)',
|
|
272
|
+
description: 'Test environment name (optional). On Cloud, applied to each test execution (environmentName). On Data Center, set at cycle level.',
|
|
275
273
|
},
|
|
276
274
|
issue_key: {
|
|
277
275
|
type: 'string',
|
|
278
|
-
description: 'Single issue key to link to the test
|
|
276
|
+
description: 'Single Jira issue key to link to the test cycle (e.g. "PROJ-123"). On Cloud, resolved to a numeric ID via Jira REST API — requires JIRA_USERNAME + JIRA_API_TOKEN env vars.',
|
|
279
277
|
},
|
|
280
278
|
issue_links: {
|
|
281
279
|
type: 'array',
|
|
282
|
-
description: 'Array of issue
|
|
280
|
+
description: 'Array of Jira issue keys to link to the test cycle (e.g. ["PROJ-123", "PROJ-456"]). On Cloud, each key is resolved to a numeric ID via Jira REST API — requires JIRA_USERNAME + JIRA_API_TOKEN env vars. Failures are reported as warnings and do not fail the tool call.',
|
|
283
281
|
items: { type: 'string' },
|
|
284
282
|
},
|
|
283
|
+
jira_project_version: {
|
|
284
|
+
type: 'integer',
|
|
285
|
+
description: 'Jira project version/release ID to link this test cycle to (optional, Cloud only — use the numeric version ID).',
|
|
286
|
+
},
|
|
285
287
|
custom_fields: {
|
|
286
288
|
type: 'object',
|
|
287
289
|
description: 'Custom fields object (optional)',
|
|
@@ -316,7 +318,7 @@ export const toolSchemas = [
|
|
|
316
318
|
},
|
|
317
319
|
test_run_keys: {
|
|
318
320
|
type: 'array',
|
|
319
|
-
description: 'Array of test run keys to search in (required for Data Center, optional for Cloud — e.g., ["PROJ-
|
|
321
|
+
description: 'Array of test run keys to search in (required for Data Center, optional for Cloud — e.g., ["PROJ-R152", "PROJ-R161"])',
|
|
320
322
|
items: { type: 'string' },
|
|
321
323
|
minItems: 1
|
|
322
324
|
},
|
|
@@ -395,7 +397,7 @@ export const toolSchemas = [
|
|
|
395
397
|
properties: {
|
|
396
398
|
test_run_key: {
|
|
397
399
|
type: 'string',
|
|
398
|
-
description: 'Test run key (e.g., PROJ-
|
|
400
|
+
description: 'Test run key (e.g., PROJ-R161)',
|
|
399
401
|
},
|
|
400
402
|
test_case_keys: {
|
|
401
403
|
type: 'array',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zephyr-scale-mcp-server",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
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/tool-handlers.ts
CHANGED
|
@@ -124,13 +124,19 @@ export class ZephyrToolHandlers {
|
|
|
124
124
|
if (!test_script) return;
|
|
125
125
|
|
|
126
126
|
if (test_script.type === 'STEP_BY_STEP' && test_script.steps && test_script.steps.length > 0) {
|
|
127
|
-
const items = test_script.steps.map((step: any) =>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
const items = test_script.steps.map((step: any) => {
|
|
128
|
+
// If step is a call-to-test (testCaseKey), use the testCase variant
|
|
129
|
+
if (step.testCaseKey) {
|
|
130
|
+
return { testCase: { testCaseKey: step.testCaseKey } };
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
inline: {
|
|
134
|
+
description: step.description || '',
|
|
135
|
+
testData: step.testData || null,
|
|
136
|
+
expectedResult: step.expectedResult || null,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
});
|
|
134
140
|
await this.axiosInstance.post(
|
|
135
141
|
`${this.jiraConfig.apiEndpoints.testcase}/${testKey}/teststeps`,
|
|
136
142
|
{ mode: 'OVERWRITE', items }
|
|
@@ -234,15 +240,22 @@ export class ZephyrToolHandlers {
|
|
|
234
240
|
const getResponse = await this.axiosInstance.get(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`);
|
|
235
241
|
const tc = getResponse.data;
|
|
236
242
|
// UpdateTestCaseInput requires: id, key, name, priority, project, status
|
|
237
|
-
//
|
|
238
|
-
|
|
243
|
+
// All optional fields must also be re-sent or the API will clear them
|
|
244
|
+
const putPayload: any = {
|
|
239
245
|
id: tc.id,
|
|
240
246
|
key: test_case_key,
|
|
241
247
|
name,
|
|
242
248
|
status: tc.status,
|
|
243
249
|
priority: tc.priority,
|
|
244
250
|
project: tc.project,
|
|
245
|
-
}
|
|
251
|
+
};
|
|
252
|
+
// Preserve all optional fields to avoid the API clearing them
|
|
253
|
+
for (const field of ['objective', 'precondition', 'estimatedTime', 'component', 'owner', 'folder']) {
|
|
254
|
+
if (tc[field] !== undefined && tc[field] !== null) putPayload[field] = tc[field];
|
|
255
|
+
}
|
|
256
|
+
if (Array.isArray(tc.labels) && tc.labels.length > 0) putPayload.labels = tc.labels;
|
|
257
|
+
if (tc.customFields && Object.keys(tc.customFields).length > 0) putPayload.customFields = tc.customFields;
|
|
258
|
+
await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`, putPayload);
|
|
246
259
|
}
|
|
247
260
|
|
|
248
261
|
return {
|
|
@@ -504,11 +517,13 @@ export class ZephyrToolHandlers {
|
|
|
504
517
|
const {
|
|
505
518
|
project_key, name, test_case_keys, folder,
|
|
506
519
|
planned_start_date, planned_end_date, description,
|
|
507
|
-
owner, environment, custom_fields,
|
|
520
|
+
owner, environment, custom_fields, issue_links, issue_key,
|
|
521
|
+
jira_project_version,
|
|
508
522
|
} = args;
|
|
509
523
|
|
|
510
524
|
// Cloud v2 TestCycleInput: projectKey, name, description, plannedStartDate,
|
|
511
|
-
// plannedEndDate, statusName, folderId, ownerId, customFields
|
|
525
|
+
// plannedEndDate, statusName, folderId, ownerId, jiraProjectVersion, customFields
|
|
526
|
+
// Note: environment is NOT a TestCycleInput field on Cloud — it belongs on TestExecutionInput
|
|
512
527
|
const payload: any = { projectKey: project_key, name };
|
|
513
528
|
|
|
514
529
|
if (description) payload.description = description;
|
|
@@ -517,6 +532,8 @@ export class ZephyrToolHandlers {
|
|
|
517
532
|
if (custom_fields) payload.customFields = custom_fields;
|
|
518
533
|
// Cloud v2 TestCycleInput supports ownerId (Jira Account ID)
|
|
519
534
|
if (owner) payload.ownerId = owner;
|
|
535
|
+
// Link to a Jira project version/release (integer ID)
|
|
536
|
+
if (jira_project_version) payload.jiraProjectVersion = jira_project_version;
|
|
520
537
|
if (folder) {
|
|
521
538
|
const folderId = await resolveFolderIdByPath(
|
|
522
539
|
this.axiosInstance, project_key, folder, 'TEST_CYCLE'
|
|
@@ -535,15 +552,47 @@ export class ZephyrToolHandlers {
|
|
|
535
552
|
// Step 2: add test cases via test executions (Cloud v2 has no /testcycles/{key}/testcases)
|
|
536
553
|
if (test_case_keys && test_case_keys.length > 0) {
|
|
537
554
|
for (const testCaseKey of test_case_keys) {
|
|
538
|
-
|
|
555
|
+
const execPayload: any = {
|
|
539
556
|
projectKey: project_key,
|
|
540
557
|
testCaseKey,
|
|
541
558
|
testCycleKey: cycleKey,
|
|
542
559
|
statusName: 'Not Executed',
|
|
543
|
-
}
|
|
560
|
+
};
|
|
561
|
+
// environment is set at execution level on Cloud, not cycle level
|
|
562
|
+
if (environment) execPayload.environmentName = environment;
|
|
563
|
+
await this.axiosInstance.post('/testexecutions', execPayload);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Step 3: link Jira issues via POST /testcycles/{key}/links/issues
|
|
568
|
+
// Merge issue_key (single) and issue_links (array) into one list
|
|
569
|
+
const allIssueLinks = [
|
|
570
|
+
...(issue_key ? [issue_key] : []),
|
|
571
|
+
...(issue_links ?? []),
|
|
572
|
+
];
|
|
573
|
+
const linkWarnings: string[] = [];
|
|
574
|
+
if (allIssueLinks.length > 0) {
|
|
575
|
+
for (const ik of allIssueLinks) {
|
|
576
|
+
try {
|
|
577
|
+
const issueId = await this.resolveJiraIssueId(ik);
|
|
578
|
+
await this.axiosInstance.post(
|
|
579
|
+
`${this.jiraConfig.apiEndpoints.testrun}/${cycleKey}/links/issues`,
|
|
580
|
+
{ issueId }
|
|
581
|
+
);
|
|
582
|
+
} catch (e) {
|
|
583
|
+
linkWarnings.push(`${ik}: ${this.formatError(e)}`);
|
|
584
|
+
}
|
|
544
585
|
}
|
|
545
586
|
}
|
|
546
587
|
|
|
588
|
+
const missingCreds = !process.env.JIRA_USERNAME || !process.env.JIRA_API_TOKEN;
|
|
589
|
+
const credHint = missingCreds && linkWarnings.length > 0
|
|
590
|
+
? '\n💡 Tip: Set JIRA_USERNAME and JIRA_API_TOKEN env vars to enable issue linking on Cloud.'
|
|
591
|
+
: '';
|
|
592
|
+
const warningText = linkWarnings.length > 0
|
|
593
|
+
? `\n⚠️ Some issue links failed:\n${linkWarnings.map(w => ` - ${w}`).join('\n')}${credHint}`
|
|
594
|
+
: '';
|
|
595
|
+
|
|
547
596
|
return {
|
|
548
597
|
content: [{
|
|
549
598
|
type: 'text',
|
|
@@ -551,7 +600,8 @@ export class ZephyrToolHandlers {
|
|
|
551
600
|
key: cycleKey,
|
|
552
601
|
name,
|
|
553
602
|
testCaseCount: test_case_keys?.length || 0,
|
|
554
|
-
|
|
603
|
+
linkedIssues: allIssueLinks.length - linkWarnings.length,
|
|
604
|
+
}, null, 2)}${warningText}`,
|
|
555
605
|
}],
|
|
556
606
|
};
|
|
557
607
|
} catch (error) {
|
package/src/tool-schemas.ts
CHANGED
|
@@ -74,14 +74,12 @@ export const toolSchemas = [
|
|
|
74
74
|
},
|
|
75
75
|
status: {
|
|
76
76
|
type: 'string',
|
|
77
|
-
description: 'Test case status (optional)',
|
|
78
|
-
enum: ['Draft', 'Approved', 'Deprecated'],
|
|
77
|
+
description: 'Test case status (optional, default: "Draft"). Value must match a status name configured in your Zephyr project (e.g. "Draft", "Approved", "Deprecated"). Note: always overridden to "Draft" on creation.',
|
|
79
78
|
default: 'Draft',
|
|
80
79
|
},
|
|
81
80
|
priority: {
|
|
82
81
|
type: 'string',
|
|
83
|
-
description: 'Test case priority (optional)',
|
|
84
|
-
enum: ['High', 'Normal', 'Low'],
|
|
82
|
+
description: 'Test case priority (optional). Value must match a priority name configured in your Zephyr project (e.g. "High", "Normal", "Low", "Critical"). Use zephyr://testcase/EXISTING-KEY to check your project\'s valid values.',
|
|
85
83
|
},
|
|
86
84
|
precondition: {
|
|
87
85
|
type: 'string',
|
|
@@ -206,7 +204,7 @@ export const toolSchemas = [
|
|
|
206
204
|
properties: {
|
|
207
205
|
test_run_key: {
|
|
208
206
|
type: 'string',
|
|
209
|
-
description: 'Test run key (e.g., PROJ-
|
|
207
|
+
description: 'Test run key (e.g., PROJ-R123)',
|
|
210
208
|
},
|
|
211
209
|
},
|
|
212
210
|
required: ['test_run_key'],
|
|
@@ -271,17 +269,21 @@ export const toolSchemas = [
|
|
|
271
269
|
},
|
|
272
270
|
environment: {
|
|
273
271
|
type: 'string',
|
|
274
|
-
description: 'Test environment (optional)',
|
|
272
|
+
description: 'Test environment name (optional). On Cloud, applied to each test execution (environmentName). On Data Center, set at cycle level.',
|
|
275
273
|
},
|
|
276
274
|
issue_key: {
|
|
277
275
|
type: 'string',
|
|
278
|
-
description: 'Single issue key to link to the test
|
|
276
|
+
description: 'Single Jira issue key to link to the test cycle (e.g. "PROJ-123"). On Cloud, resolved to a numeric ID via Jira REST API — requires JIRA_USERNAME + JIRA_API_TOKEN env vars.',
|
|
279
277
|
},
|
|
280
278
|
issue_links: {
|
|
281
279
|
type: 'array',
|
|
282
|
-
description: 'Array of issue
|
|
280
|
+
description: 'Array of Jira issue keys to link to the test cycle (e.g. ["PROJ-123", "PROJ-456"]). On Cloud, each key is resolved to a numeric ID via Jira REST API — requires JIRA_USERNAME + JIRA_API_TOKEN env vars. Failures are reported as warnings and do not fail the tool call.',
|
|
283
281
|
items: { type: 'string' },
|
|
284
282
|
},
|
|
283
|
+
jira_project_version: {
|
|
284
|
+
type: 'integer',
|
|
285
|
+
description: 'Jira project version/release ID to link this test cycle to (optional, Cloud only — use the numeric version ID).',
|
|
286
|
+
},
|
|
285
287
|
custom_fields: {
|
|
286
288
|
type: 'object',
|
|
287
289
|
description: 'Custom fields object (optional)',
|
|
@@ -316,7 +318,7 @@ export const toolSchemas = [
|
|
|
316
318
|
},
|
|
317
319
|
test_run_keys: {
|
|
318
320
|
type: 'array',
|
|
319
|
-
description: 'Array of test run keys to search in (required for Data Center, optional for Cloud — e.g., ["PROJ-
|
|
321
|
+
description: 'Array of test run keys to search in (required for Data Center, optional for Cloud — e.g., ["PROJ-R152", "PROJ-R161"])',
|
|
320
322
|
items: { type: 'string' },
|
|
321
323
|
minItems: 1
|
|
322
324
|
},
|
|
@@ -395,7 +397,7 @@ export const toolSchemas = [
|
|
|
395
397
|
properties: {
|
|
396
398
|
test_run_key: {
|
|
397
399
|
type: 'string',
|
|
398
|
-
description: 'Test run key (e.g., PROJ-
|
|
400
|
+
description: 'Test run key (e.g., PROJ-R161)',
|
|
399
401
|
},
|
|
400
402
|
test_case_keys: {
|
|
401
403
|
type: 'array',
|
package/src/types.ts
CHANGED
|
@@ -64,7 +64,8 @@ export interface TestRunArgs {
|
|
|
64
64
|
planned_end_date?: string;
|
|
65
65
|
description?: string;
|
|
66
66
|
owner?: string;
|
|
67
|
-
environment?: string;
|
|
67
|
+
environment?: string; // Cloud: mapped to environmentName on each TestExecutionInput; DC: cycle-level field
|
|
68
|
+
jira_project_version?: number; // Cloud only: Jira project version/release ID (integer)
|
|
68
69
|
issue_key?: string;
|
|
69
70
|
issue_links?: string[];
|
|
70
71
|
custom_fields?: Record<string, any>;
|