@azure-devops/mcp 2.5.0-nightly.20260318 → 2.5.0-nightly.20260320
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/pipelines.js +8 -1
- package/dist/tools/repositories.js +13 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/tools/pipelines.js
CHANGED
|
@@ -6,7 +6,7 @@ import { z } from "zod";
|
|
|
6
6
|
import { StageUpdateType } from "azure-devops-node-api/interfaces/BuildInterfaces.js";
|
|
7
7
|
import { ConfigurationType, RepositoryType } from "azure-devops-node-api/interfaces/PipelinesInterfaces.js";
|
|
8
8
|
import { mkdirSync, createWriteStream } from "fs";
|
|
9
|
-
import { join, resolve } from "path";
|
|
9
|
+
import { join, posix, resolve, win32 } from "path";
|
|
10
10
|
const PIPELINE_TOOLS = {
|
|
11
11
|
pipelines_get_builds: "pipelines_get_builds",
|
|
12
12
|
pipelines_get_build_changes: "pipelines_get_build_changes",
|
|
@@ -336,6 +336,13 @@ function configurePipelineTools(server, tokenProvider, connectionProvider, userA
|
|
|
336
336
|
artifactName: z.string().describe("The name of the artifact to download."),
|
|
337
337
|
destinationPath: z.string().optional().describe("The local path to download the artifact to. If not provided, returns binary content as base64."),
|
|
338
338
|
}, async ({ project, buildId, artifactName, destinationPath }) => {
|
|
339
|
+
const isAbsolutePath = (value) => posix.isAbsolute(value) || win32.isAbsolute(value);
|
|
340
|
+
if (artifactName.includes("..")) {
|
|
341
|
+
throw new Error("Invalid artifactName: path traversal is not allowed.");
|
|
342
|
+
}
|
|
343
|
+
if (destinationPath && (destinationPath.includes("..") || isAbsolutePath(destinationPath))) {
|
|
344
|
+
throw new Error("Invalid destinationPath: absolute paths and paths traversals are not allowed.");
|
|
345
|
+
}
|
|
339
346
|
const connection = await connectionProvider();
|
|
340
347
|
const buildApi = await connection.getBuildApi();
|
|
341
348
|
const artifact = await buildApi.getArtifact(project, buildId, artifactName);
|
|
@@ -86,6 +86,9 @@ function filterReposByName(repositories, repoNameFilter) {
|
|
|
86
86
|
return filteredByName;
|
|
87
87
|
}
|
|
88
88
|
function trimPullRequest(pr, includeDescription = false) {
|
|
89
|
+
if (!pr) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
89
92
|
return {
|
|
90
93
|
pullRequestId: pr.pullRequestId,
|
|
91
94
|
codeReviewId: pr.codeReviewId,
|
|
@@ -170,6 +173,11 @@ function configureRepoTools(server, tokenProvider, connectionProvider, userAgent
|
|
|
170
173
|
}
|
|
171
174
|
}
|
|
172
175
|
const trimmedPullRequest = trimPullRequest(pullRequest, true);
|
|
176
|
+
if (!trimmedPullRequest) {
|
|
177
|
+
return {
|
|
178
|
+
content: [{ type: "text", text: "Pull request created but API returned no data." }],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
173
181
|
return {
|
|
174
182
|
content: [{ type: "text", text: JSON.stringify(trimmedPullRequest, null, 2) }],
|
|
175
183
|
};
|
|
@@ -365,6 +373,11 @@ function configureRepoTools(server, tokenProvider, connectionProvider, userAgent
|
|
|
365
373
|
updatedPullRequest = await gitApi.getPullRequest(repositoryId, pullRequestId, project);
|
|
366
374
|
}
|
|
367
375
|
const trimmedUpdatedPullRequest = trimPullRequest(updatedPullRequest, true);
|
|
376
|
+
if (!trimmedUpdatedPullRequest) {
|
|
377
|
+
return {
|
|
378
|
+
content: [{ type: "text", text: "Pull request updated but API returned no data." }],
|
|
379
|
+
};
|
|
380
|
+
}
|
|
368
381
|
return {
|
|
369
382
|
content: [{ type: "text", text: JSON.stringify(trimmedUpdatedPullRequest, null, 2) }],
|
|
370
383
|
};
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const packageVersion = "2.5.0-nightly.
|
|
1
|
+
export const packageVersion = "2.5.0-nightly.20260320";
|