Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/tools/repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri
bypassReason: z.string().optional().describe("Reason for bypassing branch policies. Used for update only when bypassPolicy is true."),
reviewerIds: z.array(z.string()).optional().describe("List of reviewer IDs. Required for update_reviewers."),
reviewerAction: z.enum(["add", "remove"]).optional().describe("Whether to add or remove reviewers. Required for update_reviewers."),
isRequired: z.boolean().optional().describe("Whether the added reviewers are required. Used for update_reviewers when reviewerAction is add. When omitted, reviewers are added as optional."),
vote: z.enum(["Approved", "ApprovedWithSuggestions", "NoVote", "WaitingForAuthor", "Rejected"]).optional().describe("The vote to cast. Required for vote."),
},
async ({
Expand All @@ -899,6 +900,7 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri
bypassReason,
reviewerIds,
reviewerAction,
isRequired,
vote,
}) => {
try {
Expand Down Expand Up @@ -1018,7 +1020,7 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri

if (reviewerAction === "add") {
const updatedReviewers = await gitApi.createPullRequestReviewers(
reviewerIds.map((id) => ({ id })),
reviewerIds.map((id) => ({ id, ...(isRequired !== undefined ? { isRequired } : {}) })),
repositoryId,
pullRequestId,
project
Expand All @@ -1029,6 +1031,7 @@ function configureRepoTools(server: McpServer, tokenProvider: () => Promise<stri
id: item.id,
uniqueName: item.uniqueName,
vote: item.vote,
isRequired: item.isRequired,
hasDeclined: item.hasDeclined,
isFlagged: item.isFlagged,
}));
Expand Down
38 changes: 38 additions & 0 deletions test/src/tools/repositories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,44 @@ describe("repos tools", () => {
expect(result.content[0].text).toBe(JSON.stringify(mockReviewers, null, 2));
});

it("should add required reviewers to pull request when isRequired is true", async () => {
configureRepoTools(server, tokenProvider, connectionProvider, userAgentProvider);

const call = (server.tool as jest.Mock).mock.calls.find(([toolName]) => toolName === REPO_TOOLS.repo_pull_request_write);
if (!call) throw new Error("repo_pull_request_write tool not registered");
const [, , , handler] = call;

const mockReviewers = [
{ id: "reviewer1", isRequired: true },
{ id: "reviewer2", isRequired: true },
];
mockGitApi.createPullRequestReviewers.mockResolvedValue(mockReviewers);

const params = {
action: "update_reviewers",
repositoryId: "repo123",
pullRequestId: 456,
project: "test-project",
reviewerIds: ["reviewer1", "reviewer2"],
reviewerAction: "add" as const,
isRequired: true,
};

const result = await handler(params);

expect(mockGitApi.createPullRequestReviewers).toHaveBeenCalledWith(
[
{ id: "reviewer1", isRequired: true },
{ id: "reviewer2", isRequired: true },
],
"repo123",
456,
"test-project"
);

expect(result.content[0].text).toBe(JSON.stringify(mockReviewers, null, 2));
});

it("should remove reviewers from pull request", async () => {
configureRepoTools(server, tokenProvider, connectionProvider, userAgentProvider);

Expand Down