zephyr-enterprise-tools 1.2.2 → 1.2.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/README.md +28 -30
- package/mcp-server.js +21 -0
- package/package.json +1 -1
- package/zephyr-enterprise-tools.js +105 -0
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ Comprehensive tools for Zephyr Enterprise - Release Readiness, Project Health, T
|
|
|
25
25
|
| `test-trends` | Test execution trends over time |
|
|
26
26
|
| `search-tests` | Search test cases by query |
|
|
27
27
|
| `user-activity` | User activity and productivity metrics |
|
|
28
|
+
| `execution-burndown` | Day-by-day execution burndown (remaining vs ideal) |
|
|
28
29
|
|
|
29
30
|
---
|
|
30
31
|
|
|
@@ -72,51 +73,48 @@ Use zephyr-enterprise-tools as an MCP (Model Context Protocol) server with your
|
|
|
72
73
|
| `test_trends` | Get execution trends over time |
|
|
73
74
|
| `search_test_cases` | Search test cases by query |
|
|
74
75
|
| `user_activity` | Get user activity metrics |
|
|
76
|
+
| `execution_burndown` | Day-by-day execution burndown chart data (remaining vs ideal) |
|
|
75
77
|
|
|
76
|
-
###
|
|
78
|
+
### Claude Desktop
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
Edit your `claude_desktop_config.json` file:
|
|
79
81
|
|
|
80
82
|
```json
|
|
81
83
|
{
|
|
82
|
-
"
|
|
83
|
-
"zephyr
|
|
84
|
-
"type": "stdio",
|
|
84
|
+
"mcpServers": {
|
|
85
|
+
"zephyr": {
|
|
85
86
|
"command": "npx",
|
|
86
|
-
"args": [
|
|
87
|
+
"args": [
|
|
88
|
+
"-y",
|
|
89
|
+
"--package",
|
|
90
|
+
"zephyr-enterprise-tools@latest",
|
|
91
|
+
"zephyr-mcp"
|
|
92
|
+
],
|
|
87
93
|
"env": {
|
|
88
|
-
"ZEPHYR_BASE_URL": "
|
|
89
|
-
"ZEPHYR_TOKEN": "
|
|
94
|
+
"ZEPHYR_BASE_URL": "https://your-zephyr.com/flex/services/rest/latest",
|
|
95
|
+
"ZEPHYR_TOKEN": "your-api-token"
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
|
-
}
|
|
93
|
-
"inputs": [
|
|
94
|
-
{
|
|
95
|
-
"id": "zephyr_base_url",
|
|
96
|
-
"type": "promptString",
|
|
97
|
-
"description": "Zephyr Enterprise API Base URL (e.g. https://your-zephyr.com/flex/services/rest/latest)",
|
|
98
|
-
"password": false
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
"id": "zephyr_token",
|
|
102
|
-
"type": "promptString",
|
|
103
|
-
"description": "Zephyr Enterprise API Token",
|
|
104
|
-
"password": true
|
|
105
|
-
}
|
|
106
|
-
]
|
|
98
|
+
}
|
|
107
99
|
}
|
|
108
100
|
```
|
|
109
101
|
|
|
110
|
-
###
|
|
102
|
+
### VS Code with GitHub Copilot
|
|
111
103
|
|
|
112
|
-
|
|
104
|
+
Create or edit `.vscode/mcp.json` in your workspace:
|
|
113
105
|
|
|
114
106
|
```json
|
|
115
107
|
{
|
|
116
|
-
"
|
|
117
|
-
"zephyr
|
|
108
|
+
"servers": {
|
|
109
|
+
"zephyr": {
|
|
110
|
+
"type": "stdio",
|
|
118
111
|
"command": "npx",
|
|
119
|
-
"args": [
|
|
112
|
+
"args": [
|
|
113
|
+
"-y",
|
|
114
|
+
"--package",
|
|
115
|
+
"zephyr-enterprise-tools",
|
|
116
|
+
"zephyr-mcp"
|
|
117
|
+
],
|
|
120
118
|
"env": {
|
|
121
119
|
"ZEPHYR_BASE_URL": "https://your-zephyr.com/flex/services/rest/latest",
|
|
122
120
|
"ZEPHYR_TOKEN": "your-api-token"
|
|
@@ -126,9 +124,9 @@ Add to your `mcp.json` configuration:
|
|
|
126
124
|
}
|
|
127
125
|
```
|
|
128
126
|
|
|
129
|
-
###
|
|
127
|
+
### Cursor
|
|
130
128
|
|
|
131
|
-
|
|
129
|
+
Add to your `mcp.json` configuration:
|
|
132
130
|
|
|
133
131
|
```json
|
|
134
132
|
{
|
package/mcp-server.js
CHANGED
|
@@ -167,6 +167,20 @@ const TOOLS = [
|
|
|
167
167
|
required: ['projectId', 'releaseId'],
|
|
168
168
|
},
|
|
169
169
|
},
|
|
170
|
+
{
|
|
171
|
+
name: 'execution_burndown',
|
|
172
|
+
description: 'Generate a day-by-day execution burndown chart for a release. Returns daily remaining vs ideal counts so an AI or chart tool can visualise test execution progress over time.',
|
|
173
|
+
inputSchema: {
|
|
174
|
+
type: 'object',
|
|
175
|
+
properties: {
|
|
176
|
+
projectId: { type: 'number', description: 'Zephyr project ID' },
|
|
177
|
+
releaseId: { type: 'number', description: 'Zephyr release ID' },
|
|
178
|
+
startDate: { type: 'string', description: 'Burndown start date YYYY-MM-DD (default: earliest execution date)' },
|
|
179
|
+
endDate: { type: 'string', description: 'Burndown end date YYYY-MM-DD (default: today)' },
|
|
180
|
+
},
|
|
181
|
+
required: ['projectId', 'releaseId'],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
170
184
|
{
|
|
171
185
|
name: 'user_trend',
|
|
172
186
|
description: 'Get full audit log activity for a user — every action they performed across the system. Filter by date range and optionally by entity type (project or release).',
|
|
@@ -300,6 +314,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
300
314
|
result = await tools.getUserActivity(projectId, releaseId, { days: args.days || 30 });
|
|
301
315
|
break;
|
|
302
316
|
|
|
317
|
+
case 'execution_burndown':
|
|
318
|
+
result = await tools.getExecutionBurndown(projectId, releaseId, {
|
|
319
|
+
startDate: args.startDate || null,
|
|
320
|
+
endDate: args.endDate || null,
|
|
321
|
+
});
|
|
322
|
+
break;
|
|
323
|
+
|
|
303
324
|
case 'user_trend':
|
|
304
325
|
result = await tools.getUserTrend({
|
|
305
326
|
userName: args.userName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zephyr-enterprise-tools",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Comprehensive Zephyr Enterprise Tools - Release Readiness, Project Health, Test Analytics & More",
|
|
5
5
|
"main": "zephyr-enterprise-tools.js",
|
|
6
6
|
"types": "zephyr-enterprise-tools.d.ts",
|
|
@@ -1286,6 +1286,111 @@ export class QualityGates {
|
|
|
1286
1286
|
};
|
|
1287
1287
|
}
|
|
1288
1288
|
|
|
1289
|
+
// ─── Execution Burndown Chart ────────────────────────────────────────────────
|
|
1290
|
+
|
|
1291
|
+
async getExecutionBurndown(projectId, releaseId, options = {}) {
|
|
1292
|
+
const { startDate = null, endDate = null } = options;
|
|
1293
|
+
|
|
1294
|
+
// Fetch all executions for the release
|
|
1295
|
+
const executionData = await this.GET('/execution', {
|
|
1296
|
+
projectId,
|
|
1297
|
+
releaseId,
|
|
1298
|
+
maxResults: 10000,
|
|
1299
|
+
});
|
|
1300
|
+
const executions = executionData.results || executionData || [];
|
|
1301
|
+
const total = executions.length;
|
|
1302
|
+
|
|
1303
|
+
if (total === 0) {
|
|
1304
|
+
return {
|
|
1305
|
+
tool: 'Execution Burndown',
|
|
1306
|
+
projectId,
|
|
1307
|
+
releaseId,
|
|
1308
|
+
timestamp: new Date().toISOString(),
|
|
1309
|
+
total: 0,
|
|
1310
|
+
message: 'No executions found for this release.',
|
|
1311
|
+
dailyBurndown: [],
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// Determine date range
|
|
1316
|
+
const allDates = executions
|
|
1317
|
+
.map(e => e.lastModifiedOn || e.createDatetime)
|
|
1318
|
+
.filter(Boolean)
|
|
1319
|
+
.map(d => new Date(d).toISOString().split('T')[0]);
|
|
1320
|
+
|
|
1321
|
+
const rangeStart = startDate || allDates.reduce((a, b) => (a < b ? a : b));
|
|
1322
|
+
const rangeEnd = endDate || new Date().toISOString().split('T')[0];
|
|
1323
|
+
|
|
1324
|
+
// Build a map of date → how many tests were executed (status changed from unexecuted) on that day
|
|
1325
|
+
const executedByDate = {};
|
|
1326
|
+
for (const exec of executions) {
|
|
1327
|
+
const rawDate = exec.lastModifiedOn || exec.createDatetime;
|
|
1328
|
+
if (!rawDate) continue;
|
|
1329
|
+
const dateKey = new Date(rawDate).toISOString().split('T')[0];
|
|
1330
|
+
if (dateKey < rangeStart || dateKey > rangeEnd) continue;
|
|
1331
|
+
const status = String(exec.lastTestResult?.executionStatus || exec.status || exec.executionStatus || '0');
|
|
1332
|
+
// Count as "executed" if not unexecuted (status 0)
|
|
1333
|
+
if (status !== '0') {
|
|
1334
|
+
executedByDate[dateKey] = (executedByDate[dateKey] || 0) + 1;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// Build daily burndown series — remaining = total unexecuted tests at end of each day
|
|
1339
|
+
const days = [];
|
|
1340
|
+
let current = new Date(rangeStart);
|
|
1341
|
+
const end = new Date(rangeEnd);
|
|
1342
|
+
let cumulativeExecuted = 0;
|
|
1343
|
+
|
|
1344
|
+
while (current <= end) {
|
|
1345
|
+
const dateKey = current.toISOString().split('T')[0];
|
|
1346
|
+
const executedToday = executedByDate[dateKey] || 0;
|
|
1347
|
+
cumulativeExecuted += executedToday;
|
|
1348
|
+
const remaining = Math.max(0, total - cumulativeExecuted);
|
|
1349
|
+
|
|
1350
|
+
days.push({
|
|
1351
|
+
date: dateKey,
|
|
1352
|
+
executedToday,
|
|
1353
|
+
cumulativeExecuted,
|
|
1354
|
+
remaining,
|
|
1355
|
+
completionPct: Math.round((cumulativeExecuted / total) * 100),
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1358
|
+
current.setDate(current.getDate() + 1);
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
// Ideal burndown line (linear from total → 0)
|
|
1362
|
+
const totalDays = days.length;
|
|
1363
|
+
const idealDailyBurn = totalDays > 1 ? total / (totalDays - 1) : total;
|
|
1364
|
+
const dailyBurndown = days.map((day, i) => ({
|
|
1365
|
+
...day,
|
|
1366
|
+
ideal: Math.max(0, Math.round(total - idealDailyBurn * i)),
|
|
1367
|
+
}));
|
|
1368
|
+
|
|
1369
|
+
const lastDay = dailyBurndown[dailyBurndown.length - 1];
|
|
1370
|
+
const behindBy = lastDay.remaining - lastDay.ideal;
|
|
1371
|
+
|
|
1372
|
+
return {
|
|
1373
|
+
tool: 'Execution Burndown',
|
|
1374
|
+
projectId,
|
|
1375
|
+
releaseId,
|
|
1376
|
+
timestamp: new Date().toISOString(),
|
|
1377
|
+
dateRange: { from: rangeStart, to: rangeEnd },
|
|
1378
|
+
total,
|
|
1379
|
+
summary: {
|
|
1380
|
+
totalExecutions: total,
|
|
1381
|
+
executed: lastDay.cumulativeExecuted,
|
|
1382
|
+
remaining: lastDay.remaining,
|
|
1383
|
+
completionPct: lastDay.completionPct,
|
|
1384
|
+
status: behindBy > 0
|
|
1385
|
+
? `⚠️ Behind ideal by ${behindBy} tests`
|
|
1386
|
+
: behindBy < 0
|
|
1387
|
+
? `✅ Ahead of schedule by ${Math.abs(behindBy)} tests`
|
|
1388
|
+
: '✅ On track',
|
|
1389
|
+
},
|
|
1390
|
+
dailyBurndown,
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1289
1394
|
// ─── User Trend (Audit Logs) ─────────────────────────────────────────────────
|
|
1290
1395
|
|
|
1291
1396
|
async getUserTrend(options = {}) {
|