zephyr-scale-mcp-server 0.4.2 → 0.4.3
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 +43 -21
- package/build/tool-handlers.js +43 -12
- package/build/tool-schemas.js +6 -6
- package/package.json +1 -1
- package/src/tool-handlers.ts +42 -12
- package/src/tool-schemas.ts +6 -6
- package/src/types.ts +5 -3
package/README.md
CHANGED
|
@@ -27,7 +27,29 @@ Configure your MCP client with the following structure.
|
|
|
27
27
|
"args": ["zephyr-scale-mcp-server@latest"],
|
|
28
28
|
"env": {
|
|
29
29
|
"ZEPHYR_BASE_URL": "https://your-company.atlassian.net",
|
|
30
|
-
"ZEPHYR_API_KEY": "your-zephyr-api-key"
|
|
30
|
+
"ZEPHYR_API_KEY": "your-zephyr-api-key",
|
|
31
|
+
"JIRA_USERNAME": "your-email@company.com",
|
|
32
|
+
"JIRA_API_TOKEN": "your-jira-api-token"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
> **Note**: `JIRA_USERNAME` and `JIRA_API_TOKEN` are optional but required if you want to use the `issue_links` field when creating test cases. Without them, issue linking will fail with a 401 warning (the test case is still created). Generate a Jira API token at [id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens).
|
|
39
|
+
|
|
40
|
+
**Jira Cloud (EU region):**
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"zephyr-server": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["zephyr-scale-mcp-server@latest"],
|
|
47
|
+
"env": {
|
|
48
|
+
"ZEPHYR_BASE_URL": "https://your-company.atlassian.net",
|
|
49
|
+
"ZEPHYR_API_KEY": "your-zephyr-api-key",
|
|
50
|
+
"JIRA_USERNAME": "your-email@company.com",
|
|
51
|
+
"JIRA_API_TOKEN": "your-jira-api-token",
|
|
52
|
+
"ZEPHYR_API_BASE_URL": "https://eu.api.zephyrscale.smartbear.com/v2"
|
|
31
53
|
}
|
|
32
54
|
}
|
|
33
55
|
}
|
|
@@ -99,18 +121,19 @@ The server provides access to various resources through URI schemes:
|
|
|
99
121
|
|
|
100
122
|
## Usage Examples
|
|
101
123
|
|
|
102
|
-
### Create a BDD Test Case
|
|
124
|
+
### Create a BDD Test Case with Issue Links
|
|
103
125
|
```json
|
|
104
126
|
{
|
|
105
127
|
"project_key": "PROJ",
|
|
106
128
|
"name": "User Authentication",
|
|
107
129
|
"test_script": {
|
|
108
130
|
"type": "BDD",
|
|
109
|
-
"text": "
|
|
110
|
-
}
|
|
131
|
+
"text": "Given a user with valid credentials\nWhen the user attempts to log in\nThen the user should be authenticated successfully"
|
|
132
|
+
},
|
|
133
|
+
"issue_links": ["PROJ-123", "PROJ-456"]
|
|
111
134
|
}
|
|
112
135
|
```
|
|
113
|
-
**Note**:
|
|
136
|
+
**Note**: `issue_links` requires `JIRA_USERNAME` and `JIRA_API_TOKEN` to be set (Cloud only). Link failures are reported as warnings — the test case is still created.
|
|
114
137
|
|
|
115
138
|
### Use a Live Test Case as a Template
|
|
116
139
|
1. Fetch an existing test case: `zephyr://testcase/PROJ-T123`
|
|
@@ -139,26 +162,25 @@ The server provides access to various resources through URI schemes:
|
|
|
139
162
|
## Authentication
|
|
140
163
|
|
|
141
164
|
### Jira Cloud Configuration
|
|
142
|
-
- `ZEPHYR_BASE_URL`: `https://your-company.atlassian.net`
|
|
143
|
-
- `ZEPHYR_API_KEY`: Your Zephyr Scale API key (JWT). Generate it in Jira by clicking your profile picture (bottom left) → **Zephyr API keys**.
|
|
144
165
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
166
|
+
| Variable | Required | Description |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `ZEPHYR_BASE_URL` | ✅ | Your Jira Cloud URL, e.g. `https://your-company.atlassian.net` |
|
|
169
|
+
| `ZEPHYR_API_KEY` | ✅ | Zephyr Scale API key (JWT). Generate in Jira: profile picture (bottom left) → **Zephyr API keys** |
|
|
170
|
+
| `JIRA_USERNAME` | ⚠️ Optional* | Your Jira account email address |
|
|
171
|
+
| `JIRA_API_TOKEN` | ⚠️ Optional* | Jira API token. Generate at [id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens) |
|
|
172
|
+
| `ZEPHYR_API_BASE_URL` | Optional | Override the Zephyr API base URL (e.g. for EU: `https://eu.api.zephyrscale.smartbear.com/v2`). Defaults to US endpoint. |
|
|
173
|
+
| `JIRA_TYPE` | Optional | Force `"cloud"` or `"datacenter"` — overrides auto-detection |
|
|
148
174
|
|
|
149
|
-
|
|
150
|
-
```json
|
|
151
|
-
"env": {
|
|
152
|
-
"ZEPHYR_BASE_URL": "https://your-company.atlassian.net",
|
|
153
|
-
"ZEPHYR_API_KEY": "your-zephyr-api-token",
|
|
154
|
-
"ZEPHYR_API_BASE_URL": "https://eu.api.zephyrscale.smartbear.com/v2"
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
If `ZEPHYR_API_BASE_URL` is not set, the US URL is used. Omit this variable for US instances.
|
|
175
|
+
> **\* `JIRA_USERNAME` + `JIRA_API_TOKEN`**: Required only for the `issue_links` feature on Cloud. The Zephyr API key cannot authenticate against the Jira REST API, so a separate Jira credential is needed to resolve issue keys to numeric IDs. Without these, `issue_links` will fail with a 401 warning — the test case is still created successfully.
|
|
158
176
|
|
|
159
177
|
### Jira Data Center Configuration
|
|
160
|
-
|
|
161
|
-
|
|
178
|
+
|
|
179
|
+
| Variable | Required | Description |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| `ZEPHYR_BASE_URL` | ✅ | Your Jira server URL, e.g. `https://your-jira-server.com` |
|
|
182
|
+
| `ZEPHYR_API_KEY` | ✅ | Zephyr Scale API token from your Jira profile settings |
|
|
183
|
+
| `JIRA_TYPE` | Optional | Set to `"datacenter"` to override auto-detection |
|
|
162
184
|
|
|
163
185
|
### Automatic Detection
|
|
164
186
|
The server automatically detects your Jira type based on `ZEPHYR_BASE_URL` — URLs containing `.atlassian.net` are treated as Cloud, everything else as Data Center. Override with `JIRA_TYPE="cloud"` or `JIRA_TYPE="datacenter"`.
|
package/build/tool-handlers.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
1
2
|
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
2
3
|
import { convertToGherkin, resolveFolderIdByPath } from './utils.js';
|
|
3
4
|
export class ZephyrToolHandlers {
|
|
@@ -34,7 +35,7 @@ export class ZephyrToolHandlers {
|
|
|
34
35
|
return this.createTestCaseDC(args);
|
|
35
36
|
}
|
|
36
37
|
async createTestCaseCloud(args) {
|
|
37
|
-
const { project_key, name, test_script, folder, priority, precondition, objective, estimated_time, labels, custom_fields, issue_links, } = args;
|
|
38
|
+
const { project_key, name, test_script, folder, priority, precondition, objective, estimated_time, labels, custom_fields, issue_links, owner_id, component_id, } = args;
|
|
38
39
|
const payload = { projectKey: project_key, name };
|
|
39
40
|
// Cloud v2 uses statusName/priorityName (strings), folderId (integer)
|
|
40
41
|
payload.statusName = 'Draft';
|
|
@@ -50,6 +51,11 @@ export class ZephyrToolHandlers {
|
|
|
50
51
|
payload.labels = labels;
|
|
51
52
|
if (custom_fields)
|
|
52
53
|
payload.customFields = custom_fields;
|
|
54
|
+
// Cloud v2 uses ownerId (Jira Account ID) and componentId (integer)
|
|
55
|
+
if (owner_id)
|
|
56
|
+
payload.ownerId = owner_id;
|
|
57
|
+
if (component_id)
|
|
58
|
+
payload.componentId = component_id;
|
|
53
59
|
// Resolve folder path → folderId
|
|
54
60
|
if (folder) {
|
|
55
61
|
const folderId = await resolveFolderIdByPath(this.axiosInstance, project_key, folder, 'TEST_CASE');
|
|
@@ -80,8 +86,12 @@ export class ZephyrToolHandlers {
|
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
}
|
|
89
|
+
const missingCreds = !process.env.JIRA_USERNAME || !process.env.JIRA_API_TOKEN;
|
|
90
|
+
const credHint = missingCreds
|
|
91
|
+
? '\n💡 Tip: Set JIRA_USERNAME and JIRA_API_TOKEN env vars to enable issue linking on Cloud.'
|
|
92
|
+
: '';
|
|
83
93
|
const warningText = linkWarnings.length > 0
|
|
84
|
-
? `\n⚠️ Some issue links failed:\n${linkWarnings.map(w => ` - ${w}`).join('\n')}`
|
|
94
|
+
? `\n⚠️ Some issue links failed:\n${linkWarnings.map(w => ` - ${w}`).join('\n')}${credHint}`
|
|
85
95
|
: '';
|
|
86
96
|
return {
|
|
87
97
|
content: [{
|
|
@@ -202,12 +212,15 @@ export class ZephyrToolHandlers {
|
|
|
202
212
|
if (typeof name === 'string' && name.trim().length > 0) {
|
|
203
213
|
const getResponse = await this.axiosInstance.get(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`);
|
|
204
214
|
const tc = getResponse.data;
|
|
205
|
-
|
|
215
|
+
// UpdateTestCaseInput requires: id, key, name, priority, project, status
|
|
216
|
+
// tc.project is a ProjectLink { id, self } — pass it back as-is
|
|
206
217
|
await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`, {
|
|
207
|
-
|
|
218
|
+
id: tc.id,
|
|
219
|
+
key: test_case_key,
|
|
208
220
|
name,
|
|
209
221
|
status: tc.status,
|
|
210
222
|
priority: tc.priority,
|
|
223
|
+
project: tc.project,
|
|
211
224
|
});
|
|
212
225
|
}
|
|
213
226
|
return {
|
|
@@ -289,8 +302,7 @@ export class ZephyrToolHandlers {
|
|
|
289
302
|
async createFolderCloud(args) {
|
|
290
303
|
const { project_key, name: folderPath, folder_type = 'TEST_CASE' } = args;
|
|
291
304
|
// Cloud v2 uses folderType (not type) and parentId integer
|
|
292
|
-
|
|
293
|
-
const cloudFolderType = folder_type === 'TEST_RUN' ? 'TEST_CYCLE' : folder_type;
|
|
305
|
+
const cloudFolderType = folder_type;
|
|
294
306
|
const segments = folderPath.replace(/^\/+|\/+$/g, '').split('/').filter(Boolean);
|
|
295
307
|
if (segments.length === 0) {
|
|
296
308
|
throw new McpError(ErrorCode.InvalidParams, 'folder name/path cannot be empty');
|
|
@@ -454,7 +466,9 @@ export class ZephyrToolHandlers {
|
|
|
454
466
|
payload.plannedEndDate = planned_end_date;
|
|
455
467
|
if (custom_fields)
|
|
456
468
|
payload.customFields = custom_fields;
|
|
457
|
-
//
|
|
469
|
+
// Cloud v2 TestCycleInput supports ownerId (Jira Account ID)
|
|
470
|
+
if (owner)
|
|
471
|
+
payload.ownerId = owner;
|
|
458
472
|
if (folder) {
|
|
459
473
|
const folderId = await resolveFolderIdByPath(this.axiosInstance, project_key, folder, 'TEST_CYCLE');
|
|
460
474
|
if (folderId !== null)
|
|
@@ -694,7 +708,7 @@ export class ZephyrToolHandlers {
|
|
|
694
708
|
text: `✅ Found ${testRuns.length} test run(s):\n${JSON.stringify({
|
|
695
709
|
totalCount: testRuns.length,
|
|
696
710
|
testRuns: testRuns.map((tr) => ({
|
|
697
|
-
key: tr.key, name: tr.name, status: tr.status?.
|
|
711
|
+
key: tr.key, name: tr.name, status: tr.status?.id, folder: tr.folder?.name,
|
|
698
712
|
})),
|
|
699
713
|
}, null, 2)}`,
|
|
700
714
|
}],
|
|
@@ -769,11 +783,28 @@ export class ZephyrToolHandlers {
|
|
|
769
783
|
}
|
|
770
784
|
}
|
|
771
785
|
async resolveJiraIssueId(issueKey) {
|
|
772
|
-
// The Zephyr API key is
|
|
773
|
-
//
|
|
774
|
-
|
|
786
|
+
// The Zephyr API key is NOT valid for the Jira REST API — Jira Cloud requires
|
|
787
|
+
// Basic Auth: base64(email:api_token) via JIRA_USERNAME + JIRA_API_TOKEN env vars.
|
|
788
|
+
const username = process.env.JIRA_USERNAME;
|
|
789
|
+
const apiToken = process.env.JIRA_API_TOKEN;
|
|
775
790
|
const url = `${this.jiraConfig.jiraBaseUrl}/rest/api/3/issue/${issueKey}?fields=id`;
|
|
776
|
-
|
|
791
|
+
let response;
|
|
792
|
+
if (username && apiToken) {
|
|
793
|
+
// Jira Cloud Basic Auth
|
|
794
|
+
response = await axios.get(url, {
|
|
795
|
+
headers: { 'Accept': 'application/json' },
|
|
796
|
+
auth: { username, password: apiToken },
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
else {
|
|
800
|
+
// Fallback: try Bearer token (works for Data Center with PAT)
|
|
801
|
+
response = await axios.get(url, {
|
|
802
|
+
headers: {
|
|
803
|
+
'Accept': 'application/json',
|
|
804
|
+
'Authorization': `Bearer ${process.env.ZEPHYR_API_KEY}`,
|
|
805
|
+
},
|
|
806
|
+
});
|
|
807
|
+
}
|
|
777
808
|
const id = parseInt(response.data.id, 10);
|
|
778
809
|
if (!id || isNaN(id)) {
|
|
779
810
|
throw new Error(`Could not resolve numeric ID for Jira issue "${issueKey}"`);
|
package/build/tool-schemas.js
CHANGED
|
@@ -91,13 +91,13 @@ export const toolSchemas = [
|
|
|
91
91
|
type: 'string',
|
|
92
92
|
description: 'Test objective (optional)',
|
|
93
93
|
},
|
|
94
|
-
|
|
95
|
-
type: '
|
|
96
|
-
description: '
|
|
94
|
+
component_id: {
|
|
95
|
+
type: 'integer',
|
|
96
|
+
description: 'Jira component ID (optional, Cloud only — use the numeric component ID, not the name)',
|
|
97
97
|
},
|
|
98
|
-
|
|
98
|
+
owner_id: {
|
|
99
99
|
type: 'string',
|
|
100
|
-
description: 'Test case owner (optional)',
|
|
100
|
+
description: 'Test case owner Jira Account ID (optional, Cloud only — e.g. "5b10a2844c20165700ede21g")',
|
|
101
101
|
},
|
|
102
102
|
estimated_time: {
|
|
103
103
|
type: 'number',
|
|
@@ -191,7 +191,7 @@ export const toolSchemas = [
|
|
|
191
191
|
folder_type: {
|
|
192
192
|
type: 'string',
|
|
193
193
|
description: 'Type of folder',
|
|
194
|
-
enum: ['TEST_CASE', 'TEST_PLAN', '
|
|
194
|
+
enum: ['TEST_CASE', 'TEST_PLAN', 'TEST_CYCLE'],
|
|
195
195
|
default: 'TEST_CASE',
|
|
196
196
|
},
|
|
197
197
|
},
|
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.3",
|
|
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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
+
import axios from 'axios';
|
|
2
3
|
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
3
4
|
import {
|
|
4
5
|
TestCaseArgs,
|
|
@@ -47,6 +48,7 @@ export class ZephyrToolHandlers {
|
|
|
47
48
|
const {
|
|
48
49
|
project_key, name, test_script, folder, priority, precondition,
|
|
49
50
|
objective, estimated_time, labels, custom_fields, issue_links,
|
|
51
|
+
owner_id, component_id,
|
|
50
52
|
} = args;
|
|
51
53
|
|
|
52
54
|
const payload: any = { projectKey: project_key, name };
|
|
@@ -58,6 +60,9 @@ export class ZephyrToolHandlers {
|
|
|
58
60
|
if (estimated_time) payload.estimatedTime = estimated_time;
|
|
59
61
|
if (labels && labels.length > 0) payload.labels = labels;
|
|
60
62
|
if (custom_fields) payload.customFields = custom_fields;
|
|
63
|
+
// Cloud v2 uses ownerId (Jira Account ID) and componentId (integer)
|
|
64
|
+
if (owner_id) payload.ownerId = owner_id;
|
|
65
|
+
if (component_id) payload.componentId = component_id;
|
|
61
66
|
|
|
62
67
|
// Resolve folder path → folderId
|
|
63
68
|
if (folder) {
|
|
@@ -96,8 +101,12 @@ export class ZephyrToolHandlers {
|
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
103
|
|
|
104
|
+
const missingCreds = !process.env.JIRA_USERNAME || !process.env.JIRA_API_TOKEN;
|
|
105
|
+
const credHint = missingCreds
|
|
106
|
+
? '\n💡 Tip: Set JIRA_USERNAME and JIRA_API_TOKEN env vars to enable issue linking on Cloud.'
|
|
107
|
+
: '';
|
|
99
108
|
const warningText = linkWarnings.length > 0
|
|
100
|
-
? `\n⚠️ Some issue links failed:\n${linkWarnings.map(w => ` - ${w}`).join('\n')}`
|
|
109
|
+
? `\n⚠️ Some issue links failed:\n${linkWarnings.map(w => ` - ${w}`).join('\n')}${credHint}`
|
|
101
110
|
: '';
|
|
102
111
|
|
|
103
112
|
return {
|
|
@@ -224,12 +233,15 @@ export class ZephyrToolHandlers {
|
|
|
224
233
|
if (typeof name === 'string' && name.trim().length > 0) {
|
|
225
234
|
const getResponse = await this.axiosInstance.get(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`);
|
|
226
235
|
const tc = getResponse.data;
|
|
227
|
-
|
|
236
|
+
// UpdateTestCaseInput requires: id, key, name, priority, project, status
|
|
237
|
+
// tc.project is a ProjectLink { id, self } — pass it back as-is
|
|
228
238
|
await this.axiosInstance.put(`${this.jiraConfig.apiEndpoints.testcase}/${test_case_key}`, {
|
|
229
|
-
|
|
239
|
+
id: tc.id,
|
|
240
|
+
key: test_case_key,
|
|
230
241
|
name,
|
|
231
242
|
status: tc.status,
|
|
232
243
|
priority: tc.priority,
|
|
244
|
+
project: tc.project,
|
|
233
245
|
});
|
|
234
246
|
}
|
|
235
247
|
|
|
@@ -318,8 +330,7 @@ export class ZephyrToolHandlers {
|
|
|
318
330
|
const { project_key, name: folderPath, folder_type = 'TEST_CASE' } = args;
|
|
319
331
|
|
|
320
332
|
// Cloud v2 uses folderType (not type) and parentId integer
|
|
321
|
-
|
|
322
|
-
const cloudFolderType = folder_type === 'TEST_RUN' ? 'TEST_CYCLE' : folder_type;
|
|
333
|
+
const cloudFolderType = folder_type;
|
|
323
334
|
|
|
324
335
|
const segments = folderPath.replace(/^\/+|\/+$/g, '').split('/').filter(Boolean);
|
|
325
336
|
if (segments.length === 0) {
|
|
@@ -504,8 +515,8 @@ export class ZephyrToolHandlers {
|
|
|
504
515
|
if (planned_start_date) payload.plannedStartDate = planned_start_date;
|
|
505
516
|
if (planned_end_date) payload.plannedEndDate = planned_end_date;
|
|
506
517
|
if (custom_fields) payload.customFields = custom_fields;
|
|
507
|
-
|
|
508
|
-
|
|
518
|
+
// Cloud v2 TestCycleInput supports ownerId (Jira Account ID)
|
|
519
|
+
if (owner) payload.ownerId = owner;
|
|
509
520
|
if (folder) {
|
|
510
521
|
const folderId = await resolveFolderIdByPath(
|
|
511
522
|
this.axiosInstance, project_key, folder, 'TEST_CYCLE'
|
|
@@ -766,7 +777,7 @@ export class ZephyrToolHandlers {
|
|
|
766
777
|
text: `✅ Found ${testRuns.length} test run(s):\n${JSON.stringify({
|
|
767
778
|
totalCount: testRuns.length,
|
|
768
779
|
testRuns: testRuns.map((tr: any) => ({
|
|
769
|
-
key: tr.key, name: tr.name, status: tr.status?.
|
|
780
|
+
key: tr.key, name: tr.name, status: tr.status?.id, folder: tr.folder?.name,
|
|
770
781
|
})),
|
|
771
782
|
}, null, 2)}`,
|
|
772
783
|
}],
|
|
@@ -846,11 +857,30 @@ export class ZephyrToolHandlers {
|
|
|
846
857
|
}
|
|
847
858
|
|
|
848
859
|
private async resolveJiraIssueId(issueKey: string): Promise<number> {
|
|
849
|
-
// The Zephyr API key is
|
|
850
|
-
//
|
|
851
|
-
|
|
860
|
+
// The Zephyr API key is NOT valid for the Jira REST API — Jira Cloud requires
|
|
861
|
+
// Basic Auth: base64(email:api_token) via JIRA_USERNAME + JIRA_API_TOKEN env vars.
|
|
862
|
+
const username = process.env.JIRA_USERNAME;
|
|
863
|
+
const apiToken = process.env.JIRA_API_TOKEN;
|
|
864
|
+
|
|
852
865
|
const url = `${this.jiraConfig.jiraBaseUrl}/rest/api/3/issue/${issueKey}?fields=id`;
|
|
853
|
-
|
|
866
|
+
|
|
867
|
+
let response;
|
|
868
|
+
if (username && apiToken) {
|
|
869
|
+
// Jira Cloud Basic Auth
|
|
870
|
+
response = await axios.get(url, {
|
|
871
|
+
headers: { 'Accept': 'application/json' },
|
|
872
|
+
auth: { username, password: apiToken },
|
|
873
|
+
});
|
|
874
|
+
} else {
|
|
875
|
+
// Fallback: try Bearer token (works for Data Center with PAT)
|
|
876
|
+
response = await axios.get(url, {
|
|
877
|
+
headers: {
|
|
878
|
+
'Accept': 'application/json',
|
|
879
|
+
'Authorization': `Bearer ${process.env.ZEPHYR_API_KEY}`,
|
|
880
|
+
},
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
|
|
854
884
|
const id = parseInt(response.data.id, 10);
|
|
855
885
|
if (!id || isNaN(id)) {
|
|
856
886
|
throw new Error(`Could not resolve numeric ID for Jira issue "${issueKey}"`);
|
package/src/tool-schemas.ts
CHANGED
|
@@ -91,13 +91,13 @@ export const toolSchemas = [
|
|
|
91
91
|
type: 'string',
|
|
92
92
|
description: 'Test objective (optional)',
|
|
93
93
|
},
|
|
94
|
-
|
|
95
|
-
type: '
|
|
96
|
-
description: '
|
|
94
|
+
component_id: {
|
|
95
|
+
type: 'integer',
|
|
96
|
+
description: 'Jira component ID (optional, Cloud only — use the numeric component ID, not the name)',
|
|
97
97
|
},
|
|
98
|
-
|
|
98
|
+
owner_id: {
|
|
99
99
|
type: 'string',
|
|
100
|
-
description: 'Test case owner (optional)',
|
|
100
|
+
description: 'Test case owner Jira Account ID (optional, Cloud only — e.g. "5b10a2844c20165700ede21g")',
|
|
101
101
|
},
|
|
102
102
|
estimated_time: {
|
|
103
103
|
type: 'number',
|
|
@@ -191,7 +191,7 @@ export const toolSchemas = [
|
|
|
191
191
|
folder_type: {
|
|
192
192
|
type: 'string',
|
|
193
193
|
description: 'Type of folder',
|
|
194
|
-
enum: ['TEST_CASE', 'TEST_PLAN', '
|
|
194
|
+
enum: ['TEST_CASE', 'TEST_PLAN', 'TEST_CYCLE'],
|
|
195
195
|
default: 'TEST_CASE',
|
|
196
196
|
},
|
|
197
197
|
},
|
package/src/types.ts
CHANGED
|
@@ -31,8 +31,10 @@ export interface TestCaseArgs {
|
|
|
31
31
|
priority?: 'High' | 'Normal' | 'Low';
|
|
32
32
|
precondition?: string;
|
|
33
33
|
objective?: string;
|
|
34
|
-
component?: string;
|
|
35
|
-
owner?: string;
|
|
34
|
+
component?: string; // Data Center: component name
|
|
35
|
+
owner?: string; // Data Center: owner name
|
|
36
|
+
component_id?: number; // Cloud: Jira component ID (integer)
|
|
37
|
+
owner_id?: string; // Cloud: Jira Account ID
|
|
36
38
|
estimated_time?: number;
|
|
37
39
|
labels?: string[];
|
|
38
40
|
issue_links?: string[];
|
|
@@ -49,7 +51,7 @@ export interface UpdateBddArgs {
|
|
|
49
51
|
export interface FolderArgs {
|
|
50
52
|
project_key: string;
|
|
51
53
|
name: string; // Full folder path including parent folders (e.g., "/folder/subfolder")
|
|
52
|
-
folder_type?: 'TEST_CASE' | 'TEST_PLAN' | '
|
|
54
|
+
folder_type?: 'TEST_CASE' | 'TEST_PLAN' | 'TEST_CYCLE';
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
export interface TestRunArgs {
|