Skip to content

Add Pull Request Label Support to Repository Tools #682

@Meir017

Description

@Meir017

Problem Statement

The Azure DevOps MCP server currently lacks support for managing labels on pull requests. Labels are a common workflow tool in Azure DevOps for categorizing and filtering PRs, but users cannot get, add, or remove labels through the MCP server. This limits the ability to automate PR workflows and integrate label-based processes.

Current Limitations

  • Cannot retrieve labels assigned to a pull request
  • Cannot add labels to a pull request programmatically
  • Cannot remove labels from a pull request
  • Cannot discover available labels in a repository

Use Cases

  • Automated PR categorization: Apply labels based on changed files, PR size, or other criteria
  • Workflow automation: Add/remove labels as PRs progress through review stages
  • PR filtering and search: Query PRs by labels for reporting or automation
  • Integration with other tools: Sync labels between Azure DevOps and other systems

Proposed Solution

Add 3 new tools to the repository tools in src/tools/repositories.ts:

1. repo_get_pull_request_labels

Get all labels currently assigned to a pull request.

2. repo_update_pull_request_labels

Add or remove labels from a pull request using an action-based approach (similar to the existing repo_update_pull_request_reviewers tool).

3. repo_list_repository_labels (Optional)

List all available labels in a repository for discovery purposes.

Acceptance Criteria

  • Tool repo_get_pull_request_labels retrieves labels from a PR
  • Tool repo_update_pull_request_labels adds labels to a PR with action: "add"
  • Tool repo_update_pull_request_labels removes labels from a PR with action: "remove"
  • (Optional) Tool repo_list_repository_labels lists available labels in a repository
  • All tools added to REPO_TOOLS constant with proper naming convention
  • Proper TypeScript interfaces imported from Azure DevOps API
  • Response data is trimmed to essential properties only
  • Error handling returns isError: true on failures
  • Comprehensive unit tests with mocked GitApi in test/src/tools/repositories.test.ts
  • Documentation updated with usage examples in docs/EXAMPLES.md
  • ESLint tool naming validation passes

Example Usage

// Get labels on a PR
await mcp.call("repo_get_pull_request_labels", {
  repositoryId: "abc123",
  pullRequestId: 42
});

// Add labels to a PR
await mcp.call("repo_update_pull_request_labels", {
  repositoryId: "abc123",
  pullRequestId: 42,
  labels: ["bug", "high-priority"],
  action: "add"
});

// Remove labels from a PR
await mcp.call("repo_update_pull_request_labels", {
  repositoryId: "abc123",
  pullRequestId: 42,
  labels: ["needs-review"],
  action: "remove"
});

Technical Implementation Details

API Methods to Use

From azure-devops-node-api GitApi interface:

  • getPullRequestLabels(repositoryId, pullRequestId, project?)
  • createPullRequestLabel(label, repositoryId, pullRequestId, project?)
  • deletePullRequestLabels(repositoryId, pullRequestId, labelId, project?)

Required Imports

Add to src/tools/repositories.ts:

import {
  // ... existing imports
  WebApiTagDefinition,  // or GitPullRequestLabel - verify exact interface name
} from "azure-devops-node-api/interfaces/GitInterfaces.js";

Tool Schema Definitions

repo_get_pull_request_labels:

{
  repositoryId: z.string().describe("The ID of the repository"),
  pullRequestId: z.number().describe("The ID of the pull request"),
  project: z.string().optional().describe("Project name or ID (optional)")
}

repo_update_pull_request_labels:

{
  repositoryId: z.string().describe("The ID of the repository"),
  pullRequestId: z.number().describe("The ID of the pull request"),
  labels: z.array(z.string()).describe("Array of label names to add/remove"),
  action: z.enum(["add", "remove"]).describe("Action to perform on labels"),
  project: z.string().optional().describe("Project name or ID (optional)")
}

Code Patterns to Follow

  1. Add/Remove pattern: Follow repo_update_pull_request_reviewers implementation
  2. Response trimming: Create trimPullRequestLabels() function similar to trimPullRequest()
  3. Error handling: Use try/catch with isError: true response pattern
  4. Tool naming: Follow {category}_{action}_{entity} convention
  5. Optional project parameter: Include as optional last parameter like other tools

Response Trimming Function

function trimPullRequestLabels(labels: WebApiTagDefinition[] | undefined) {
  return labels?.map((label) => ({
    id: label.id,
    name: label.name,
    active: label.active,
  }));
}

Testing Requirements

Add tests to test/src/tools/repositories.test.ts:

  • Test getting labels from a PR
  • Test adding single and multiple labels
  • Test removing single and multiple labels
  • Test error handling for invalid repository/PR IDs
  • Test optional project parameter
  • Mock all GitApi label methods appropriately

Related Code References

  • repo_update_pull_request_reviewers - Add/remove action pattern
  • repo_get_pull_request_by_id - Single entity retrieval pattern
  • repo_list_pull_request_threads - List operation pattern
  • trimPullRequest() - Response trimming pattern
  • trimComments() - Array trimming pattern

Implementation Notes

  • Verify label API methods exist in azure-devops-node-api v15.1.0
  • Handle both label IDs and label names if the API supports both
  • Consider whether labels are auto-created when added or must pre-exist
  • Ensure ESLint tool name validation passes
  • Follow existing error message formatting patterns

Metadata

Metadata

Assignees

Labels

Needs Review 👓needs review by the product teamRepos 📁issue in the repos area

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions