Skip to content

Commit 69b2928

Browse files
authored
add branch parameter to configureWikiTools for wiki page operations (microsoft#509)
According to the official documentation (https://learn.microsoft.com/en-us/rest/api/azure/devops/wiki/pages/create-or-update?view=azure-devops-rest-7.1&tabs=HTTP) following fields are required; - versionDescriptor.versionType - versionDescriptor.version `versionType` field could be `branch` and `version` field could be the name of the `branch` that wiki is published to. Default branch name for wikis is; `wikiMaster` ## GitHub issue number Fixes microsoft#490 ## **Associated Risks** None ## ✅ **PR Checklist** - [x] **I have read the [contribution guidelines](https://github.com/microsoft/azure-devops-mcp/blob/main/CONTRIBUTING.md)** - [x] **I have read the [code of conduct guidelines](https://github.com/microsoft/azure-devops-mcp/blob/main/CODE_OF_CONDUCT.md)** - [x] Title of the pull request is clear and informative. - [x] 👌 Code hygiene - [x] 🔭 Telemetry added, updated, or N/A - [x] 📄 Documentation added, updated, or N/A - [x] 🛡️ Automated tests added, or N/A ## 🧪 **How did you test it?** Run `npm test`
1 parent 19c52f6 commit 69b2928

File tree

2 files changed

+65
-13
lines changed

2 files changed

+65
-13
lines changed

src/tools/wiki.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,9 @@ function configureWikiTools(server: McpServer, tokenProvider: () => Promise<Acce
220220
content: z.string().describe("The content of the wiki page in markdown format."),
221221
project: z.string().optional().describe("The project name or ID where the wiki is located. If not provided, the default project will be used."),
222222
etag: z.string().optional().describe("ETag for editing existing pages (optional, will be fetched if not provided)."),
223+
branch: z.string().default("wikiMaster").describe("The branch name for the wiki repository. Defaults to 'wikiMaster' which is the default branch for Azure DevOps wikis."),
223224
},
224-
async ({ wikiIdentifier, path, content, project, etag }) => {
225+
async ({ wikiIdentifier, path, content, project, etag, branch = "wikiMaster" }) => {
225226
try {
226227
const connection = await connectionProvider();
227228
const accessToken = await tokenProvider();
@@ -230,10 +231,10 @@ function configureWikiTools(server: McpServer, tokenProvider: () => Promise<Acce
230231
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
231232
const encodedPath = encodeURIComponent(normalizedPath);
232233

233-
// Build the URL for the wiki page API
234+
// Build the URL for the wiki page API with version descriptor
234235
const baseUrl = connection.serverUrl;
235236
const projectParam = project || "";
236-
const url = `${baseUrl}/${projectParam}/_apis/wiki/wikis/${wikiIdentifier}/pages?path=${encodedPath}&api-version=7.1`;
237+
const url = `${baseUrl}/${projectParam}/_apis/wiki/wikis/${wikiIdentifier}/pages?path=${encodedPath}&versionDescriptor.versionType=branch&versionDescriptor.version=${encodeURIComponent(branch)}&api-version=7.1`;
237238

238239
// First, try to create a new page (PUT without ETag)
239240
try {

test/src/tools/wiki.test.ts

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -755,14 +755,17 @@ describe("configureWikiTools", () => {
755755

756756
const result = await handler(params);
757757

758-
expect(mockFetch).toHaveBeenCalledWith("https://dev.azure.com/testorg/proj1/_apis/wiki/wikis/wiki1/pages?path=%2FHome&api-version=7.1", {
759-
method: "PUT",
760-
headers: {
761-
"Authorization": "Bearer test-token",
762-
"Content-Type": "application/json",
763-
},
764-
body: JSON.stringify({ content: "# Welcome\nThis is the home page." }),
765-
});
758+
expect(mockFetch).toHaveBeenCalledWith(
759+
"https://dev.azure.com/testorg/proj1/_apis/wiki/wikis/wiki1/pages?path=%2FHome&versionDescriptor.versionType=branch&versionDescriptor.version=wikiMaster&api-version=7.1",
760+
{
761+
method: "PUT",
762+
headers: {
763+
"Authorization": "Bearer test-token",
764+
"Content-Type": "application/json",
765+
},
766+
body: JSON.stringify({ content: "# Welcome\nThis is the home page." }),
767+
}
768+
);
766769
expect(result.content[0].text).toContain("Successfully created wiki page at path: /Home");
767770
expect(result.isError).toBeUndefined();
768771
});
@@ -1176,7 +1179,10 @@ describe("configureWikiTools", () => {
11761179

11771180
const result = await handler(params);
11781181

1179-
expect(mockFetch).toHaveBeenCalledWith("https://dev.azure.com/testorg/proj1/_apis/wiki/wikis/wiki1/pages?path=%2FHome&api-version=7.1", expect.any(Object));
1182+
expect(mockFetch).toHaveBeenCalledWith(
1183+
"https://dev.azure.com/testorg/proj1/_apis/wiki/wikis/wiki1/pages?path=%2FHome&versionDescriptor.versionType=branch&versionDescriptor.version=wikiMaster&api-version=7.1",
1184+
expect.any(Object)
1185+
);
11801186
expect(result.content[0].text).toContain("Successfully created wiki page at path: /Home");
11811187
});
11821188

@@ -1206,7 +1212,10 @@ describe("configureWikiTools", () => {
12061212

12071213
const result = await handler(params);
12081214

1209-
expect(mockFetch).toHaveBeenCalledWith("https://dev.azure.com/testorg//_apis/wiki/wikis/wiki1/pages?path=%2FHome&api-version=7.1", expect.any(Object));
1215+
expect(mockFetch).toHaveBeenCalledWith(
1216+
"https://dev.azure.com/testorg//_apis/wiki/wikis/wiki1/pages?path=%2FHome&versionDescriptor.versionType=branch&versionDescriptor.version=wikiMaster&api-version=7.1",
1217+
expect.any(Object)
1218+
);
12101219
expect(result.content[0].text).toContain("Successfully created wiki page at path: /Home");
12111220
});
12121221

@@ -1242,5 +1251,47 @@ describe("configureWikiTools", () => {
12421251
expect(result.isError).toBe(true);
12431252
expect(result.content[0].text).toContain("Error creating/updating wiki page: Could not retrieve ETag for existing page");
12441253
});
1254+
1255+
it("should use custom branch when specified", async () => {
1256+
configureWikiTools(server, tokenProvider, connectionProvider);
1257+
const call = (server.tool as jest.Mock).mock.calls.find(([toolName]) => toolName === "wiki_create_or_update_page");
1258+
if (!call) throw new Error("wiki_create_or_update_page tool not registered");
1259+
const [, , , handler] = call;
1260+
1261+
const mockResponse = {
1262+
path: "/Home",
1263+
id: 123,
1264+
content: "# Welcome",
1265+
};
1266+
1267+
mockFetch.mockResolvedValueOnce({
1268+
ok: true,
1269+
json: jest.fn().mockResolvedValue(mockResponse),
1270+
});
1271+
1272+
const params = {
1273+
wikiIdentifier: "wiki1",
1274+
path: "/Home",
1275+
content: "# Welcome",
1276+
project: "proj1",
1277+
branch: "main",
1278+
};
1279+
1280+
const result = await handler(params);
1281+
1282+
expect(mockFetch).toHaveBeenCalledWith(
1283+
"https://dev.azure.com/testorg/proj1/_apis/wiki/wikis/wiki1/pages?path=%2FHome&versionDescriptor.versionType=branch&versionDescriptor.version=main&api-version=7.1",
1284+
{
1285+
method: "PUT",
1286+
headers: {
1287+
"Authorization": "Bearer test-token",
1288+
"Content-Type": "application/json",
1289+
},
1290+
body: JSON.stringify({ content: "# Welcome" }),
1291+
}
1292+
);
1293+
expect(result.content[0].text).toContain("Successfully created wiki page at path: /Home");
1294+
expect(result.isError).toBeUndefined();
1295+
});
12451296
});
12461297
});

0 commit comments

Comments
 (0)