@azure-devops/mcp 2.5.0-nightly.20260413 → 2.5.0-nightly.20260414

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.
@@ -811,42 +811,76 @@ function configureRepoTools(server, tokenProvider, connectionProvider, userAgent
811
811
  project: z.string().optional().describe("Project ID or project name. Required when repositoryId is a repository name instead of a GUID."),
812
812
  includeWorkItemRefs: z.boolean().optional().default(false).describe("Whether to reference work items associated with the pull request."),
813
813
  includeLabels: z.boolean().optional().default(false).describe("Whether to include a summary of labels in the response."),
814
- }, async ({ repositoryId, pullRequestId, project, includeWorkItemRefs, includeLabels }) => {
814
+ includeChangedFiles: z.boolean().optional().default(false).describe("Whether to include the list of files changed in the pull request."),
815
+ }, async ({ repositoryId, pullRequestId, project, includeWorkItemRefs, includeLabels, includeChangedFiles }) => {
815
816
  try {
816
817
  const connection = await connectionProvider();
817
818
  const gitApi = await connection.getGitApi();
818
819
  const pullRequest = await gitApi.getPullRequest(repositoryId, pullRequestId, project, undefined, undefined, undefined, undefined, includeWorkItemRefs);
820
+ let enhancedResponse = { ...pullRequest };
819
821
  if (includeLabels) {
820
822
  try {
821
823
  const projectId = pullRequest.repository?.project?.id;
822
824
  const projectName = pullRequest.repository?.project?.name;
823
825
  const labels = await gitApi.getPullRequestLabels(repositoryId, pullRequestId, projectName, projectId);
824
826
  const labelNames = labels.map((label) => label.name).filter((name) => name !== undefined);
825
- const enhancedResponse = {
826
- ...pullRequest,
827
+ enhancedResponse = {
828
+ ...enhancedResponse,
827
829
  labelSummary: {
828
830
  labels: labelNames,
829
831
  labelCount: labelNames.length,
830
832
  },
831
833
  };
832
- return {
833
- content: [{ type: "text", text: JSON.stringify(enhancedResponse, null, 2) }],
834
- };
835
834
  }
836
835
  catch (error) {
837
836
  console.warn(`Error fetching PR labels: ${error instanceof Error ? error.message : "Unknown error"}`);
838
- // Fall back to the original response without labels
839
- const enhancedResponse = {
840
- ...pullRequest,
837
+ enhancedResponse = {
838
+ ...enhancedResponse,
841
839
  labelSummary: {},
842
840
  };
843
- return {
844
- content: [{ type: "text", text: JSON.stringify(enhancedResponse, null, 2) }],
841
+ }
842
+ }
843
+ if (includeChangedFiles) {
844
+ try {
845
+ const iterations = await gitApi.getPullRequestIterations(repositoryId, pullRequestId, project);
846
+ if (iterations?.length) {
847
+ const latestIteration = iterations[iterations.length - 1];
848
+ if (latestIteration.id != null) {
849
+ const changes = await gitApi.getPullRequestIterationChanges(repositoryId, pullRequestId, latestIteration.id, project);
850
+ enhancedResponse = {
851
+ ...enhancedResponse,
852
+ changedFilesSummary: {
853
+ changeEntries: changes?.changeEntries ?? [],
854
+ fileCount: changes?.changeEntries?.length ?? 0,
855
+ nextSkip: changes?.nextSkip,
856
+ nextTop: changes?.nextTop,
857
+ },
858
+ };
859
+ }
860
+ else {
861
+ enhancedResponse = {
862
+ ...enhancedResponse,
863
+ changedFilesSummary: { changeEntries: [], fileCount: 0 },
864
+ };
865
+ }
866
+ }
867
+ else {
868
+ enhancedResponse = {
869
+ ...enhancedResponse,
870
+ changedFilesSummary: { changeEntries: [], fileCount: 0 },
871
+ };
872
+ }
873
+ }
874
+ catch (error) {
875
+ console.warn(`Error fetching PR changed files: ${error instanceof Error ? error.message : "Unknown error"}`);
876
+ enhancedResponse = {
877
+ ...enhancedResponse,
878
+ changedFilesSummary: {},
845
879
  };
846
880
  }
847
881
  }
848
882
  return {
849
- content: [{ type: "text", text: JSON.stringify(pullRequest, null, 2) }],
883
+ content: [{ type: "text", text: JSON.stringify(enhancedResponse, null, 2) }],
850
884
  };
851
885
  }
852
886
  catch (error) {
@@ -222,13 +222,16 @@ function configureWorkItemTools(server, tokenProvider, connectionProvider, userA
222
222
  server.tool(WORKITEM_TOOLS.get_work_item, "Get a single work item by ID. If a project is not specified, you will be prompted to select one.", {
223
223
  id: z.coerce.number().min(1).describe("The ID of the work item to retrieve."),
224
224
  project: z.string().optional().describe("The name or ID of the Azure DevOps project. Reuse from prior context if already known. If not provided, a project selection prompt will be shown."),
225
- fields: z.array(z.string()).optional().describe("Optional list of fields to include in the response. If not provided, all fields will be returned."),
225
+ fields: z
226
+ .array(z.string())
227
+ .optional()
228
+ .describe("Optional list of fields to include in the response. If not provided, all fields will be returned. Cannot be used together with the expand parameter."),
226
229
  asOf: z.coerce.date().optional().describe("Optional date string to retrieve the work item as of a specific time. If not provided, the current state will be returned."),
227
230
  expand: z
228
231
  .enum(["all", "fields", "links", "none", "relations"])
229
- .describe("Optional expand parameter to include additional details in the response.")
232
+ .describe("Optional expand parameter to include additional details in the response. Cannot be used together with the fields parameter.")
230
233
  .optional()
231
- .describe("Expand options include 'all', 'fields', 'links', 'none', and 'relations'. Relations can be used to get child workitems. Defaults to 'none'."),
234
+ .describe("Expand options include 'All', 'Fields', 'Links', 'None', and 'Relations'. Relations can be used to get child workitems. Defaults to 'None'. Cannot be used together with the fields parameter."),
232
235
  }, async ({ id, project, fields, asOf, expand }) => {
233
236
  try {
234
237
  const connection = await connectionProvider();
@@ -239,6 +242,11 @@ function configureWorkItemTools(server, tokenProvider, connectionProvider, userA
239
242
  return result.response;
240
243
  resolvedProject = result.resolved;
241
244
  }
245
+ // The Azure DevOps API does not support using expand and fields together.
246
+ // When both are provided, prefer fields as it is the more specific selection.
247
+ if (fields && fields.length > 0 && expand != null) {
248
+ expand = "none";
249
+ }
242
250
  const workItemApi = await connection.getWorkItemTrackingApi();
243
251
  const workItem = await workItemApi.getWorkItem(id, fields, asOf, expand, resolvedProject);
244
252
  return {
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const packageVersion = "2.5.0-nightly.20260413";
1
+ export const packageVersion = "2.5.0-nightly.20260414";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-devops/mcp",
3
- "version": "2.5.0-nightly.20260413",
3
+ "version": "2.5.0-nightly.20260414",
4
4
  "mcpName": "microsoft.com/azure-devops",
5
5
  "description": "MCP server for interacting with Azure DevOps",
6
6
  "license": "MIT",