This is page 8 of 8. Use http://codebase.md/tiberriver256/azure-devops-mcp?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .clinerules ├── .env.example ├── .eslintrc.json ├── .github │ ├── FUNDING.yml │ ├── release-please-config.json │ ├── release-please-manifest.json │ └── workflows │ ├── main.yml │ └── release-please.yml ├── .gitignore ├── .husky │ ├── commit-msg │ └── pre-commit ├── .kilocode │ └── mcp.json ├── .prettierrc ├── .vscode │ └── settings.json ├── CHANGELOG.md ├── commitlint.config.js ├── CONTRIBUTING.md ├── create_branch.sh ├── docs │ ├── authentication.md │ ├── azure-identity-authentication.md │ ├── ci-setup.md │ ├── examples │ │ ├── azure-cli-authentication.env │ │ ├── azure-identity-authentication.env │ │ ├── pat-authentication.env │ │ └── README.md │ ├── testing │ │ ├── README.md │ │ └── setup.md │ └── tools │ ├── core-navigation.md │ ├── organizations.md │ ├── pipelines.md │ ├── projects.md │ ├── pull-requests.md │ ├── README.md │ ├── repositories.md │ ├── resources.md │ ├── search.md │ ├── user-tools.md │ ├── wiki.md │ └── work-items.md ├── finish_task.sh ├── jest.e2e.config.js ├── jest.int.config.js ├── jest.unit.config.js ├── LICENSE ├── memory │ └── tasks_memory_2025-05-26T16-18-03.json ├── package-lock.json ├── package.json ├── project-management │ ├── planning │ │ ├── architecture-guide.md │ │ ├── azure-identity-authentication-design.md │ │ ├── project-plan.md │ │ ├── project-structure.md │ │ ├── tech-stack.md │ │ └── the-dream-team.md │ ├── startup.xml │ ├── tdd-cycle.xml │ └── troubleshooter.xml ├── README.md ├── setup_env.sh ├── shrimp-rules.md ├── src │ ├── clients │ │ └── azure-devops.ts │ ├── features │ │ ├── organizations │ │ │ ├── __test__ │ │ │ │ └── test-helpers.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── list-organizations │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── schemas.ts │ │ │ ├── tool-definitions.ts │ │ │ └── types.ts │ │ ├── pipelines │ │ │ ├── get-pipeline │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── list-pipelines │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── tool-definitions.ts │ │ │ ├── trigger-pipeline │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ └── types.ts │ │ ├── projects │ │ │ ├── __test__ │ │ │ │ └── test-helpers.ts │ │ │ ├── get-project │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-project-details │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── list-projects │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── schemas.ts │ │ │ ├── tool-definitions.ts │ │ │ └── types.ts │ │ ├── pull-requests │ │ │ ├── add-pull-request-comment │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ └── index.ts │ │ │ ├── create-pull-request │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-pull-request-comments │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ └── index.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── list-pull-requests │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── schemas.ts │ │ │ ├── tool-definitions.ts │ │ │ ├── types.ts │ │ │ └── update-pull-request │ │ │ ├── feature.spec.int.ts │ │ │ ├── feature.spec.unit.ts │ │ │ ├── feature.ts │ │ │ └── index.ts │ │ ├── repositories │ │ │ ├── __test__ │ │ │ │ └── test-helpers.ts │ │ │ ├── get-all-repositories-tree │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── feature.spec.unit.ts.snap │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-file-content │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-repository │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-repository-details │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── list-repositories │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── schemas.ts │ │ │ ├── tool-definitions.ts │ │ │ └── types.ts │ │ ├── search │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── schemas.ts │ │ │ ├── search-code │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ └── index.ts │ │ │ ├── search-wiki │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ └── index.ts │ │ │ ├── search-work-items │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ └── index.ts │ │ │ ├── tool-definitions.ts │ │ │ └── types.ts │ │ ├── users │ │ │ ├── get-me │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── schemas.ts │ │ │ ├── tool-definitions.ts │ │ │ └── types.ts │ │ ├── wikis │ │ │ ├── create-wiki │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── create-wiki-page │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-wiki-page │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── get-wikis │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── index.spec.unit.ts │ │ │ ├── index.ts │ │ │ ├── list-wiki-pages │ │ │ │ ├── feature.spec.int.ts │ │ │ │ ├── feature.spec.unit.ts │ │ │ │ ├── feature.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ │ ├── tool-definitions.ts │ │ │ └── update-wiki-page │ │ │ ├── feature.spec.int.ts │ │ │ ├── feature.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ └── work-items │ │ ├── __test__ │ │ │ ├── fixtures.ts │ │ │ ├── test-helpers.ts │ │ │ └── test-utils.ts │ │ ├── create-work-item │ │ │ ├── feature.spec.int.ts │ │ │ ├── feature.spec.unit.ts │ │ │ ├── feature.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ ├── get-work-item │ │ │ ├── feature.spec.int.ts │ │ │ ├── feature.spec.unit.ts │ │ │ ├── feature.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ ├── index.spec.unit.ts │ │ ├── index.ts │ │ ├── list-work-items │ │ │ ├── feature.spec.int.ts │ │ │ ├── feature.spec.unit.ts │ │ │ ├── feature.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ ├── manage-work-item-link │ │ │ ├── feature.spec.int.ts │ │ │ ├── feature.spec.unit.ts │ │ │ ├── feature.ts │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ ├── schemas.ts │ │ ├── tool-definitions.ts │ │ ├── types.ts │ │ └── update-work-item │ │ ├── feature.spec.int.ts │ │ ├── feature.spec.unit.ts │ │ ├── feature.ts │ │ ├── index.ts │ │ └── schema.ts │ ├── index.spec.unit.ts │ ├── index.ts │ ├── server.spec.e2e.ts │ ├── server.ts │ ├── shared │ │ ├── api │ │ │ ├── client.ts │ │ │ └── index.ts │ │ ├── auth │ │ │ ├── auth-factory.ts │ │ │ ├── client-factory.ts │ │ │ └── index.ts │ │ ├── config │ │ │ ├── index.ts │ │ │ └── version.ts │ │ ├── enums │ │ │ ├── index.spec.unit.ts │ │ │ └── index.ts │ │ ├── errors │ │ │ ├── azure-devops-errors.ts │ │ │ ├── handle-request-error.ts │ │ │ └── index.ts │ │ ├── test │ │ │ └── test-helpers.ts │ │ └── types │ │ ├── config.ts │ │ ├── index.ts │ │ ├── request-handler.ts │ │ └── tool-definition.ts │ └── utils │ ├── environment.spec.unit.ts │ └── environment.ts ├── tasks.json ├── tests │ └── setup.ts └── tsconfig.json ``` # Files -------------------------------------------------------------------------------- /docs/tools/pull-requests.md: -------------------------------------------------------------------------------- ```markdown 1 | # Azure DevOps Pull Requests Tools 2 | 3 | This document describes the tools available for working with Azure DevOps Pull Requests. 4 | 5 | ## create_pull_request 6 | 7 | Creates a new pull request in a specific Git repository. 8 | 9 | ### Description 10 | 11 | The `create_pull_request` tool creates a new pull request in a specified Azure DevOps Git repository. It allows you to propose changes from a source branch to a target branch, add a title, description, reviewers, and link to work items. Pull requests are a key part of code review and collaboration workflows in Azure DevOps. 12 | 13 | ### Parameters 14 | 15 | ```json 16 | { 17 | "projectId": "MyProject", // Required: The ID or name of the project 18 | "repositoryId": "MyRepo", // Required: The ID or name of the repository 19 | "title": "Update feature X", // Required: The title of the pull request 20 | "sourceRefName": "refs/heads/feature-branch", // Required: The source branch name 21 | "targetRefName": "refs/heads/main", // Required: The target branch name 22 | "description": "This PR implements feature X", // Optional: The description of the pull request 23 | "reviewers": ["[email protected]"], // Optional: List of reviewer email addresses or IDs 24 | "isDraft": true, // Optional: Whether the pull request should be created as a draft 25 | "workItemRefs": [123, 456] // Optional: List of work item IDs to link to the pull request 26 | } 27 | ``` 28 | 29 | | Parameter | Type | Required | Description | 30 | | --------------- | -------- | -------- | -------------------------------------------------------------- | 31 | | `projectId` | string | Yes | The ID or name of the project containing the repository | 32 | | `repositoryId` | string | Yes | The ID or name of the repository to create the pull request in | 33 | | `title` | string | Yes | The title of the pull request | 34 | | `sourceRefName` | string | Yes | The source branch name (e.g., "refs/heads/feature-branch") | 35 | | `targetRefName` | string | Yes | The target branch name (e.g., "refs/heads/main") | 36 | | `description` | string | No | The description of the pull request | 37 | | `reviewers` | string[] | No | List of reviewer email addresses or IDs | 38 | | `isDraft` | boolean | No | Whether the pull request should be created as a draft | 39 | | `workItemRefs` | number[] | No | List of work item IDs to link to the pull request | 40 | 41 | ### Response 42 | 43 | The tool returns a `PullRequest` object containing: 44 | 45 | - `pullRequestId`: The unique identifier of the created pull request 46 | - `status`: The status of the pull request (active, abandoned, completed) 47 | - `createdBy`: Information about the user who created the pull request 48 | - `creationDate`: The date and time when the pull request was created 49 | - `title`: The title of the pull request 50 | - `description`: The description of the pull request 51 | - `sourceRefName`: The source branch name 52 | - `targetRefName`: The target branch name 53 | - `mergeStatus`: The merge status of the pull request 54 | - And various other fields and references 55 | 56 | Example response: 57 | 58 | ```json 59 | { 60 | "repository": { 61 | "id": "repo-guid", 62 | "name": "MyRepo", 63 | "url": "https://dev.azure.com/organization/MyProject/_apis/git/repositories/MyRepo", 64 | "project": { 65 | "id": "project-guid", 66 | "name": "MyProject" 67 | } 68 | }, 69 | "pullRequestId": 42, 70 | "codeReviewId": 42, 71 | "status": 1, 72 | "createdBy": { 73 | "displayName": "John Doe", 74 | "id": "user-guid", 75 | "uniqueName": "[email protected]" 76 | }, 77 | "creationDate": "2023-01-01T12:00:00Z", 78 | "title": "Update feature X", 79 | "description": "This PR implements feature X", 80 | "sourceRefName": "refs/heads/feature-branch", 81 | "targetRefName": "refs/heads/main", 82 | "mergeStatus": 1, 83 | "isDraft": true, 84 | "reviewers": [ 85 | { 86 | "displayName": "Jane Smith", 87 | "id": "reviewer-guid", 88 | "uniqueName": "[email protected]", 89 | "voteResult": 0 90 | } 91 | ], 92 | "url": "https://dev.azure.com/organization/MyProject/_apis/git/repositories/MyRepo/pullRequests/42" 93 | } 94 | ``` 95 | 96 | ### Error Handling 97 | 98 | The tool may throw the following errors: 99 | 100 | - ValidationError: If required parameters are missing or invalid 101 | - AuthenticationError: If authentication fails 102 | - PermissionError: If the user doesn't have permission to create a pull request 103 | - ResourceNotFoundError: If the project, repository, or specified branches don't exist 104 | - GitError: For Git-related errors (e.g., conflicts, branch issues) 105 | - GeneralError: For other unexpected errors 106 | 107 | Error messages will include details about what went wrong and suggestions for resolution. 108 | 109 | ### Example Usage 110 | 111 | ```typescript 112 | // Basic example - create a PR from feature branch to main 113 | const pr = await mcpClient.callTool('create_pull_request', { 114 | projectId: 'MyProject', 115 | repositoryId: 'MyRepo', 116 | title: 'Add new feature', 117 | sourceRefName: 'refs/heads/feature-branch', 118 | targetRefName: 'refs/heads/main', 119 | }); 120 | console.log(`Created PR #${pr.pullRequestId}: ${pr.url}`); 121 | 122 | // Create a draft PR with description and reviewers 123 | const draftPr = await mcpClient.callTool('create_pull_request', { 124 | projectId: 'MyProject', 125 | repositoryId: 'MyRepo', 126 | title: 'WIP: Refactor authentication code', 127 | description: 128 | '# Work in Progress\n\nRefactoring authentication code to use the new identity service.', 129 | sourceRefName: 'refs/heads/auth-refactor', 130 | targetRefName: 'refs/heads/develop', 131 | isDraft: true, 132 | reviewers: ['[email protected]', '[email protected]'], 133 | }); 134 | console.log(`Created draft PR #${draftPr.pullRequestId}`); 135 | 136 | // Create a PR linked to work items 137 | const linkedPr = await mcpClient.callTool('create_pull_request', { 138 | projectId: 'MyProject', 139 | repositoryId: 'MyRepo', 140 | title: 'Fix bugs in payment processor', 141 | sourceRefName: 'refs/heads/bugfix/payment', 142 | targetRefName: 'refs/heads/main', 143 | workItemRefs: [1234, 1235, 1236], 144 | }); 145 | console.log(`Created PR #${linkedPr.pullRequestId} linked to work items`); 146 | ``` 147 | 148 | ## list_pull_requests 149 | 150 | Lists pull requests in a specific Git repository with optional filtering. 151 | 152 | ### Description 153 | 154 | The `list_pull_requests` tool retrieves pull requests from a specified Azure DevOps Git repository. It supports filtering by status (active, completed, abandoned), creator, reviewer, and source/target branches. This tool is useful for monitoring code review progress, identifying pending PRs, and automating PR-related workflows. 155 | 156 | ### Parameters 157 | 158 | ```json 159 | { 160 | "projectId": "MyProject", // Required: The ID or name of the project 161 | "repositoryId": "MyRepo", // Required: The ID or name of the repository 162 | "status": "active", // Optional: The status of pull requests to return (active, completed, abandoned, all) 163 | "creatorId": "a8a8a8a8-a8a8-a8a8-a8a8-a8a8a8a8a8a8", // Optional: Filter by creator ID (must be a UUID) 164 | "reviewerId": "b9b9b9b9-b9b9-b9b9-b9b9-b9b9b9b9b9b9", // Optional: Filter by reviewer ID (must be a UUID) 165 | "sourceRefName": "refs/heads/feature-branch", // Optional: Filter by source branch name 166 | "targetRefName": "refs/heads/main", // Optional: Filter by target branch name 167 | "top": 10, // Optional: Maximum number of pull requests to return (default: 10) 168 | "skip": 0 // Optional: Number of pull requests to skip for pagination 169 | } 170 | ``` 171 | 172 | | Parameter | Type | Required | Description | 173 | | --------------- | ------ | -------- | ----------------------------------------------------------------------------------- | 174 | | `projectId` | string | Yes | The ID or name of the project containing the repository | 175 | | `repositoryId` | string | Yes | The ID or name of the repository to list pull requests from | 176 | | `status` | string | No | The status of pull requests to return: "active", "completed", "abandoned", or "all" | 177 | | `creatorId` | string | No | Filter pull requests by creator ID (must be a UUID) | 178 | | `reviewerId` | string | No | Filter pull requests by reviewer ID (must be a UUID) | 179 | | `sourceRefName` | string | No | Filter pull requests by source branch name | 180 | | `targetRefName` | string | No | Filter pull requests by target branch name | 181 | | `top` | number | No | Maximum number of pull requests to return | 182 | 183 | ### Response 184 | 185 | The tool returns an object containing: 186 | 187 | - `count`: The number of pull requests returned 188 | - `value`: An array of `PullRequest` objects 189 | - `hasMoreResults`: A boolean indicating if there are more results available 190 | - `warning`: A message with pagination guidance (only present when hasMoreResults is true) 191 | 192 | Each pull request in the `value` array contains: 193 | 194 | - `pullRequestId`: The unique identifier of the pull request 195 | - `title`: The title of the pull request 196 | - `status`: The status of the pull request (active, abandoned, completed) 197 | - `createdBy`: Information about the user who created the pull request 198 | - `creationDate`: The date and time when the pull request was created 199 | - `sourceRefName`: The source branch name 200 | - `targetRefName`: The target branch name 201 | - And various other fields and references 202 | 203 | Example response: 204 | 205 | ```json 206 | { 207 | "count": 2, 208 | "value": [ 209 | { 210 | "repository": { 211 | "id": "repo-guid", 212 | "name": "MyRepo", 213 | "project": { 214 | "id": "project-guid", 215 | "name": "MyProject" 216 | } 217 | }, 218 | "pullRequestId": 42, 219 | "codeReviewId": 42, 220 | "status": 1, 221 | "createdBy": { 222 | "displayName": "John Doe", 223 | "uniqueName": "[email protected]" 224 | }, 225 | "creationDate": "2023-01-01T12:00:00Z", 226 | "title": "Update feature X", 227 | "description": "This PR implements feature X", 228 | "sourceRefName": "refs/heads/feature-branch", 229 | "targetRefName": "refs/heads/main", 230 | "mergeStatus": 3, 231 | "isDraft": false, 232 | "url": "https://dev.azure.com/organization/MyProject/_apis/git/repositories/MyRepo/pullRequests/42" 233 | }, 234 | { 235 | "repository": { 236 | "id": "repo-guid", 237 | "name": "MyRepo", 238 | "project": { 239 | "id": "project-guid", 240 | "name": "MyProject" 241 | } 242 | }, 243 | "pullRequestId": 43, 244 | "codeReviewId": 43, 245 | "status": 1, 246 | "createdBy": { 247 | "displayName": "Jane Smith", 248 | "uniqueName": "[email protected]" 249 | }, 250 | "creationDate": "2023-01-02T14:30:00Z", 251 | "title": "Fix bug in login flow", 252 | "description": "This PR fixes a critical bug in the login flow", 253 | "sourceRefName": "refs/heads/bugfix/login", 254 | "targetRefName": "refs/heads/main", 255 | "mergeStatus": 3, 256 | "isDraft": false, 257 | "url": "https://dev.azure.com/organization/MyProject/_apis/git/repositories/MyRepo/pullRequests/43" 258 | } 259 | ], 260 | "hasMoreResults": false 261 | } 262 | ``` 263 | 264 | ### Error Handling 265 | 266 | The tool may throw the following errors: 267 | 268 | - ValidationError: If required parameters are missing or invalid 269 | - AuthenticationError: If authentication fails 270 | - PermissionError: If the user doesn't have permission to list pull requests 271 | - ResourceNotFoundError: If the project or repository doesn't exist 272 | - GeneralError: For other unexpected errors 273 | 274 | Error messages will include details about what went wrong and suggestions for resolution. 275 | 276 | ### Example Usage 277 | 278 | ```typescript 279 | // List all active pull requests in a repository 280 | const activePRs = await mcpClient.callTool('list_pull_requests', { 281 | projectId: 'MyProject', 282 | repositoryId: 'MyRepo', 283 | status: 'active', 284 | }); 285 | console.log(`Found ${activePRs.count} active pull requests`); 286 | 287 | // List pull requests created by a specific user (using their UUID) 288 | const userPRs = await mcpClient.callTool('list_pull_requests', { 289 | projectId: 'MyProject', 290 | repositoryId: 'MyRepo', 291 | creatorId: 'a8a8a8a8-a8a8-a8a8-a8a8-a8a8a8a8a8a8', 292 | }); 293 | console.log(`Found ${userPRs.count} pull requests created by this user`); 294 | 295 | // List pull requests targeting a specific branch 296 | const mainPRs = await mcpClient.callTool('list_pull_requests', { 297 | projectId: 'MyProject', 298 | repositoryId: 'MyRepo', 299 | targetRefName: 'refs/heads/main', 300 | }); 301 | console.log(`Found ${mainPRs.count} pull requests targeting main branch`); 302 | 303 | // Paginate through pull requests 304 | const page1 = await mcpClient.callTool('list_pull_requests', { 305 | projectId: 'MyProject', 306 | repositoryId: 'MyRepo', 307 | top: 10, 308 | skip: 0, 309 | }); 310 | 311 | // Check if there are more results and get the next page 312 | let page2 = { count: 0, value: [] }; 313 | if (page1.hasMoreResults) { 314 | page2 = await mcpClient.callTool('list_pull_requests', { 315 | projectId: 'MyProject', 316 | repositoryId: 'MyRepo', 317 | top: 10, 318 | skip: 10, 319 | }); 320 | } 321 | 322 | console.log(`Retrieved ${page1.count + page2.count} pull requests in 2 pages`); 323 | ``` 324 | 325 | ### Pagination 326 | 327 | The `list_pull_requests` tool supports pagination to handle large result sets. By default, results are limited to 10 pull requests per request to prevent performance issues. 328 | 329 | #### Pagination Parameters 330 | 331 | - `top`: Maximum number of pull requests to return (default: 10) 332 | - `skip`: Number of pull requests to skip for pagination 333 | 334 | #### Example: Paginating through all pull requests 335 | 336 | ```typescript 337 | // Get first page (10 items) 338 | const firstPage = await mcpClient.callTool('list_pull_requests', { 339 | projectId: 'MyProject', 340 | repositoryId: 'MyRepo', 341 | }); 342 | 343 | // Check if there are more results 344 | if (firstPage.hasMoreResults) { 345 | // Get second page 346 | const secondPage = await mcpClient.callTool('list_pull_requests', { 347 | projectId: 'MyProject', 348 | repositoryId: 'MyRepo', 349 | skip: 10, 350 | }); 351 | 352 | // Continue until no more results 353 | if (secondPage.hasMoreResults) { 354 | const thirdPage = await mcpClient.callTool('list_pull_requests', { 355 | projectId: 'MyProject', 356 | repositoryId: 'MyRepo', 357 | skip: 20, 358 | }); 359 | } 360 | } 361 | ``` 362 | 363 | #### Handling Large Repositories 364 | 365 | When working with repositories that have many pull requests, it's recommended to use pagination to avoid performance issues. The `list_pull_requests` tool now limits results to 10 by default to prevent issues with very large responses. 366 | 367 | If you need to process all pull requests, use the pagination pattern shown above to iterate through the results in manageable chunks. 368 | 369 | ### Implementation Details 370 | 371 | The `list_pull_requests` tool: 372 | 373 | 1. Establishes a connection to Azure DevOps using the provided credentials 374 | 2. Retrieves the Git API client 375 | 3. Constructs a search criteria object based on the provided filters 376 | 4. Maps status strings to Azure DevOps PullRequestStatus enum values 377 | 5. Makes the API call to retrieve the pull requests with pagination parameters 378 | 6. Determines if there are more results available 379 | 7. Returns an enhanced response object with count, value, hasMoreResults, and warning 380 | 8. Handles errors and provides meaningful error messages 381 | 382 | This implementation provides a robust and flexible way to retrieve pull requests from Azure DevOps repositories while preventing infinite loop issues. 383 | 384 | ## get_pull_request_comments 385 | 386 | Gets comments and comment threads from a specific pull request. 387 | 388 | ### Description 389 | 390 | The `get_pull_request_comments` tool retrieves comment threads and their associated comments from a specific pull request in an Azure DevOps Git repository. It allows you to get all comments or filter for a specific thread, and supports options for including deleted comments and limiting the number of results. This tool is useful for reviewing feedback on code changes, monitoring discussions, and integrating pull request comments into external workflows. 391 | 392 | ### Parameters 393 | 394 | ```json 395 | { 396 | "projectId": "MyProject", // Required: The ID or name of the project 397 | "repositoryId": "MyRepo", // Required: The ID or name of the repository 398 | "pullRequestId": 42, // Required: The ID of the pull request 399 | "threadId": 123, // Optional: The ID of a specific thread to retrieve 400 | "includeDeleted": false, // Optional: Whether to include deleted comments 401 | "top": 50 // Optional: Maximum number of threads to return 402 | } 403 | ``` 404 | 405 | | Parameter | Type | Required | Description | 406 | | ---------------- | ------- | -------- | ------------------------------------------------------------------------------ | 407 | | `projectId` | string | Yes | The ID or name of the project containing the repository | 408 | | `repositoryId` | string | Yes | The ID or name of the repository containing the pull request | 409 | | `pullRequestId` | number | Yes | The ID of the pull request to get comments from | 410 | | `threadId` | number | No | The ID of a specific thread to retrieve (if omitted, all threads are returned) | 411 | | `includeDeleted` | boolean | No | Whether to include deleted comments in the results | 412 | | `top` | number | No | Maximum number of comment threads to return | 413 | 414 | ### Response 415 | 416 | The tool returns an array of `GitPullRequestCommentThread` objects, each containing: 417 | 418 | - `id`: The unique identifier of the thread 419 | - `status`: The status of the thread (active, fixed, closed, etc.) 420 | - `threadContext`: Information about the location of the thread in the code (file path, line numbers) 421 | - `comments`: An array of comments within the thread 422 | - And various other fields and references 423 | 424 | Each comment in the thread contains: 425 | 426 | - `id`: The unique identifier of the comment 427 | - `content`: The text content of the comment 428 | - `commentType`: The type of comment (code change, general, etc.) 429 | - `author`: Information about the user who created the comment 430 | - `publishedDate`: The date and time when the comment was published 431 | - `filePath`: The path of the file the comment is associated with (if any) 432 | - `leftFileStart`: The start position in the left file (object with `line` and `offset`), or null 433 | - `leftFileEnd`: The end position in the left file (object with `line` and `offset`), or null 434 | - `rightFileStart`: The start position in the right file (object with `line` and `offset`), or null 435 | - `rightFileEnd`: The end position in the right file (object with `line` and `offset`), or null 436 | - And various other fields and references 437 | 438 | Example response: 439 | 440 | ```json 441 | [ 442 | { 443 | "id": 123, 444 | "status": 1, 445 | "threadContext": { 446 | "filePath": "/src/app.ts", 447 | "rightFileStart": { 448 | "line": 10, 449 | "offset": 5 450 | }, 451 | "rightFileEnd": { 452 | "line": 10, 453 | "offset": 15 454 | } 455 | }, 456 | "comments": [ 457 | { 458 | "id": 456, 459 | "content": "This variable name is not descriptive enough.", 460 | "commentType": 1, 461 | "author": { 462 | "displayName": "Jane Smith", 463 | "id": "user-guid", 464 | "uniqueName": "[email protected]" 465 | }, 466 | "publishedDate": "2023-04-15T14:30:00Z", 467 | "filePath": "/src/app.ts", 468 | "rightFileStart": { "line": 10, "offset": 5 }, 469 | "rightFileEnd": { "line": 10, "offset": 15 }, 470 | "leftFileStart": undefined, 471 | "leftFileEnd": undefined 472 | }, 473 | { 474 | "id": 457, 475 | "parentCommentId": 456, 476 | "content": "Good point, I'll rename it to be more descriptive.", 477 | "commentType": 1, 478 | "author": { 479 | "displayName": "John Doe", 480 | "id": "user-guid-2", 481 | "uniqueName": "[email protected]" 482 | }, 483 | "publishedDate": "2023-04-15T14:35:00Z", 484 | "filePath": "/src/app.ts", 485 | "rightFileStart": { "line": 10, "offset": 5 }, 486 | "rightFileEnd": { "line": 10, "offset": 15 }, 487 | "leftFileStart": undefined, 488 | "leftFileEnd": undefined 489 | } 490 | ], 491 | "isDeleted": false 492 | }, 493 | { 494 | "id": 124, 495 | "status": 2, 496 | "comments": [ 497 | { 498 | "id": 458, 499 | "content": "Can you add more validation here?", 500 | "commentType": 1, 501 | "author": { 502 | "displayName": "Jane Smith", 503 | "id": "user-guid", 504 | "uniqueName": "[email protected]" 505 | }, 506 | "publishedDate": "2023-04-15T14:40:00Z", 507 | "filePath": null, 508 | "rightFileStart": undefined, 509 | "rightFileEnd": undefined, 510 | "leftFileStart": undefined, 511 | "leftFileEnd": undefined 512 | } 513 | ], 514 | "isDeleted": false 515 | } 516 | ] 517 | ``` 518 | 519 | ### Error Handling 520 | 521 | The tool may throw the following errors: 522 | 523 | - ValidationError: If required parameters are missing or invalid 524 | - AuthenticationError: If authentication fails 525 | - PermissionError: If the user doesn't have permission to access the pull request comments 526 | - ResourceNotFoundError: If the project, repository, pull request, or thread doesn't exist 527 | - GeneralError: For other unexpected errors 528 | 529 | Error messages will include details about what went wrong and suggestions for resolution. 530 | 531 | ### Example Usage 532 | 533 | ```typescript 534 | // Get all comments from a pull request 535 | const comments = await mcpClient.callTool('get_pull_request_comments', { 536 | projectId: 'MyProject', 537 | repositoryId: 'MyRepo', 538 | pullRequestId: 42, 539 | }); 540 | 541 | // Get comments with file path and line number information 542 | comments.forEach(thread => { 543 | thread.comments?.forEach(comment => { 544 | if (comment.filePath && comment.rightFileStart && comment.rightFileEnd) { 545 | console.log(`Comment on ${comment.filePath}:${comment.rightFileStart.line}-${comment.rightFileEnd.line}: ${comment.content}`); 546 | } else { 547 | console.log(`General comment: ${comment.content}`); 548 | } 549 | }); 550 | }); 551 | 552 | // Get a specific thread by ID 553 | const thread = await mcpClient.callTool('get_pull_request_comments', { 554 | projectId: 'MyProject', 555 | repositoryId: 'MyRepo', 556 | pullRequestId: 42, 557 | threadId: 123, 558 | }); 559 | 560 | // Get comments with pagination 561 | const firstPage = await mcpClient.callTool('get_pull_request_comments', { 562 | projectId: 'MyProject', 563 | repositoryId: 'MyRepo', 564 | pullRequestId: 42, 565 | top: 10, 566 | }); 567 | ``` 568 | 569 | ### Implementation Details 570 | 571 | The `get_pull_request_comments` tool: 572 | 573 | 1. Establishes a connection to Azure DevOps using the provided credentials 574 | 2. Retrieves the Git API client 575 | 3. Gets the comment threads from the pull request 576 | 4. For each thread: 577 | - Extracts file path and line number information from the thread context 578 | - Adds these fields to each comment in the thread 579 | - Uses rightFileStart.line for line number if available, falls back to leftFileStart.line 580 | 5. Returns the transformed threads with enhanced comment information 581 | 6. Handles errors and provides meaningful error messages 582 | 583 | This implementation provides a robust way to retrieve and analyze pull request comments from Azure DevOps repositories, with enhanced file and line number information for better code review integration. 584 | 585 | ## add_pull_request_comment 586 | 587 | Adds a comment to a pull request, either as a reply to an existing comment or as a new thread. 588 | 589 | ### Description 590 | 591 | The `add_pull_request_comment` tool allows you to create new comments in pull requests in Azure DevOps. You can either: 592 | 593 | 1. Add a reply to an existing comment thread 594 | 2. Create a new thread with a comment in the general discussion 595 | 3. Create a new thread with a comment on a specific file at a specific line 596 | 597 | This tool is useful for providing feedback on pull requests, engaging in code review discussions, and automating comment workflows. 598 | 599 | ### Parameters 600 | 601 | ```json 602 | { 603 | "projectId": "MyProject", // Required: The ID or name of the project 604 | "repositoryId": "MyRepo", // Required: The ID or name of the repository 605 | "pullRequestId": 42, // Required: The ID of the pull request 606 | "content": "This looks good, let's merge!", // Required: The content of the comment 607 | "threadId": 123, // Optional: The ID of the thread to add the comment to (for replying) 608 | "parentCommentId": 456, // Optional: The ID of the parent comment (for threaded replies) 609 | "filePath": "/src/app.ts", // Optional: The path of the file to comment on (for file comments) 610 | "lineNumber": 42, // Optional: The line number to comment on (for file comments) 611 | "status": "active" // Optional: The status to set for a new thread (active, fixed, wontFix, closed, pending) 612 | } 613 | ``` 614 | 615 | | Parameter | Type | Required | Description | 616 | | ----------------- | ------ | -------- | ------------------------------------------------------------------------------------------------ | 617 | | `projectId` | string | Yes | The ID or name of the project containing the repository | 618 | | `repositoryId` | string | Yes | The ID or name of the repository containing the pull request | 619 | | `pullRequestId` | number | Yes | The ID of the pull request to comment on | 620 | | `content` | string | Yes | The text content of the comment | 621 | | `threadId` | number | No | The ID of an existing thread to add the comment to. Required when replying to an existing thread | 622 | | `parentCommentId` | number | No | ID of the parent comment when replying to a specific comment in a thread | 623 | | `filePath` | string | No | The path of the file to comment on (for creating a new thread on a file) | 624 | | `lineNumber` | number | No | The line number to comment on (for creating a new thread on a file) | 625 | | `status` | string | No | The status to set for a new thread: "active", "fixed", "wontFix", "closed", or "pending" | 626 | 627 | ### Response 628 | 629 | When adding a comment to an existing thread, the tool returns an object containing: 630 | 631 | - `comment`: The created comment object with details like ID, content, and author 632 | 633 | When creating a new thread with a comment, the tool returns an object containing: 634 | 635 | - `comment`: The created comment object 636 | - `thread`: The created thread object with details like ID, status, and context 637 | 638 | Example response for replying to an existing thread: 639 | 640 | ```json 641 | { 642 | "comment": { 643 | "id": 101, 644 | "content": "I agree with the suggestion", 645 | "commentType": 1, 646 | "parentCommentId": 100, 647 | "author": { 648 | "displayName": "John Doe", 649 | "id": "user-guid", 650 | "uniqueName": "[email protected]" 651 | }, 652 | "publishedDate": "2023-05-15T10:23:45Z" 653 | } 654 | } 655 | ``` 656 | 657 | Example response for creating a new thread on a file: 658 | 659 | ```json 660 | { 661 | "comment": { 662 | "id": 200, 663 | "content": "This variable name should be more descriptive", 664 | "commentType": 1, 665 | "author": { 666 | "displayName": "John Doe", 667 | "id": "user-guid", 668 | "uniqueName": "[email protected]" 669 | }, 670 | "publishedDate": "2023-05-15T10:30:12Z" 671 | }, 672 | "thread": { 673 | "id": 50, 674 | "status": 1, 675 | "threadContext": { 676 | "filePath": "/src/app.ts", 677 | "rightFileStart": { 678 | "line": 42, 679 | "offset": 1 680 | }, 681 | "rightFileEnd": { 682 | "line": 42, 683 | "offset": 1 684 | } 685 | }, 686 | "comments": [ 687 | { 688 | "id": 200, 689 | "content": "This variable name should be more descriptive", 690 | "commentType": 1, 691 | "author": { 692 | "displayName": "John Doe", 693 | "id": "user-guid", 694 | "uniqueName": "[email protected]" 695 | }, 696 | "publishedDate": "2023-05-15T10:30:12Z" 697 | } 698 | ] 699 | } 700 | } 701 | ``` 702 | 703 | ### Error Handling 704 | 705 | The tool may throw the following errors: 706 | 707 | - ValidationError: If required parameters are missing or invalid 708 | - AuthenticationError: If authentication fails 709 | - PermissionError: If the user doesn't have permission to comment on the pull request 710 | - ResourceNotFoundError: If the project, repository, pull request, or thread doesn't exist 711 | - GeneralError: For other unexpected errors 712 | 713 | Error messages will include details about what went wrong and suggestions for resolution. 714 | 715 | ### Example Usage 716 | 717 | ```typescript 718 | // Reply to an existing thread in a pull request 719 | const reply = await mcpClient.callTool('add_pull_request_comment', { 720 | projectId: 'MyProject', 721 | repositoryId: 'MyRepo', 722 | pullRequestId: 42, 723 | threadId: 123, 724 | content: 'I agree with the suggestion, let me implement this change.', 725 | }); 726 | console.log(`Created reply with ID ${reply.comment.id}`); 727 | 728 | // Reply to a specific comment in a thread 729 | const threadedReply = await mcpClient.callTool('add_pull_request_comment', { 730 | projectId: 'MyProject', 731 | repositoryId: 'MyRepo', 732 | pullRequestId: 42, 733 | threadId: 123, 734 | parentCommentId: 456, 735 | content: 'Specifically addressing your point about error handling.', 736 | }); 737 | console.log(`Created threaded reply with ID ${threadedReply.comment.id}`); 738 | 739 | // Create a new general discussion thread in a pull request 740 | const newThread = await mcpClient.callTool('add_pull_request_comment', { 741 | projectId: 'MyProject', 742 | repositoryId: 'MyRepo', 743 | pullRequestId: 42, 744 | content: 745 | "Overall this looks good, but let's discuss the error handling approach.", 746 | }); 747 | console.log(`Created new thread with ID ${newThread.thread.id}`); 748 | 749 | // Create a comment on a specific file and line 750 | const fileComment = await mcpClient.callTool('add_pull_request_comment', { 751 | projectId: 'MyProject', 752 | repositoryId: 'MyRepo', 753 | pullRequestId: 42, 754 | content: 'This variable name should be more descriptive.', 755 | filePath: '/src/app.ts', 756 | lineNumber: 42, 757 | }); 758 | console.log( 759 | `Created file comment with ID ${fileComment.comment.id} in thread ${fileComment.thread.id}`, 760 | ); 761 | 762 | // Create a comment with thread status 763 | const statusComment = await mcpClient.callTool('add_pull_request_comment', { 764 | projectId: 'MyProject', 765 | repositoryId: 'MyRepo', 766 | pullRequestId: 42, 767 | content: "There's an edge case not handled here.", 768 | filePath: '/src/app.ts', 769 | lineNumber: 87, 770 | status: 'active', 771 | }); 772 | console.log(`Created active thread with ID ${statusComment.thread.id}`); 773 | ``` 774 | 775 | ### Implementation Details 776 | 777 | The `add_pull_request_comment` tool: 778 | 779 | 1. Establishes a connection to Azure DevOps using the provided credentials 780 | 2. Retrieves the Git API client 781 | 3. Creates the comment object with the provided content 782 | 4. Determines whether to add a comment to an existing thread or create a new thread: 783 | - For existing threads, it calls `createComment` to add a comment to the thread 784 | - For new threads, it creates a thread object and calls `createThread` to create a new thread with the comment 785 | 5. For file comments, it adds file path and line information to the thread context 786 | 6. Maps status strings to the appropriate CommentThreadStatus enum values 787 | 7. Returns the created comment or thread information 788 | 8. Handles errors and provides meaningful error messages 789 | 790 | This implementation provides a flexible way to add comments to pull requests, supporting both regular discussion comments and code review feedback. 791 | 792 | ## update_pull_request 793 | 794 | Updates an existing pull request with new properties, links work items, and manages reviewers. 795 | 796 | ### Description 797 | 798 | The `update_pull_request` tool allows you to update various aspects of an existing pull request in Azure DevOps. You can modify the title, description, status, draft state, add or remove linked work items, and add or remove reviewers. This tool is useful for automating pull request workflows, updating PR details based on new information, and managing the review process. 799 | 800 | ### Parameters 801 | 802 | ```json 803 | { 804 | "projectId": "MyProject", // Required: The ID or name of the project 805 | "repositoryId": "MyRepo", // Required: The ID or name of the repository 806 | "pullRequestId": 42, // Required: The ID of the pull request to update 807 | "title": "Updated PR Title", // Optional: The updated title of the pull request 808 | "description": "Updated PR description", // Optional: The updated description 809 | "status": "active", // Optional: The updated status (active, abandoned, completed) 810 | "isDraft": false, // Optional: Whether to mark (true) or unmark (false) as draft 811 | "addWorkItemIds": [123, 456], // Optional: Work item IDs to link to the PR 812 | "removeWorkItemIds": [789], // Optional: Work item IDs to unlink from the PR 813 | "addReviewers": ["[email protected]"], // Optional: Reviewers to add 814 | "removeReviewers": ["[email protected]"], // Optional: Reviewers to remove 815 | "additionalProperties": {} // Optional: Additional properties to update 816 | } 817 | ``` 818 | 819 | | Parameter | Type | Required | Description | 820 | | ---------------------- | -------- | -------- | ------------------------------------------------------------ | 821 | | `projectId` | string | Yes | The ID or name of the project containing the repository | 822 | | `repositoryId` | string | Yes | The ID or name of the repository containing the pull request | 823 | | `pullRequestId` | number | Yes | The ID of the pull request to update | 824 | | `title` | string | No | The updated title of the pull request | 825 | | `description` | string | No | The updated description of the pull request | 826 | | `status` | string | No | The updated status: "active", "abandoned", or "completed" | 827 | | `isDraft` | boolean | No | Whether to mark (true) or unmark (false) the PR as a draft | 828 | | `addWorkItemIds` | number[] | No | Array of work item IDs to link to the pull request | 829 | | `removeWorkItemIds` | number[] | No | Array of work item IDs to unlink from the pull request | 830 | | `addReviewers` | string[] | No | Array of reviewer email addresses or IDs to add | 831 | | `removeReviewers` | string[] | No | Array of reviewer email addresses or IDs to remove | 832 | | `additionalProperties` | object | No | Additional properties to update on the pull request | 833 | 834 | ### Response 835 | 836 | The tool returns the updated `PullRequest` object containing: 837 | 838 | - `pullRequestId`: The unique identifier of the updated pull request 839 | - `title`: The title of the pull request (updated if provided) 840 | - `description`: The description of the pull request (updated if provided) 841 | - `status`: The status of the pull request (active, abandoned, completed) 842 | - `isDraft`: Whether the pull request is a draft 843 | - And various other fields and references, including updated reviewers and work item references 844 | 845 | Example response: 846 | 847 | ```json 848 | { 849 | "repository": { 850 | "id": "repo-guid", 851 | "name": "MyRepo", 852 | "url": "https://dev.azure.com/organization/MyProject/_apis/git/repositories/MyRepo", 853 | "project": { 854 | "id": "project-guid", 855 | "name": "MyProject" 856 | } 857 | }, 858 | "pullRequestId": 42, 859 | "codeReviewId": 42, 860 | "status": 1, 861 | "createdBy": { 862 | "displayName": "John Doe", 863 | "id": "user-guid", 864 | "uniqueName": "[email protected]" 865 | }, 866 | "creationDate": "2023-01-01T12:00:00Z", 867 | "title": "Updated PR Title", 868 | "description": "Updated PR description", 869 | "sourceRefName": "refs/heads/feature-branch", 870 | "targetRefName": "refs/heads/main", 871 | "mergeStatus": 3, 872 | "isDraft": false, 873 | "reviewers": [ 874 | { 875 | "displayName": "Jane Smith", 876 | "id": "reviewer-guid", 877 | "uniqueName": "[email protected]", 878 | "voteResult": 0 879 | } 880 | ], 881 | "url": "https://dev.azure.com/organization/MyProject/_apis/git/repositories/MyRepo/pullRequests/42", 882 | "workItemRefs": [ 883 | { 884 | "id": "123", 885 | "url": "https://dev.azure.com/organization/MyProject/_apis/wit/workItems/123" 886 | }, 887 | { 888 | "id": "456", 889 | "url": "https://dev.azure.com/organization/MyProject/_apis/wit/workItems/456" 890 | } 891 | ] 892 | } 893 | ``` 894 | 895 | ### Error Handling 896 | 897 | The tool may throw the following errors: 898 | 899 | - ValidationError: If required parameters are missing or invalid 900 | - AuthenticationError: If authentication fails 901 | - PermissionError: If the user doesn't have permission to update the pull request 902 | - ResourceNotFoundError: If the project, repository, or pull request doesn't exist 903 | - GeneralError: For other unexpected errors 904 | 905 | Error messages will include details about what went wrong and suggestions for resolution. 906 | 907 | ### Example Usage 908 | 909 | ```typescript 910 | // Update the title and description of a pull request 911 | const updatedPR = await mcpClient.callTool('update_pull_request', { 912 | projectId: 'MyProject', 913 | repositoryId: 'MyRepo', 914 | pullRequestId: 42, 915 | title: 'Updated PR Title', 916 | description: 'This PR has been updated to add new features', 917 | }); 918 | console.log(`Updated PR: ${updatedPR.title}`); 919 | 920 | // Mark a pull request as completed 921 | const completedPR = await mcpClient.callTool('update_pull_request', { 922 | projectId: 'MyProject', 923 | repositoryId: 'MyRepo', 924 | pullRequestId: 42, 925 | status: 'completed', 926 | }); 927 | console.log( 928 | `PR status: ${completedPR.status === 3 ? 'Completed' : 'Not completed'}`, 929 | ); 930 | 931 | // Convert a draft PR to a normal PR 932 | const readyPR = await mcpClient.callTool('update_pull_request', { 933 | projectId: 'MyProject', 934 | repositoryId: 'MyRepo', 935 | pullRequestId: 42, 936 | isDraft: false, 937 | }); 938 | console.log(`PR is draft: ${readyPR.isDraft ? 'Yes' : 'No'}`); 939 | 940 | // Add and remove work items from a PR 941 | const workItemPR = await mcpClient.callTool('update_pull_request', { 942 | projectId: 'MyProject', 943 | repositoryId: 'MyRepo', 944 | pullRequestId: 42, 945 | addWorkItemIds: [123, 456], 946 | removeWorkItemIds: [789], 947 | }); 948 | console.log( 949 | `PR now has ${workItemPR.workItemRefs?.length || 0} linked work items`, 950 | ); 951 | 952 | // Add and remove reviewers 953 | const reviewersPR = await mcpClient.callTool('update_pull_request', { 954 | projectId: 'MyProject', 955 | repositoryId: 'MyRepo', 956 | pullRequestId: 42, 957 | addReviewers: ['[email protected]', '[email protected]'], 958 | removeReviewers: ['[email protected]'], 959 | }); 960 | console.log(`PR now has ${reviewersPR.reviewers?.length || 0} reviewers`); 961 | ``` 962 | 963 | ### Implementation Details 964 | 965 | The `update_pull_request` tool: 966 | 967 | 1. Establishes a connection to Azure DevOps using the provided credentials 968 | 2. Retrieves the Git API client 969 | 3. Gets the current pull request to verify it exists 970 | 4. Creates an update object with only the properties that are being updated: 971 | - Basic properties (title, description, isDraft) 972 | - Status (active, abandoned, completed) 973 | - Any additional properties provided 974 | 5. Updates the pull request with the provided changes 975 | 6. If specified, handles adding and removing work item associations: 976 | - Adds work items by creating links between the PR and work items 977 | - Removes work items by deleting links between the PR and work items 978 | 7. If specified, handles adding and removing reviewers: 979 | - Adds reviewers by creating reviewer references 980 | - Removes reviewers by deleting reviewer references 981 | 8. Gets the final updated pull request to return all changes 982 | 9. Handles errors and provides meaningful error messages 983 | 984 | This implementation provides a comprehensive way to update pull requests in Azure DevOps repositories, supporting all common update scenarios. 985 | ```