-
Notifications
You must be signed in to change notification settings - Fork 302
Description
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_labelsretrieves labels from a PR - Tool
repo_update_pull_request_labelsadds labels to a PR withaction: "add" - Tool
repo_update_pull_request_labelsremoves labels from a PR withaction: "remove" - (Optional) Tool
repo_list_repository_labelslists available labels in a repository - All tools added to
REPO_TOOLSconstant with proper naming convention - Proper TypeScript interfaces imported from Azure DevOps API
- Response data is trimmed to essential properties only
- Error handling returns
isError: trueon 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
- Add/Remove pattern: Follow
repo_update_pull_request_reviewersimplementation - Response trimming: Create
trimPullRequestLabels()function similar totrimPullRequest() - Error handling: Use try/catch with
isError: trueresponse pattern - Tool naming: Follow
{category}_{action}_{entity}convention - 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 patternrepo_get_pull_request_by_id- Single entity retrieval patternrepo_list_pull_request_threads- List operation patterntrimPullRequest()- Response trimming patterntrimComments()- Array trimming pattern
Implementation Notes
- Verify label API methods exist in
azure-devops-node-apiv15.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