@azure-devops/mcp 2.5.0-nightly.20260407 → 2.5.0-nightly.20260408
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/dist/tools/test-plans.js +98 -14
- package/dist/tools.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/tools/test-plans.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT License.
|
|
3
|
-
import { SuiteExpand } from "azure-devops-node-api/interfaces/TestPlanInterfaces.js";
|
|
4
3
|
import { z } from "zod";
|
|
4
|
+
import { apiVersion } from "../utils.js";
|
|
5
5
|
const Test_Plan_Tools = {
|
|
6
6
|
create_test_plan: "testplan_create_test_plan",
|
|
7
7
|
create_test_case: "testplan_create_test_case",
|
|
@@ -13,7 +13,7 @@ const Test_Plan_Tools = {
|
|
|
13
13
|
list_test_suites: "testplan_list_test_suites",
|
|
14
14
|
create_test_suite: "testplan_create_test_suite",
|
|
15
15
|
};
|
|
16
|
-
function configureTestPlanTools(server,
|
|
16
|
+
function configureTestPlanTools(server, tokenProvider, connectionProvider, userAgentProvider) {
|
|
17
17
|
server.tool(Test_Plan_Tools.list_test_plans, "Retrieve a paginated list of test plans from an Azure DevOps project. Allows filtering for active plans and toggling detailed information.", {
|
|
18
18
|
project: z.string().describe("The unique identifier (ID or name) of the Azure DevOps project."),
|
|
19
19
|
filterActivePlans: z.boolean().default(true).describe("Filter to include only active test plans. Defaults to true."),
|
|
@@ -21,12 +21,42 @@ function configureTestPlanTools(server, _, connectionProvider) {
|
|
|
21
21
|
continuationToken: z.string().optional().describe("Token to continue fetching test plans from a previous request."),
|
|
22
22
|
}, async ({ project, filterActivePlans, includePlanDetails, continuationToken }) => {
|
|
23
23
|
try {
|
|
24
|
-
const owner = ""; //making owner an empty string untill we can figure out how to get owner id
|
|
25
24
|
const connection = await connectionProvider();
|
|
26
|
-
const
|
|
27
|
-
const
|
|
25
|
+
const accessToken = await tokenProvider();
|
|
26
|
+
const params = new URLSearchParams({ "api-version": apiVersion });
|
|
27
|
+
if (filterActivePlans)
|
|
28
|
+
params.append("filterActivePlans", "true");
|
|
29
|
+
if (includePlanDetails)
|
|
30
|
+
params.append("includePlanDetails", "true");
|
|
31
|
+
if (continuationToken)
|
|
32
|
+
params.append("continuationToken", continuationToken);
|
|
33
|
+
const url = `${connection.serverUrl}/${encodeURIComponent(project)}/_apis/testplan/Plans?${params.toString()}`;
|
|
34
|
+
const headers = {
|
|
35
|
+
Authorization: `Bearer ${accessToken}`,
|
|
36
|
+
};
|
|
37
|
+
const userAgent = userAgentProvider?.();
|
|
38
|
+
if (userAgent) {
|
|
39
|
+
headers["User-Agent"] = userAgent;
|
|
40
|
+
}
|
|
41
|
+
const response = await fetch(url, {
|
|
42
|
+
method: "GET",
|
|
43
|
+
headers,
|
|
44
|
+
});
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
const errorText = await response.text();
|
|
47
|
+
throw new Error(`Failed to list test plans (${response.status}): ${errorText}`);
|
|
48
|
+
}
|
|
49
|
+
const body = await response.json();
|
|
50
|
+
const testPlans = body.value ?? [];
|
|
51
|
+
const nextToken = response.headers.get("x-ms-continuationtoken") ?? undefined;
|
|
52
|
+
const result = {
|
|
53
|
+
testPlans: testPlans,
|
|
54
|
+
};
|
|
55
|
+
if (nextToken) {
|
|
56
|
+
result.continuationToken = nextToken;
|
|
57
|
+
}
|
|
28
58
|
return {
|
|
29
|
-
content: [{ type: "text", text: JSON.stringify(
|
|
59
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
30
60
|
};
|
|
31
61
|
}
|
|
32
62
|
catch (error) {
|
|
@@ -258,13 +288,41 @@ function configureTestPlanTools(server, _, connectionProvider) {
|
|
|
258
288
|
project: z.string().describe("The unique identifier (ID or name) of the Azure DevOps project."),
|
|
259
289
|
planid: z.coerce.number().min(1).describe("The ID of the test plan."),
|
|
260
290
|
suiteid: z.coerce.number().min(1).describe("The ID of the test suite."),
|
|
261
|
-
|
|
291
|
+
continuationToken: z.string().optional().describe("Token to continue fetching test cases from a previous request."),
|
|
292
|
+
}, async ({ project, planid, suiteid, continuationToken }) => {
|
|
262
293
|
try {
|
|
263
294
|
const connection = await connectionProvider();
|
|
264
|
-
const
|
|
265
|
-
const
|
|
295
|
+
const accessToken = await tokenProvider();
|
|
296
|
+
const params = new URLSearchParams({ "api-version": "7.2-preview.3" });
|
|
297
|
+
if (continuationToken)
|
|
298
|
+
params.append("continuationToken", continuationToken);
|
|
299
|
+
const url = `${connection.serverUrl}/${encodeURIComponent(project)}/_apis/testplan/Plans/${planid}/Suites/${suiteid}/TestCase?${params.toString()}`;
|
|
300
|
+
const headers = {
|
|
301
|
+
Authorization: `Bearer ${accessToken}`,
|
|
302
|
+
};
|
|
303
|
+
const userAgent = userAgentProvider?.();
|
|
304
|
+
if (userAgent) {
|
|
305
|
+
headers["User-Agent"] = userAgent;
|
|
306
|
+
}
|
|
307
|
+
const response = await fetch(url, {
|
|
308
|
+
method: "GET",
|
|
309
|
+
headers,
|
|
310
|
+
});
|
|
311
|
+
if (!response.ok) {
|
|
312
|
+
const errorText = await response.text();
|
|
313
|
+
throw new Error(`Failed to list test cases (${response.status}): ${errorText}`);
|
|
314
|
+
}
|
|
315
|
+
const body = await response.json();
|
|
316
|
+
const testcases = body.value ?? [];
|
|
317
|
+
const nextToken = response.headers.get("x-ms-continuationtoken") ?? undefined;
|
|
318
|
+
const result = {
|
|
319
|
+
testCases: testcases,
|
|
320
|
+
};
|
|
321
|
+
if (nextToken) {
|
|
322
|
+
result.continuationToken = nextToken;
|
|
323
|
+
}
|
|
266
324
|
return {
|
|
267
|
-
content: [{ type: "text", text: JSON.stringify(
|
|
325
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
268
326
|
};
|
|
269
327
|
}
|
|
270
328
|
catch (error) {
|
|
@@ -334,9 +392,29 @@ function configureTestPlanTools(server, _, connectionProvider) {
|
|
|
334
392
|
}, async ({ project, planId, continuationToken }) => {
|
|
335
393
|
try {
|
|
336
394
|
const connection = await connectionProvider();
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
|
|
395
|
+
const accessToken = await tokenProvider();
|
|
396
|
+
const params = new URLSearchParams({ "api-version": apiVersion, "expand": "children" });
|
|
397
|
+
if (continuationToken)
|
|
398
|
+
params.append("continuationToken", continuationToken);
|
|
399
|
+
const url = `${connection.serverUrl}/${encodeURIComponent(project)}/_apis/testplan/Plans/${planId}/Suites?${params.toString()}`;
|
|
400
|
+
const headers = {
|
|
401
|
+
Authorization: `Bearer ${accessToken}`,
|
|
402
|
+
};
|
|
403
|
+
const userAgent = userAgentProvider?.();
|
|
404
|
+
if (userAgent) {
|
|
405
|
+
headers["User-Agent"] = userAgent;
|
|
406
|
+
}
|
|
407
|
+
const response = await fetch(url, {
|
|
408
|
+
method: "GET",
|
|
409
|
+
headers,
|
|
410
|
+
});
|
|
411
|
+
if (!response.ok) {
|
|
412
|
+
const errorText = await response.text();
|
|
413
|
+
throw new Error(`Failed to list test suites (${response.status}): ${errorText}`);
|
|
414
|
+
}
|
|
415
|
+
const body = await response.json();
|
|
416
|
+
const testSuites = body.value ?? [];
|
|
417
|
+
const nextToken = response.headers.get("x-ms-continuationtoken") ?? undefined;
|
|
340
418
|
// The API returns a flat list where the root suite is first, followed by all nested suites
|
|
341
419
|
// We need to build a proper hierarchy by creating a map and assembling the tree
|
|
342
420
|
// Create a map of all suites by ID for quick lookup
|
|
@@ -373,7 +451,13 @@ function configureTestPlanTools(server, _, connectionProvider) {
|
|
|
373
451
|
}
|
|
374
452
|
return cleaned;
|
|
375
453
|
};
|
|
376
|
-
const
|
|
454
|
+
const cleanedSuites = roots.map((root) => cleanSuite(root));
|
|
455
|
+
const result = {
|
|
456
|
+
testSuites: cleanedSuites,
|
|
457
|
+
};
|
|
458
|
+
if (nextToken) {
|
|
459
|
+
result.continuationToken = nextToken;
|
|
460
|
+
}
|
|
377
461
|
return {
|
|
378
462
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
379
463
|
};
|
package/dist/tools.js
CHANGED
|
@@ -24,7 +24,7 @@ function configureAllTools(server, tokenProvider, connectionProvider, userAgentP
|
|
|
24
24
|
configureIfDomainEnabled(Domain.REPOSITORIES, () => configureRepoTools(server, tokenProvider, connectionProvider, userAgentProvider));
|
|
25
25
|
configureIfDomainEnabled(Domain.WORK_ITEMS, () => configureWorkItemTools(server, tokenProvider, connectionProvider, userAgentProvider));
|
|
26
26
|
configureIfDomainEnabled(Domain.WIKI, () => configureWikiTools(server, tokenProvider, connectionProvider, userAgentProvider));
|
|
27
|
-
configureIfDomainEnabled(Domain.TEST_PLANS, () => configureTestPlanTools(server, tokenProvider, connectionProvider));
|
|
27
|
+
configureIfDomainEnabled(Domain.TEST_PLANS, () => configureTestPlanTools(server, tokenProvider, connectionProvider, userAgentProvider));
|
|
28
28
|
configureIfDomainEnabled(Domain.SEARCH, () => configureSearchTools(server, tokenProvider, connectionProvider, userAgentProvider));
|
|
29
29
|
configureIfDomainEnabled(Domain.ADVANCED_SECURITY, () => configureAdvSecTools(server, tokenProvider, connectionProvider));
|
|
30
30
|
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const packageVersion = "2.5.0-nightly.
|
|
1
|
+
export const packageVersion = "2.5.0-nightly.20260408";
|