@achieveai/azuredevops-mcp 1.3.4 → 1.3.6
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/Services/WorkItemService.js +11 -8
- package/dist/Services/WorkItemService.js.map +1 -1
- package/dist/Tools/BoardsSprintsTools.js +13 -4
- package/dist/Tools/BoardsSprintsTools.js.map +1 -1
- package/dist/Tools/ProjectTools.js +2 -2
- package/dist/Tools/ProjectTools.js.map +1 -1
- package/dist/Tools/WorkItemTools.js +5 -2
- package/dist/Tools/WorkItemTools.js.map +1 -1
- package/dist/index.js +91 -58
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17,7 +17,39 @@ const WikiTools_1 = require("./Tools/WikiTools");
|
|
|
17
17
|
const zod_1 = require("zod");
|
|
18
18
|
const Common_1 = require("./Interfaces/Common");
|
|
19
19
|
/** Wrap a value so string-encoded JSON arrays are auto-parsed (some MCP clients send arrays as strings). */
|
|
20
|
-
const coerceArray = (val) =>
|
|
20
|
+
const coerceArray = (val) => {
|
|
21
|
+
if (typeof val !== 'string')
|
|
22
|
+
return val;
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(val);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new Error(`Expected a JSON array (e.g. [1, 2, 3]) but received: "${val.length > 50 ? val.slice(0, 50) + '...' : val}"`);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Strip common prefixes/symbols from ID values so LLMs can pass
|
|
32
|
+
* "123", "#123", "WI#123", "PR 456", "BUILD#789", etc.
|
|
33
|
+
* Returns a number or NaN (which z.number() will reject with a clear error).
|
|
34
|
+
*/
|
|
35
|
+
const coerceId = (val) => {
|
|
36
|
+
if (typeof val === 'number')
|
|
37
|
+
return val;
|
|
38
|
+
if (typeof val !== 'string')
|
|
39
|
+
return NaN;
|
|
40
|
+
// Strip known prefixes: WI#, PR#, BUILD#, leading #, or any "Word " / "Word#" prefix
|
|
41
|
+
const cleaned = val.trim().replace(/^(?:[A-Za-z]+[#\s])?#?/, '');
|
|
42
|
+
if (cleaned === '')
|
|
43
|
+
return NaN;
|
|
44
|
+
const num = Number(cleaned);
|
|
45
|
+
return Number.isSafeInteger(num) && num > 0 ? num : NaN;
|
|
46
|
+
};
|
|
47
|
+
/** Zod schema for an ID parameter — accepts numbers and common LLM string formats like "#123", "WI#123", "PR 456" */
|
|
48
|
+
const zId = () => zod_1.z.union([zod_1.z.number(), zod_1.z.string()]).transform(coerceId).pipe(zod_1.z.number().int().min(1));
|
|
49
|
+
/** Zod schema for an optional ID parameter */
|
|
50
|
+
const zIdOptional = () => zod_1.z.union([zod_1.z.number(), zod_1.z.string()]).transform(coerceId).pipe(zod_1.z.number().int().min(1)).optional();
|
|
51
|
+
/** Zod schema for an array of IDs */
|
|
52
|
+
const zIdArray = () => zod_1.z.preprocess(coerceArray, zod_1.z.array(zod_1.z.union([zod_1.z.number(), zod_1.z.string()]).transform(coerceId).pipe(zod_1.z.number().int().min(1))));
|
|
21
53
|
const EntraAuthHandler_1 = require("./Services/EntraAuthHandler");
|
|
22
54
|
async function main() {
|
|
23
55
|
try {
|
|
@@ -71,7 +103,7 @@ async function main() {
|
|
|
71
103
|
};
|
|
72
104
|
});
|
|
73
105
|
allowedTools.has("getWorkItemById") && server.tool("getWorkItemById", "Get a specific work item by ID with summary and detailed view", {
|
|
74
|
-
id:
|
|
106
|
+
id: zId().describe("Work item ID")
|
|
75
107
|
}, async (params, extra) => {
|
|
76
108
|
const result = await workItemTools.getWorkItemById({ id: params.id });
|
|
77
109
|
return {
|
|
@@ -134,7 +166,7 @@ async function main() {
|
|
|
134
166
|
};
|
|
135
167
|
});
|
|
136
168
|
allowedTools.has("updateWorkItem") && server.tool("updateWorkItem", "Update an existing work item", {
|
|
137
|
-
id:
|
|
169
|
+
id: zId().describe("ID of the work item to update"),
|
|
138
170
|
fields: zod_1.z.record(zod_1.z.any()).describe("Fields to update on the work item")
|
|
139
171
|
}, async (params, extra) => {
|
|
140
172
|
const result = await workItemTools.updateWorkItem(params);
|
|
@@ -146,9 +178,10 @@ async function main() {
|
|
|
146
178
|
};
|
|
147
179
|
});
|
|
148
180
|
allowedTools.has("getWorkItemComments") && server.tool("getWorkItemComments", "Get comments on a work item", {
|
|
149
|
-
id:
|
|
181
|
+
id: zId().describe("ID of the work item"),
|
|
150
182
|
top: zod_1.z.coerce.number().optional().describe("Maximum number of comments to return"),
|
|
151
|
-
order: zod_1.z.enum(['asc', 'desc']).optional().default('desc').describe("Sort order: 'asc' (oldest first) or 'desc' (newest first)")
|
|
183
|
+
order: zod_1.z.enum(['asc', 'desc']).optional().default('desc').describe("Sort order: 'asc' (oldest first) or 'desc' (newest first)"),
|
|
184
|
+
includeDeleted: zod_1.z.boolean().optional().describe("Include deleted comments")
|
|
152
185
|
}, async (params, extra) => {
|
|
153
186
|
const result = await workItemTools.getWorkItemComments(params);
|
|
154
187
|
return {
|
|
@@ -159,7 +192,7 @@ async function main() {
|
|
|
159
192
|
};
|
|
160
193
|
});
|
|
161
194
|
allowedTools.has("addWorkItemComment") && server.tool("addWorkItemComment", "Add a comment to a work item. Supports markdown formatting by default.", {
|
|
162
|
-
id:
|
|
195
|
+
id: zId().describe("ID of the work item"),
|
|
163
196
|
text: zod_1.z.string().describe("Comment text (supports markdown when format is 'markdown')"),
|
|
164
197
|
format: zod_1.z.enum(['markdown', 'html']).optional().default('markdown').describe("Comment format: 'markdown' (default) or 'html'")
|
|
165
198
|
}, async (params, extra) => {
|
|
@@ -172,7 +205,7 @@ async function main() {
|
|
|
172
205
|
};
|
|
173
206
|
});
|
|
174
207
|
allowedTools.has("updateWorkItemState") && server.tool("updateWorkItemState", "Update the state of a work item", {
|
|
175
|
-
id:
|
|
208
|
+
id: zId().describe("ID of the work item"),
|
|
176
209
|
state: zod_1.z.string().describe("New state for the work item"),
|
|
177
210
|
comment: zod_1.z.string().optional().describe("Comment explaining the state change")
|
|
178
211
|
}, async (params, extra) => {
|
|
@@ -184,7 +217,7 @@ async function main() {
|
|
|
184
217
|
};
|
|
185
218
|
});
|
|
186
219
|
allowedTools.has("assignWorkItem") && server.tool("assignWorkItem", "Assign a work item to a user", {
|
|
187
|
-
id:
|
|
220
|
+
id: zId().describe("ID of the work item"),
|
|
188
221
|
assignedTo: zod_1.z.string().describe("User to assign the work item to")
|
|
189
222
|
}, async (params, extra) => {
|
|
190
223
|
const result = await workItemTools.assignWorkItem(params);
|
|
@@ -198,7 +231,7 @@ async function main() {
|
|
|
198
231
|
"Use prefixes for targetId: WI#123 (work item), PR#456 (pull request), " +
|
|
199
232
|
"BUILD#789 (build), BRANCH#main (branch), COMMIT#abc123 (commit). " +
|
|
200
233
|
"Plain numbers default to work item.", {
|
|
201
|
-
sourceId:
|
|
234
|
+
sourceId: zId().describe("ID of the source work item"),
|
|
202
235
|
targetId: zod_1.z.string().describe("Target with prefix: WI#123, PR#456, BUILD#789, BRANCH#main, COMMIT#abc, or plain number for work item"),
|
|
203
236
|
linkType: zod_1.z.string().describe("Link type (e.g., System.LinkTypes.Related). For artifact prefixes, this is still required but the actual rel type is auto-set to ArtifactLink."),
|
|
204
237
|
comment: zod_1.z.string().optional().describe("Comment explaining the link"),
|
|
@@ -225,7 +258,7 @@ async function main() {
|
|
|
225
258
|
additionalFields: zod_1.z.record(zod_1.z.any()).optional().describe("Additional fields to set on the work item")
|
|
226
259
|
}),
|
|
227
260
|
zod_1.z.object({
|
|
228
|
-
id:
|
|
261
|
+
id: zId().describe("ID of work item to update"),
|
|
229
262
|
fields: zod_1.z.record(zod_1.z.any()).describe("Fields to update on the work item")
|
|
230
263
|
})
|
|
231
264
|
])).min(1).describe("Array of work items to create or update")
|
|
@@ -238,14 +271,14 @@ async function main() {
|
|
|
238
271
|
};
|
|
239
272
|
});
|
|
240
273
|
allowedTools.has("getWorkItemsBatch") && server.tool("getWorkItemsBatch", "Get multiple work items by their IDs in a single efficient call", {
|
|
241
|
-
ids:
|
|
274
|
+
ids: zIdArray().describe("Array of work item IDs to retrieve"),
|
|
242
275
|
fields: zod_1.z.preprocess(coerceArray, zod_1.z.array(zod_1.z.string()).optional()).describe("Specific fields to return (e.g., ['System.Title', 'System.State'])"),
|
|
243
276
|
}, async (params) => {
|
|
244
277
|
const result = await workItemTools.getWorkItemsBatch(params);
|
|
245
278
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
246
279
|
});
|
|
247
280
|
allowedTools.has("getWorkItemRevisions") && server.tool("getWorkItemRevisions", "Get revision/change history for a work item showing all field changes over time", {
|
|
248
|
-
id:
|
|
281
|
+
id: zId().describe("Work item ID"),
|
|
249
282
|
top: zod_1.z.coerce.number().optional().describe("Maximum number of revisions to return"),
|
|
250
283
|
skip: zod_1.z.coerce.number().optional().describe("Number of revisions to skip"),
|
|
251
284
|
}, async (params) => {
|
|
@@ -259,7 +292,7 @@ async function main() {
|
|
|
259
292
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
260
293
|
});
|
|
261
294
|
allowedTools.has("addChildWorkItem") && server.tool("addChildWorkItem", "Create a new work item and link it as a child of an existing parent work item", {
|
|
262
|
-
parentId:
|
|
295
|
+
parentId: zId().describe("Parent work item ID"),
|
|
263
296
|
workItemType: zod_1.z.string().describe("Type of child work item (e.g., 'Task', 'Bug')"),
|
|
264
297
|
title: zod_1.z.string().describe("Title of the child work item"),
|
|
265
298
|
description: zod_1.z.string().optional().describe("Description"),
|
|
@@ -273,7 +306,7 @@ async function main() {
|
|
|
273
306
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
274
307
|
});
|
|
275
308
|
allowedTools.has("unlinkWorkItem") && server.tool("unlinkWorkItem", "Remove a link/relation from a work item by its relation index. Use getWorkItemById first to see the relations and their indices.", {
|
|
276
|
-
id:
|
|
309
|
+
id: zId().describe("Work item ID"),
|
|
277
310
|
relationIndex: zod_1.z.coerce.number().describe("Index of the relation to remove (0-based, from the relations array)"),
|
|
278
311
|
}, async (params) => {
|
|
279
312
|
const result = await workItemTools.unlinkWorkItem(params);
|
|
@@ -315,7 +348,7 @@ async function main() {
|
|
|
315
348
|
allowedTools.has("moveCardOnBoard") && server.tool("moveCardOnBoard", "Move a card on a board", {
|
|
316
349
|
teamId: zod_1.z.string().optional().describe("Team ID (uses default team if not specified)"),
|
|
317
350
|
boardId: zod_1.z.string().describe("ID of the board"),
|
|
318
|
-
workItemId:
|
|
351
|
+
workItemId: zId().describe("ID of the work item to move"),
|
|
319
352
|
columnId: zod_1.z.string().describe("ID of the column to move to"),
|
|
320
353
|
position: zod_1.z.coerce.number().optional().describe("Position within the column")
|
|
321
354
|
}, async (params, extra) => {
|
|
@@ -659,7 +692,7 @@ async function main() {
|
|
|
659
692
|
"'files' (changed file list — prefer getAllPullRequestChanges for large diffs). " +
|
|
660
693
|
"Supports both repository names and IDs.", {
|
|
661
694
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
662
|
-
pullRequestId:
|
|
695
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to retrieve. This is the PR number shown in the Azure DevOps UI (e.g., PR #123)."),
|
|
663
696
|
include: zod_1.z.array(zod_1.z.enum(['policies', 'description', 'reviewers', 'workItems', 'completionOptions', 'files'])).optional().describe("Sections to return in full detail. When omitted, returns compact overview with all sections truncated. Specify sections you need full data for.")
|
|
664
697
|
}, async (params, extra) => {
|
|
665
698
|
const result = await gitTools.getPullRequest(params);
|
|
@@ -671,8 +704,8 @@ async function main() {
|
|
|
671
704
|
});
|
|
672
705
|
allowedTools.has("getPullRequestComments") && server.tool("getPullRequestComments", "Retrieve all comment threads and associated comments for a pull request. Returns a summary and organized list of threads including code review comments (with file/line context) and general discussions. Optionally filter by thread status (e.g., only 'active' unresolved threads), author name, specific thread ID, or use pagination. Supports both repository names and IDs.", {
|
|
673
706
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
674
|
-
pullRequestId:
|
|
675
|
-
threadId:
|
|
707
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to retrieve comments from. This is the PR number shown in the Azure DevOps UI."),
|
|
708
|
+
threadId: zIdOptional().describe("Optional ID of a specific comment thread to retrieve. If provided, only returns the specified thread rather than all threads."),
|
|
676
709
|
status: zod_1.z.enum(['active', 'fixed', 'wontFix', 'closed', 'byDesign', 'pending']).optional().describe("Filter threads by status. Use 'active' to see only unresolved threads, 'fixed' for resolved ones, etc."),
|
|
677
710
|
authorName: zod_1.z.string().optional().describe("Filter threads by author display name or email (case-insensitive partial match). Only threads where the root comment was authored by a matching user are returned."),
|
|
678
711
|
top: zod_1.z.coerce.number().optional().describe("Maximum number of comment threads to return in the response. Use this for pagination in PRs with many comments."),
|
|
@@ -688,7 +721,7 @@ async function main() {
|
|
|
688
721
|
});
|
|
689
722
|
allowedTools.has("approvePullRequest") && server.tool("approvePullRequest", "Cast an 'Approve' vote on a pull request on behalf of the current authenticated user. This marks the PR as approved by the user and contributes toward satisfying approval requirements defined in branch policies. Equivalent to clicking 'Approve' in the Azure DevOps UI. Supports both repository names and IDs.", {
|
|
690
723
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
691
|
-
pullRequestId:
|
|
724
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to approve. This is the PR number shown in the Azure DevOps UI (e.g., PR #123).")
|
|
692
725
|
}, async (params, extra) => {
|
|
693
726
|
const result = await gitTools.approvePullRequest(params);
|
|
694
727
|
return {
|
|
@@ -699,7 +732,7 @@ async function main() {
|
|
|
699
732
|
});
|
|
700
733
|
allowedTools.has("mergePullRequest") && server.tool("mergePullRequest", "Complete a pull request by merging the source branch changes into the target branch. This operation requires that all required reviewers have approved the PR and all branch policies are satisfied. Supports different merge strategies (squash, rebase, etc.) and allows adding a custom commit message. Supports both repository names and IDs.", {
|
|
701
734
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
702
|
-
pullRequestId:
|
|
735
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to merge. This is the PR number shown in the Azure DevOps UI (e.g., PR #123)."),
|
|
703
736
|
mergeStrategy: zod_1.z.enum(['noFastForward', 'rebase', 'rebaseMerge', 'squash']).optional().describe("The strategy to use when merging changes: 'noFastForward' creates a merge commit, 'rebase' updates the source branch commits onto the target branch, 'rebaseMerge' combines rebase with a merge commit, 'squash' combines all changes into a single commit."),
|
|
704
737
|
comment: zod_1.z.string().optional().describe("Optional comment to include in the merge commit message. Use this to provide additional context about the merge beyond the default message.")
|
|
705
738
|
}, async (params, extra) => {
|
|
@@ -713,7 +746,7 @@ async function main() {
|
|
|
713
746
|
// Register new Pull Request Comment Tools
|
|
714
747
|
allowedTools.has("addPullRequestInlineComment") && server.tool("addPullRequestInlineComment", "Add an inline code comment anchored to a SPECIFIC LINE of code in a file. The comment appears directly on that line in the Files tab. WHEN TO USE: Point out specific code issues, suggest improvements to a particular line, or ask questions about specific implementation details. EXAMPLES: 'This variable should be null-checked here', 'Consider using async/await on line 45', 'Why is this hardcoded?'. The system automatically retrieves the correct change tracking ID from the PR diff.", {
|
|
715
748
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
716
|
-
pullRequestId:
|
|
749
|
+
pullRequestId: zId().describe("The numeric ID of the pull request where the comment will be added. This is the PR number shown in the Azure DevOps UI."),
|
|
717
750
|
comment: zod_1.z.string().describe("The text content of the comment to add. Can include markdown formatting. Should be specific to the line of code being commented on."),
|
|
718
751
|
position: zod_1.z.object({
|
|
719
752
|
line: zod_1.z.coerce.number().describe("The 1-based line number in the file where the comment starts. Must be a line visible in the PR diff (added, removed, or context line)."),
|
|
@@ -732,7 +765,7 @@ async function main() {
|
|
|
732
765
|
});
|
|
733
766
|
allowedTools.has("addPullRequestFileComment") && server.tool("addPullRequestFileComment", "Add a comment about an ENTIRE FILE (not a specific line). The comment appears at the file level in the Files tab. WHEN TO USE: Discuss overall file structure, architecture decisions, naming conventions, or when feedback applies to the whole file. EXAMPLES: 'This file should be split into smaller modules', 'Consider moving this to a different namespace', 'Great refactoring of this entire service!', 'This file needs unit tests'.", {
|
|
734
767
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
735
|
-
pullRequestId:
|
|
768
|
+
pullRequestId: zId().describe("The numeric ID of the pull request where the comment will be added. This is the PR number shown in the Azure DevOps UI."),
|
|
736
769
|
path: zod_1.z.string().describe("The full path to the file within the repository that the comment relates to. Must be a file changed in the PR (e.g., '/src/Models/User.cs')."),
|
|
737
770
|
comment: zod_1.z.string().describe("The text content of the comment about the entire file. Can include markdown formatting. Should address file-level concerns, not specific lines.")
|
|
738
771
|
}, async (params, extra) => {
|
|
@@ -745,7 +778,7 @@ async function main() {
|
|
|
745
778
|
});
|
|
746
779
|
allowedTools.has("addPullRequestComment") && server.tool("addPullRequestComment", "Add a GENERAL comment about the entire pull request (not tied to any file or code). Appears in the Overview/Conversation tab. WHEN TO USE: Provide overall feedback, discuss architecture, approve/reject the PR, ask general questions, or comment on the PR description. EXAMPLES: 'This feature looks great! LGTM after CI passes', 'Can you add integration tests for this feature?', 'What's the performance impact of these changes?', 'Please update the documentation before merging'.", {
|
|
747
780
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
748
|
-
pullRequestId:
|
|
781
|
+
pullRequestId: zId().describe("The numeric ID of the pull request where the comment will be added. This is the PR number shown in the Azure DevOps UI."),
|
|
749
782
|
comment: zod_1.z.string().describe("The text content of the general comment about the PR. Can include markdown formatting for rich text, code blocks, links, etc. Should address PR-level concerns, not specific files or lines.")
|
|
750
783
|
}, async (params, extra) => {
|
|
751
784
|
const result = await gitTools.addPullRequestComment(params);
|
|
@@ -758,7 +791,7 @@ async function main() {
|
|
|
758
791
|
// Register new Pull Request Diff Tools
|
|
759
792
|
allowedTools.has("getPullRequestFileChanges") && server.tool("getPullRequestFileChanges", "Retrieve detailed file diff information for a specific file changed within a pull request. Returns change metadata including change type (add, edit, delete), before/after content identifiers, and file path information. Optionally filter to a specific file path.", {
|
|
760
793
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
761
|
-
pullRequestId:
|
|
794
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to examine. This is the PR number shown in the Azure DevOps UI."),
|
|
762
795
|
path: zod_1.z.string().optional().describe("Optional path to a specific file to return changes for. If omitted, changes for all files will be returned but filtered to match this specific path.")
|
|
763
796
|
}, async (params, extra) => {
|
|
764
797
|
const result = await gitTools.getPullRequestFileChanges(params);
|
|
@@ -770,7 +803,7 @@ async function main() {
|
|
|
770
803
|
});
|
|
771
804
|
allowedTools.has("getPullRequestChangesCount") && server.tool("getPullRequestChangesCount", "Get statistical summary of changes in a pull request, including total count of files changed and breakdowns by change type (added, modified, deleted). Useful for understanding the scope of changes in a PR at a glance.", {
|
|
772
805
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
773
|
-
pullRequestId:
|
|
806
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to analyze. This is the PR number shown in the Azure DevOps UI.")
|
|
774
807
|
}, async (params, extra) => {
|
|
775
808
|
const result = await gitTools.getPullRequestChangesCount(params);
|
|
776
809
|
return {
|
|
@@ -781,7 +814,7 @@ async function main() {
|
|
|
781
814
|
});
|
|
782
815
|
allowedTools.has("getAllPullRequestChanges") && server.tool("getAllPullRequestChanges", "Retrieve a comprehensive list of all file changes in a pull request with pagination support. Returns a summary and table of changed files with change types. Use pagination parameters (top/skip) to handle large PRs with many file changes. This does NOT include diff content - use getPullRequestFileChanges for detailed diffs.", {
|
|
783
816
|
repository: zod_1.z.string().describe("The repository name (e.g., 'MyProject') or ID (GUID) containing the pull request. Repository names are case-insensitive."),
|
|
784
|
-
pullRequestId:
|
|
817
|
+
pullRequestId: zId().describe("The numeric ID of the pull request to retrieve changes for. This is the PR number shown in the Azure DevOps UI."),
|
|
785
818
|
top: zod_1.z.coerce.number().optional().describe("Maximum number of change entries to return in a single request. Use this for pagination to avoid large response payloads."),
|
|
786
819
|
skip: zod_1.z.coerce.number().optional().describe("Number of change entries to skip before starting to return results. Use with 'top' for implementing pagination.")
|
|
787
820
|
}, async (params, extra) => {
|
|
@@ -795,7 +828,7 @@ async function main() {
|
|
|
795
828
|
});
|
|
796
829
|
allowedTools.has("updatePullRequest") && server.tool("updatePullRequest", "Update pull request properties (title, description, status, auto-complete, draft mode, target branch)", {
|
|
797
830
|
repository: zod_1.z.string().describe("Repository name or ID"),
|
|
798
|
-
pullRequestId:
|
|
831
|
+
pullRequestId: zId().describe("Pull request ID"),
|
|
799
832
|
title: zod_1.z.string().optional().describe("New title for the PR"),
|
|
800
833
|
description: zod_1.z.string().optional().describe("New description for the PR"),
|
|
801
834
|
status: zod_1.z.enum(['active', 'abandoned', 'completed']).optional().describe("New status"),
|
|
@@ -810,7 +843,7 @@ async function main() {
|
|
|
810
843
|
});
|
|
811
844
|
allowedTools.has("updatePullRequestReviewers") && server.tool("updatePullRequestReviewers", "Add or remove reviewers on an existing pull request", {
|
|
812
845
|
repository: zod_1.z.string().describe("Repository name or ID"),
|
|
813
|
-
pullRequestId:
|
|
846
|
+
pullRequestId: zId().describe("Pull request ID"),
|
|
814
847
|
reviewersToAdd: zod_1.z.array(zod_1.z.string()).optional().describe("User IDs or email addresses to add as reviewers"),
|
|
815
848
|
reviewersToRemove: zod_1.z.array(zod_1.z.string()).optional().describe("User IDs or email addresses to remove from reviewers"),
|
|
816
849
|
makeRequired: zod_1.z.boolean().optional().describe("Make added reviewers required (default false)"),
|
|
@@ -820,8 +853,8 @@ async function main() {
|
|
|
820
853
|
});
|
|
821
854
|
allowedTools.has("replyToComment") && server.tool("replyToComment", "Reply to an existing comment thread on a pull request", {
|
|
822
855
|
repository: zod_1.z.string().describe("Repository name or ID"),
|
|
823
|
-
pullRequestId:
|
|
824
|
-
threadId:
|
|
856
|
+
pullRequestId: zId().describe("Pull request ID"),
|
|
857
|
+
threadId: zId().describe("Thread ID to reply to"),
|
|
825
858
|
comment: zod_1.z.string().describe("Reply text content (supports markdown)"),
|
|
826
859
|
}, async (params) => {
|
|
827
860
|
const result = await gitTools.replyToComment(params);
|
|
@@ -829,8 +862,8 @@ async function main() {
|
|
|
829
862
|
});
|
|
830
863
|
allowedTools.has("updatePullRequestThread") && server.tool("updatePullRequestThread", "Update a comment thread's status (resolve, reactivate, close, etc.)", {
|
|
831
864
|
repository: zod_1.z.string().describe("Repository name or ID"),
|
|
832
|
-
pullRequestId:
|
|
833
|
-
threadId:
|
|
865
|
+
pullRequestId: zId().describe("Pull request ID"),
|
|
866
|
+
threadId: zId().describe("Thread ID to update"),
|
|
834
867
|
status: zod_1.z.enum(['active', 'byDesign', 'closed', 'fixed', 'pending', 'unknown', 'wontFix']).describe("New thread status"),
|
|
835
868
|
}, async (params) => {
|
|
836
869
|
const result = await gitTools.updatePullRequestThread(params);
|
|
@@ -846,8 +879,8 @@ async function main() {
|
|
|
846
879
|
});
|
|
847
880
|
// Register Testing Capabilities Tools
|
|
848
881
|
allowedTools.has("runAutomatedTests") && server.tool("runAutomatedTests", "Execute automated test suites", {
|
|
849
|
-
testSuiteId:
|
|
850
|
-
testPlanId:
|
|
882
|
+
testSuiteId: zIdOptional().describe("ID of the test suite to run"),
|
|
883
|
+
testPlanId: zIdOptional().describe("ID of the test plan to run"),
|
|
851
884
|
testEnvironment: zod_1.z.string().optional().describe("Environment to run tests in"),
|
|
852
885
|
parallelExecution: zod_1.z.boolean().optional().describe("Whether to run tests in parallel")
|
|
853
886
|
}, async (params, extra) => {
|
|
@@ -859,7 +892,7 @@ async function main() {
|
|
|
859
892
|
};
|
|
860
893
|
});
|
|
861
894
|
allowedTools.has("getTestAutomationStatus") && server.tool("getTestAutomationStatus", "Check status of automated test execution", {
|
|
862
|
-
testRunId:
|
|
895
|
+
testRunId: zId().describe("ID of the test run to check status for")
|
|
863
896
|
}, async (params, extra) => {
|
|
864
897
|
const result = await testingCapabilitiesTools.getTestAutomationStatus(params);
|
|
865
898
|
return {
|
|
@@ -905,8 +938,8 @@ async function main() {
|
|
|
905
938
|
};
|
|
906
939
|
});
|
|
907
940
|
allowedTools.has("getTestFlakiness") && server.tool("getTestFlakiness", "Analyze and report on test flakiness", {
|
|
908
|
-
testId:
|
|
909
|
-
testRunIds:
|
|
941
|
+
testId: zIdOptional().describe("ID of a specific test to analyze"),
|
|
942
|
+
testRunIds: zIdArray().optional().describe("Specific test runs to analyze"),
|
|
910
943
|
timeRange: zod_1.z.string().optional().describe("Time range for analysis (e.g., '30d')")
|
|
911
944
|
}, async (params, extra) => {
|
|
912
945
|
const result = await testingCapabilitiesTools.getTestFlakiness(params);
|
|
@@ -928,7 +961,7 @@ async function main() {
|
|
|
928
961
|
};
|
|
929
962
|
});
|
|
930
963
|
allowedTools.has("runTestImpactAnalysis") && server.tool("runTestImpactAnalysis", "Determine which tests to run based on code changes", {
|
|
931
|
-
buildId:
|
|
964
|
+
buildId: zId().describe("ID of the build to analyze"),
|
|
932
965
|
changedFiles: zod_1.z.array(zod_1.z.string()).optional().describe("List of changed files")
|
|
933
966
|
}, async (params, extra) => {
|
|
934
967
|
const result = await testingCapabilitiesTools.runTestImpactAnalysis(params);
|
|
@@ -950,7 +983,7 @@ async function main() {
|
|
|
950
983
|
};
|
|
951
984
|
});
|
|
952
985
|
allowedTools.has("runTestOptimization") && server.tool("runTestOptimization", "Optimize test suite execution for faster feedback", {
|
|
953
|
-
testPlanId:
|
|
986
|
+
testPlanId: zId().describe("ID of the test plan to optimize"),
|
|
954
987
|
optimizationGoal: zod_1.z.enum(['time', 'coverage', 'reliability']).describe("Optimization goal")
|
|
955
988
|
}, async (params, extra) => {
|
|
956
989
|
const result = await testingCapabilitiesTools.runTestOptimization(params);
|
|
@@ -973,7 +1006,7 @@ async function main() {
|
|
|
973
1006
|
};
|
|
974
1007
|
});
|
|
975
1008
|
allowedTools.has("recordExploratoryTestResults") && server.tool("recordExploratoryTestResults", "Record findings during exploratory testing", {
|
|
976
|
-
sessionId:
|
|
1009
|
+
sessionId: zId().describe("ID of the exploratory session"),
|
|
977
1010
|
findings: zod_1.z.array(zod_1.z.string()).describe("List of findings to record"),
|
|
978
1011
|
attachments: zod_1.z.array(zod_1.z.object({
|
|
979
1012
|
name: zod_1.z.string().describe("Name of the attachment"),
|
|
@@ -989,8 +1022,8 @@ async function main() {
|
|
|
989
1022
|
};
|
|
990
1023
|
});
|
|
991
1024
|
allowedTools.has("convertFindingsToWorkItems") && server.tool("convertFindingsToWorkItems", "Convert exploratory test findings to work items", {
|
|
992
|
-
sessionId:
|
|
993
|
-
findingIds:
|
|
1025
|
+
sessionId: zId().describe("ID of the exploratory session"),
|
|
1026
|
+
findingIds: zIdArray().describe("IDs of findings to convert"),
|
|
994
1027
|
workItemType: zod_1.z.string().optional().describe("Type of work item to create")
|
|
995
1028
|
}, async (params, extra) => {
|
|
996
1029
|
const result = await testingCapabilitiesTools.convertFindingsToWorkItems(params);
|
|
@@ -1316,7 +1349,7 @@ async function main() {
|
|
|
1316
1349
|
});
|
|
1317
1350
|
// AI Assisted Development Tools
|
|
1318
1351
|
allowedTools.has("getAICodeReview") && server.tool("getAICodeReview", "Get AI-based code review suggestions", {
|
|
1319
|
-
pullRequestId:
|
|
1352
|
+
pullRequestId: zIdOptional().describe("ID of the pull request to review"),
|
|
1320
1353
|
repositoryId: zod_1.z.string().optional().describe("ID of the repository"),
|
|
1321
1354
|
commitId: zod_1.z.string().optional().describe("ID of the commit to review"),
|
|
1322
1355
|
filePath: zod_1.z.string().optional().describe("Path to the file to review")
|
|
@@ -1357,7 +1390,7 @@ async function main() {
|
|
|
1357
1390
|
});
|
|
1358
1391
|
allowedTools.has("getPredictiveBugAnalysis") && server.tool("getPredictiveBugAnalysis", "Predict potential bugs in code changes. Supports both repository names and IDs.", {
|
|
1359
1392
|
repository: zod_1.z.string().describe("Repository name (e.g., 'MyProject') or ID (GUID). Repository names are case-insensitive."),
|
|
1360
|
-
pullRequestId:
|
|
1393
|
+
pullRequestId: zIdOptional().describe("ID of the pull request"),
|
|
1361
1394
|
branch: zod_1.z.string().optional().describe("Branch to analyze"),
|
|
1362
1395
|
filePath: zod_1.z.string().optional().describe("Path to the file to analyze")
|
|
1363
1396
|
}, async (params, extra) => {
|
|
@@ -1382,7 +1415,7 @@ async function main() {
|
|
|
1382
1415
|
};
|
|
1383
1416
|
});
|
|
1384
1417
|
allowedTools.has("getPredictiveEffortEstimation") && server.tool("getPredictiveEffortEstimation", "AI-based effort estimation for work items", {
|
|
1385
|
-
workItemIds:
|
|
1418
|
+
workItemIds: zIdArray().optional().describe("IDs of work items to estimate"),
|
|
1386
1419
|
workItemType: zod_1.z.string().optional().describe("Type of work items to estimate"),
|
|
1387
1420
|
areaPath: zod_1.z.string().optional().describe("Area path to filter work items")
|
|
1388
1421
|
}, async (params, extra) => {
|
|
@@ -1407,7 +1440,7 @@ async function main() {
|
|
|
1407
1440
|
};
|
|
1408
1441
|
});
|
|
1409
1442
|
allowedTools.has("suggestWorkItemRefinements") && server.tool("suggestWorkItemRefinements", "Get AI suggestions for work item refinements", {
|
|
1410
|
-
workItemId:
|
|
1443
|
+
workItemId: zIdOptional().describe("ID of the work item to refine"),
|
|
1411
1444
|
workItemType: zod_1.z.string().optional().describe("Type of work item"),
|
|
1412
1445
|
areaPath: zod_1.z.string().optional().describe("Area path to filter work items")
|
|
1413
1446
|
}, async (params, extra) => {
|
|
@@ -1443,7 +1476,7 @@ async function main() {
|
|
|
1443
1476
|
};
|
|
1444
1477
|
});
|
|
1445
1478
|
allowedTools.has("predictBuildFailures") && server.tool("predictBuildFailures", "Predict potential build failures before they occur", {
|
|
1446
|
-
buildDefinitionId:
|
|
1479
|
+
buildDefinitionId: zId().describe("ID of the build definition"),
|
|
1447
1480
|
lookbackPeriod: zod_1.z.string().optional().describe("Period to analyze for patterns (e.g., '30d')")
|
|
1448
1481
|
}, async (params, extra) => {
|
|
1449
1482
|
const result = await aiAssistedDevelopmentTools.predictBuildFailures(params);
|
|
@@ -1454,7 +1487,7 @@ async function main() {
|
|
|
1454
1487
|
};
|
|
1455
1488
|
});
|
|
1456
1489
|
allowedTools.has("optimizeTestSelection") && server.tool("optimizeTestSelection", "Intelligently select tests to run based on changes", {
|
|
1457
|
-
buildId:
|
|
1490
|
+
buildId: zId().describe("ID of the build"),
|
|
1458
1491
|
changedFiles: zod_1.z.array(zod_1.z.string()).optional().describe("List of changed files"),
|
|
1459
1492
|
maxTestCount: zod_1.z.coerce.number().optional().describe("Maximum number of tests to select")
|
|
1460
1493
|
}, async (params, extra) => {
|
|
@@ -1508,7 +1541,7 @@ async function main() {
|
|
|
1508
1541
|
});
|
|
1509
1542
|
// Register Build/Pipeline Tools
|
|
1510
1543
|
allowedTools.has("getBuilds") && server.tool("getBuilds", "List builds with optional filters (status, result, branch, definition, tags)", {
|
|
1511
|
-
definitions:
|
|
1544
|
+
definitions: zIdArray().optional().describe("Filter by definition IDs"),
|
|
1512
1545
|
statusFilter: zod_1.z.string().optional().describe("Filter by status: inProgress, completed, cancelling, postponed, notStarted, all"),
|
|
1513
1546
|
resultFilter: zod_1.z.string().optional().describe("Filter by result: succeeded, partiallySucceeded, failed, canceled"),
|
|
1514
1547
|
branchName: zod_1.z.string().optional().describe("Filter by source branch (e.g., 'refs/heads/main')"),
|
|
@@ -1523,14 +1556,14 @@ async function main() {
|
|
|
1523
1556
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1524
1557
|
});
|
|
1525
1558
|
allowedTools.has("getBuild") && server.tool("getBuild", "Get detailed information about a specific build by ID", {
|
|
1526
|
-
buildId:
|
|
1559
|
+
buildId: zId().describe("Build ID"),
|
|
1527
1560
|
}, async (params) => {
|
|
1528
1561
|
const result = await buildTools.getBuild(params);
|
|
1529
1562
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1530
1563
|
});
|
|
1531
1564
|
allowedTools.has("getBuildLog") && server.tool("getBuildLog", "Get build logs. Without logId returns log metadata list; with logId returns specific log content", {
|
|
1532
|
-
buildId:
|
|
1533
|
-
logId:
|
|
1565
|
+
buildId: zId().describe("Build ID"),
|
|
1566
|
+
logId: zIdOptional().describe("Specific log ID to retrieve content for"),
|
|
1534
1567
|
startLine: zod_1.z.coerce.number().optional().describe("Start line for log content"),
|
|
1535
1568
|
endLine: zod_1.z.coerce.number().optional().describe("End line for log content"),
|
|
1536
1569
|
}, async (params) => {
|
|
@@ -1538,7 +1571,7 @@ async function main() {
|
|
|
1538
1571
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1539
1572
|
});
|
|
1540
1573
|
allowedTools.has("getBuildChanges") && server.tool("getBuildChanges", "Get changes (commits) associated with a build", {
|
|
1541
|
-
buildId:
|
|
1574
|
+
buildId: zId().describe("Build ID"),
|
|
1542
1575
|
top: zod_1.z.coerce.number().optional().describe("Maximum number of changes to return (default 50)"),
|
|
1543
1576
|
}, async (params) => {
|
|
1544
1577
|
const result = await buildTools.getBuildChanges(params);
|
|
@@ -1556,14 +1589,14 @@ async function main() {
|
|
|
1556
1589
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1557
1590
|
});
|
|
1558
1591
|
allowedTools.has("getDefinition") && server.tool("getDefinition", "Get detailed information about a specific pipeline/build definition", {
|
|
1559
|
-
definitionId:
|
|
1592
|
+
definitionId: zId().describe("Definition ID"),
|
|
1560
1593
|
includeLatestBuilds: zod_1.z.boolean().optional().describe("Include latest build info"),
|
|
1561
1594
|
}, async (params) => {
|
|
1562
1595
|
const result = await buildTools.getDefinition(params);
|
|
1563
1596
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1564
1597
|
});
|
|
1565
1598
|
allowedTools.has("runPipeline") && server.tool("runPipeline", "Queue/trigger a pipeline run", {
|
|
1566
|
-
definitionId:
|
|
1599
|
+
definitionId: zId().describe("Pipeline definition ID to run"),
|
|
1567
1600
|
sourceBranch: zod_1.z.string().optional().describe("Source branch (e.g., 'refs/heads/main')"),
|
|
1568
1601
|
parameters: zod_1.z.record(zod_1.z.string()).optional().describe("Pipeline parameters as key-value pairs"),
|
|
1569
1602
|
}, async (params) => {
|
|
@@ -1571,19 +1604,19 @@ async function main() {
|
|
|
1571
1604
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1572
1605
|
});
|
|
1573
1606
|
allowedTools.has("getBuildArtifacts") && server.tool("getBuildArtifacts", "List artifacts produced by a build", {
|
|
1574
|
-
buildId:
|
|
1607
|
+
buildId: zId().describe("Build ID"),
|
|
1575
1608
|
}, async (params) => {
|
|
1576
1609
|
const result = await buildTools.getBuildArtifacts(params);
|
|
1577
1610
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1578
1611
|
});
|
|
1579
1612
|
allowedTools.has("getBuildTimeline") && server.tool("getBuildTimeline", "Get build timeline showing stages, jobs, and tasks with their status", {
|
|
1580
|
-
buildId:
|
|
1613
|
+
buildId: zId().describe("Build ID"),
|
|
1581
1614
|
}, async (params) => {
|
|
1582
1615
|
const result = await buildTools.getBuildTimeline(params);
|
|
1583
1616
|
return { content: result.content, rawData: result.rawData, structuredContent: result.structuredContent };
|
|
1584
1617
|
});
|
|
1585
1618
|
allowedTools.has("getBuildWorkItems") && server.tool("getBuildWorkItems", "Get work items associated with a build", {
|
|
1586
|
-
buildId:
|
|
1619
|
+
buildId: zId().describe("Build ID"),
|
|
1587
1620
|
top: zod_1.z.coerce.number().optional().describe("Maximum number of work items to return (default 50)"),
|
|
1588
1621
|
}, async (params) => {
|
|
1589
1622
|
const result = await buildTools.getBuildWorkItems(params);
|