@azure-devops/mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE
package/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # ⭐ Azure DevOps MCP Server
2
+
3
+ Easily install the Azure DevOps MCP Server for VS Code or VS Code Insiders:
4
+
5
+ [![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-Install_AzureDevops_MCP_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=ado&config=%7B%20%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22npx%22%2C%20%22args%22%3A%20%5B%22-y%22%2C%20%22%40ado%2Fazure-devops-mcp%22%2C%20%22%24%7Binput%3Aado_org%7D%22%5D%7D&inputs=%5B%7B%22id%22%3A%20%22ado_org%22%2C%20%22type%22%3A%20%22promptString%22%2C%20%22description%22%3A%20%22Azure%20DevOps%20organization%20name%20%20%28e.g.%20%27contoso%27%29%22%7D%5D)
6
+ [![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_AzureDevops_MCP_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=ado&quality=insiders&config=%7B%20%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22npx%22%2C%20%22args%22%3A%20%5B%22-y%22%2C%20%22%40ado%2Fazure-devops-mcp%22%2C%20%22%24%7Binput%3Aado_org%7D%22%5D%7D&inputs=%5B%7B%22id%22%3A%20%22ado_org%22%2C%20%22type%22%3A%20%22promptString%22%2C%20%22description%22%3A%20%22Azure%20DevOps%20organization%20name%20%20%28e.g.%20%27contoso%27%29%22%7D%5D)
7
+
8
+ This TypeScript project defines the **local** MCP server for Azure DevOps, enabling you to perform a wide range of Azure DevOps tasks directly from your code editor.
9
+
10
+ > 🚨 **Public Preview:** This project is in public preview. You can expect that the tools will change before general availability.
11
+
12
+ ## 📄 Table of contents
13
+
14
+ 1. [📺 Overview](#-overview)
15
+ 2. [⚙️ Supported tools](#️-supported-tools)
16
+ 3. [🔌 Installation & getting started](#-installation--getting-started)
17
+ 4. [🔦 Usage](#-usage)
18
+ 5. [📝 Troubleshooting](#-troubleshooting)
19
+ 6. [🎩 Samples & best practices](#-samples--best-practices)
20
+ 7. [📌 Contributing](#️-contributing)
21
+
22
+ ## 📺 Overview
23
+
24
+ The Azure DevOps MCP Server brings Azure DevOps context to your agents. Try prompts like:
25
+
26
+ - "List my ADO projects"
27
+ - "List ADO Builds for 'Contoso'"
28
+ - "List ADO Releases for 'Contoso'"
29
+ - "List ADO Repos for 'Contoso'"
30
+ - "List test plans for 'Contoso'"
31
+ - "List teams for project 'Contoso'"
32
+ - "List iterations for project 'Contoso'"
33
+ - "List my work items for project 'Contoso'"
34
+ - "List work items in current iteration for 'Contoso' project and 'Contoso Team'"
35
+
36
+ ## ⚙️ Supported tools
37
+
38
+ Interact with these Azure DevOps services:
39
+
40
+ ### 🧿 Core
41
+
42
+ - **core_list_project_teams**: Retrieve a list of teams for the specified Azure DevOps project.
43
+ - **core_list_projects**: Retrieve a list of projects in your Azure DevOps organization.
44
+
45
+ ### ⚒️ Work
46
+
47
+ - **work_list_team_iterations**: Retrieve a list of iterations for a specific team in a project.
48
+ - **work_create_iterations**: Create new iterations in a specified Azure DevOps project.
49
+ - **work_assign_iterations**: Assign existing iterations to a specific team in a project.
50
+
51
+ ### 📅 Work Items
52
+
53
+ - **wit_my_work_items**: Retrieve a list of work items relevent to the authenticated user.
54
+ - **wit_list_backlogs**: Revieve a list of backlogs for a given project and team.
55
+ - **wit_list_backlog_work_items**: Retrieve a list of backlogs of for a given project, team, and backlog category.
56
+ - **wit_get_work_item**: Get a single work item by ID.
57
+ - **wit_get_work_items_batch_by_ids**: Retrieve list of work items by IDs in batch.
58
+ - **wit_update_work_item**: Update a work item by ID with specified fields.
59
+ - **wit_create_work_item**: Create a new work item in a specified project and work item type.
60
+ - **wit_list_work_item_comments**: Retrieve list of comments for a work item by ID.
61
+ - **wit_get_work_items_for_iteration**: Retrieve a list of work items for a specified iteration.
62
+ - **wit_add_work_item_comment**: Add comment to a work item by ID.
63
+ - **wit_add_child_work_item**: Create a child work item from a parent by ID.
64
+ - **wit_link_work_item_to_pull_request**: Link a single work item to an existing pull request.
65
+ - **wit_get_work_item_type**: Get a specific work item type.
66
+ - **wit_get_query**: Get a query by its ID or path.
67
+ - **wit_get_query_results_by_id**: Retrieve the results of a work item query given the query ID.
68
+ - **wit_update_work_items_batch**: Update work items in batch.
69
+ - **wit_close_and_link_workitem_duplicates**: Close duplicate work items by id.
70
+ - **wit_work_items_link**: Link work items together in batch.
71
+
72
+ ### 📁 Repositories
73
+
74
+ - **repo_list_repos_by_project**: Retrieve a list of repositories for a given project.
75
+ - **repo_list_pull_requests_by_repo**: Retrieve a list of pull requests for a given repository.
76
+ - **repo_list_pull_requests_by_project**: Retrieve a list of pull requests for a given project Id or Name.
77
+ - **repo_list_branches_by_repo**: Retrieve a list of branches for a given repository.
78
+ - **repo_list_my_branches_by_repo**: Retrieve a list of my branches for a given repository Id.
79
+ - **repo_list_pull_request_threads**: Retrieve a list of comment threads for a pull request.
80
+ - **repo_list_pull_request_thread_comments**: Retrieve a list of comments in a pull request thread.
81
+ - **repo_get_repo_by_name_or_id**: Get the repository by project and repository name or ID.
82
+ - **repo_get_branch_by_name**: Get a branch by its name.
83
+ - **repo_get_pull_request_by_id**: Get a pull request by its ID.
84
+ - **repo_create_pull_request**: Create a new pull request.
85
+ - **repo_update_pull_request_status**: Update status of an existing pull request to active or abandoned.
86
+ - **repo_reply_to_comment**: Replies to a specific comment on a pull request.
87
+ - **repo_resolve_comment**: Resolves a specific comment thread on a pull request.
88
+
89
+ ### 🛰️ Builds
90
+
91
+ - **build_get_definitions**: Retrieves a list of build definitions for a given project.
92
+ - **build_get_definition_revisions**: Retrieves a list of revisions for a specific build definition.
93
+ - **build_get_builds**: Retrieves a list of builds for a given project.
94
+ - **build_get_log**: Retrieves the logs for a specific build.
95
+ - **build_get_log_by_id**: Get a specific build log by log ID.
96
+ - **build_get_changes**: Get the changes associated with a specific build.
97
+ - **build_run_build**: Triggers a new build for a specified definition.
98
+ - **build_get_status**: Fetches the status of a specific build.
99
+
100
+ ### 🚀 Releases
101
+
102
+ - **release_get_definitions**: Retrieves list of release definitions for a given project.
103
+ - **release_get_releases**: Retrieves a list of releases for a given project.
104
+
105
+ ### 🧪 Test Plans
106
+
107
+ - **testplan_create_test_plan**: Creates a new test plan in the project.
108
+ - **testplan_create_test_case**: Creates a new test case work item.
109
+ - **testplan_add_test_cases_to_suite**: Adds existing test cases to a test suite.
110
+ - **testplan_list_test_plans**: Retrieve a paginated list of test plans from an Azure DevOps project. Allows filtering for active plans and toggling detailed information.
111
+ - **testplan_list_test_cases**: Gets a list of test cases in the test plan.
112
+ - **testplan_show_test_results_from_build_id**: Gets a list of test results for a given project and build ID.
113
+
114
+ ### 🔎 Search
115
+
116
+ - **search_code**: Get the code search results for a given search text.
117
+ - **search_wiki**: Get wiki search results for a given search text.
118
+ - **search_workitem**: Get work item search results for a given search text.
119
+
120
+ ## 🔌 Installation & getting started
121
+
122
+ Clone the repository, install dependencies, and add it to your MCP client configuration.
123
+
124
+ ### Visual Studio Code & GitHub Copilot
125
+
126
+ For the best experience, use Visual Studio Code and GitHub Copilot.
127
+
128
+ ### Prerequisites
129
+
130
+ 1. Install [VS Code](https://code.visualstudio.com/download) or [VS Code Insiders](https://code.visualstudio.com/insiders)
131
+ 2. Install [Node.js](https://nodejs.org/en/download) 20+
132
+ 3. Open VS Code in an empty folder
133
+
134
+ ### Azure Login
135
+
136
+ Ensure you are logged in to Azure DevOps via the Azure CLI:
137
+
138
+ ```sh
139
+ az login
140
+ ```
141
+
142
+ ### Installation
143
+
144
+ #### ✨ One-Click install
145
+
146
+ [![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-Install_AzureDevops_MCP_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=ado&config=%7B%20%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22npx%22%2C%20%22args%22%3A%20%5B%22-y%22%2C%20%22%40ado%2Fazure-devops-mcp%22%2C%20%22%24%7Binput%3Aado_org%7D%22%5D%7D&inputs=%5B%7B%22id%22%3A%20%22ado_org%22%2C%20%22type%22%3A%20%22promptString%22%2C%20%22description%22%3A%20%22Azure%20DevOps%20organization%20name%20%20%28e.g.%20%27contoso%27%29%22%7D%5D)
147
+ [![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_AzureDevops_MCP_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=ado&quality=insiders&config=%7B%20%22type%22%3A%20%22stdio%22%2C%20%22command%22%3A%20%22npx%22%2C%20%22args%22%3A%20%5B%22-y%22%2C%20%22%40ado%2Fazure-devops-mcp%22%2C%20%22%24%7Binput%3Aado_org%7D%22%5D%7D&inputs=%5B%7B%22id%22%3A%20%22ado_org%22%2C%20%22type%22%3A%20%22promptString%22%2C%20%22description%22%3A%20%22Azure%20DevOps%20organization%20name%20%20%28e.g.%20%27contoso%27%29%22%7D%5D)
148
+
149
+ After installation, select GitHub Copilot Agent Mode and refresh the tools list. Learn more about Agent Mode in the [VS Code Documentation](https://code.visualstudio.com/docs/copilot/chat/chat-agent-mode).
150
+
151
+ #### 🛠️ Installing from source (dev mode)
152
+
153
+ This installation method is recommended for advanced users and contributors who want immediate access to the latest updates from the main branch. It is ideal if you are developing new tools, enhancing existing features, or maintaining a custom fork.
154
+
155
+ > **Note:** For most users, installing from the public feed is simpler and preferred. Use source installation only if you need the latest changes or are actively contributing to the project.
156
+
157
+ ##### Steps
158
+
159
+ 1. Clone the repository.
160
+ 2. Install dependencies:
161
+ ```sh
162
+ npm install
163
+ ```
164
+ 3. Edit or add `.vscode/mcp.json`:
165
+
166
+ ```json
167
+ {
168
+ "inputs": [
169
+ {
170
+ "id": "ado_org",
171
+ "type": "promptString",
172
+ "description": "Azure DevOps organization name (e.g. 'contoso')"
173
+ }
174
+ ],
175
+ "servers": {
176
+ "ado": {
177
+ "type": "stdio",
178
+ "command": "mcp-server-azuredevops",
179
+ "args": ["${input:ado_org}"]
180
+ }
181
+ }
182
+ }
183
+ ```
184
+
185
+ 4. Start the Azure DevOps MCP Server:
186
+ 5. In chat, switch to [Agent Mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode).
187
+ 6. Click "Select Tools" and choose the available `ado_` tools.
188
+
189
+ See [How To](./docs/HOWTO.md) section for details
190
+
191
+ #### Placeholder for public feed
192
+
193
+ Update for Public Feed
194
+
195
+ ## 🔦 Usage
196
+
197
+ ### Visual Studio Code + GitHub Copilot
198
+
199
+ 1. Open GitHub Copilot in VS Code and switch to Agent mode.
200
+ 2. Start the Azure DevOps MCP Server.
201
+ 3. The server appears in the tools list.
202
+ 4. Try prompts like "List ADO projects".
203
+
204
+ ### Visual Studio + GitHub Copilot
205
+
206
+ > *Prerequisites:* Visual Studio 2022 v17.14+, Agent mode enabled in Tools > Options > GitHub > Copilot > Copilot Chat.
207
+
208
+ 1. Switch to Agent mode in the Copilot Chat window.
209
+ 2. Enter your Azure DevOps organization name.
210
+ 3. Select desired `ado` tools.
211
+ 4. Try prompts like "List ADO projects".
212
+
213
+ For more details, see [Visual Studio MCP Servers documentation](https://learn.microsoft.com/en-us/visualstudio/ide/mcp-servers?view=vs-2022) and [Getting Started Video](https://www.youtube.com/watch?v=oPFecZHBCkg).
214
+
215
+ ## 📝 Troubleshooting
216
+
217
+ See the [Troubleshooting guide](./docs/TROUBLESHOOTING.md) for help with common issues and logging.
218
+
219
+ ## 🎩 Samples & best practices
220
+
221
+ Find sample prompts and best practices in our [How-to Guide](./docs/HOWTO.md).
222
+
223
+ ## 📌 Contributing
224
+
225
+ We welcome contributions! During preview, please file Issues for bugs, enhancements, or documentation improvements.
226
+
227
+ See our [Contributions Guide](./CONTRIBUTING.md) for:
228
+
229
+ - 🛠️ Development setup
230
+ - ✨ Adding new tools
231
+ - 📝 Code style & testing
232
+ - 🔄 Pull request process
233
+
234
+ ## 🤝 Code of conduct
235
+
236
+ This project follows the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
237
+ For questions, see the [FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [open@microsoft.com](mailto:open@microsoft.com).
238
+
239
+ ## License
240
+
241
+ Licensed under the [MIT License](./LICENSE.md).
242
+
243
+ ---
244
+
245
+ _Trademarks: This project may include trademarks or logos for Microsoft or third parties. Use of Microsoft trademarks or logos must follow [Microsoft’s Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). Third-party trademarks are subject to their respective policies._
246
+
247
+ <!-- version: 2023-04-07 [Do not delete this line, it is used for analytics that drive template improvements] -->
package/dist/index.js ADDED
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ // Copyright (c) Microsoft Corporation.
3
+ // Licensed under the MIT License.
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import * as azdev from "azure-devops-node-api";
7
+ import { DefaultAzureCredential } from "@azure/identity";
8
+ import { configurePrompts } from "./prompts.js";
9
+ import { configureAllTools } from "./tools.js";
10
+ import { userAgent } from "./utils.js";
11
+ import { packageVersion } from "./version.js";
12
+ const args = process.argv.slice(2);
13
+ if (args.length === 0) {
14
+ console.error("Usage: mcp-server-azuredevops <organization_name>");
15
+ process.exit(1);
16
+ }
17
+ export const orgName = args[0];
18
+ const orgUrl = "https://dev.azure.com/" + orgName;
19
+ async function getAzureDevOpsToken() {
20
+ process.env.AZURE_TOKEN_CREDENTIALS = "dev";
21
+ const credential = new DefaultAzureCredential(); // CodeQL [SM05138] resolved by explicitly setting AZURE_TOKEN_CREDENTIALS
22
+ const token = await credential.getToken("499b84ac-1321-427f-aa17-267ca6975798/.default");
23
+ return token;
24
+ }
25
+ async function getAzureDevOpsClient() {
26
+ const token = await getAzureDevOpsToken();
27
+ const authHandler = azdev.getBearerHandler(token.token);
28
+ const connection = new azdev.WebApi(orgUrl, authHandler, undefined, {
29
+ productName: "AzureDevOps.MCP",
30
+ productVersion: packageVersion,
31
+ userAgent: userAgent
32
+ });
33
+ return connection;
34
+ }
35
+ async function main() {
36
+ console.error("Starting Azure DevOps MCP Server...");
37
+ const server = new McpServer({
38
+ name: "Azure DevOps MCP Server",
39
+ version: "1.0.0",
40
+ });
41
+ configurePrompts(server);
42
+ configureAllTools(server, getAzureDevOpsToken, getAzureDevOpsClient);
43
+ const transport = new StdioServerTransport();
44
+ console.error("Connecting server to transport...");
45
+ await server.connect(transport);
46
+ console.error("Azure DevOps MCP Server running on stdio");
47
+ }
48
+ main().catch((error) => {
49
+ console.error("Fatal error in main():", error);
50
+ process.exit(1);
51
+ });
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { z } from "zod";
4
+ import { REPO_TOOLS } from "./tools/repos.js";
5
+ function configurePrompts(server) {
6
+ server.prompt("relevant_pull_requests", "Presents the list of relevant pull requests for a given repository.", { repositoryId: z.string() }, ({ repositoryId }) => ({
7
+ messages: [
8
+ {
9
+ role: "user",
10
+ content: {
11
+ type: "text",
12
+ text: String.raw `
13
+ # Prerequisites
14
+ 1. Unless already provided, ask user for the project name
15
+ 2. Unless already provided, use '${REPO_TOOLS.list_repos_by_project}' tool to get a summarized response of the repositories in this project and ask user to select one
16
+
17
+ # Task
18
+ Find all pull requests for repository ${repositoryId} using '${REPO_TOOLS.list_pull_requests_by_repo}' tool and summarize them in a table.
19
+ Include the following columns: ID, Title, Status, Created Date, Author and Reviewers.`,
20
+ },
21
+ },
22
+ ],
23
+ }));
24
+ }
25
+ export { configurePrompts };
@@ -0,0 +1,20 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ async function getCurrentUserDetails(tokenProvider, connectionProvider) {
4
+ const connection = await connectionProvider();
5
+ const url = `${connection.serverUrl}/_apis/connectionData`;
6
+ const token = (await tokenProvider()).token;
7
+ const response = await fetch(url, {
8
+ method: "GET",
9
+ headers: {
10
+ Authorization: `Bearer ${token}`,
11
+ "Content-Type": "application/json",
12
+ },
13
+ });
14
+ const data = await response.json();
15
+ if (!response.ok) {
16
+ throw new Error(`Error fetching user details: ${data.message}`);
17
+ }
18
+ return data;
19
+ }
20
+ export { getCurrentUserDetails };
@@ -0,0 +1,146 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { BuildQueryOrder, DefinitionQueryOrder } from "azure-devops-node-api/interfaces/BuildInterfaces.js";
4
+ import { z } from "zod";
5
+ const BUILD_TOOLS = {
6
+ get_definitions: "build_get_definitions",
7
+ get_definition_revisions: "build_get_definition_revisions",
8
+ get_builds: "build_get_builds",
9
+ get_log: "build_get_log",
10
+ get_log_by_id: "build_get_log_by_id",
11
+ get_changes: "build_get_changes",
12
+ run_build: "build_run_build",
13
+ get_status: "build_get_status"
14
+ };
15
+ function configureBuildTools(server, tokenProvider, connectionProvider) {
16
+ server.tool(BUILD_TOOLS.get_definitions, "Retrieves a list of build definitions for a given project.", {
17
+ project: z.string().describe("Project ID or name to get build definitions for"),
18
+ repositoryId: z.string().optional().describe("Repository ID to filter build definitions"),
19
+ repositoryType: z.enum(["TfsGit", "GitHub", "BitbucketCloud"]).optional().describe("Type of repository to filter build definitions"),
20
+ name: z.string().optional().describe("Name of the build definition to filter"),
21
+ path: z.string().optional().describe("Path of the build definition to filter"),
22
+ queryOrder: z.nativeEnum(DefinitionQueryOrder).optional().describe("Order in which build definitions are returned"),
23
+ top: z.number().optional().describe("Maximum number of build definitions to return"),
24
+ continuationToken: z.string().optional().describe("Token for continuing paged results"),
25
+ minMetricsTime: z.date().optional().describe("Minimum metrics time to filter build definitions"),
26
+ definitionIds: z.array(z.number()).optional().describe("Array of build definition IDs to filter"),
27
+ builtAfter: z.date().optional().describe("Return definitions that have builds after this date"),
28
+ notBuiltAfter: z.date().optional().describe("Return definitions that do not have builds after this date"),
29
+ includeAllProperties: z.boolean().optional().describe("Whether to include all properties in the results"),
30
+ includeLatestBuilds: z.boolean().optional().describe("Whether to include the latest builds for each definition"),
31
+ taskIdFilter: z.string().optional().describe("Task ID to filter build definitions"),
32
+ processType: z.number().optional().describe("Process type to filter build definitions"),
33
+ yamlFilename: z.string().optional().describe("YAML filename to filter build definitions"),
34
+ }, async ({ project, repositoryId, repositoryType, name, path, queryOrder, top, continuationToken, minMetricsTime, definitionIds, builtAfter, notBuiltAfter, includeAllProperties, includeLatestBuilds, taskIdFilter, processType, yamlFilename, }) => {
35
+ const connection = await connectionProvider();
36
+ const buildApi = await connection.getBuildApi();
37
+ const buildDefinitions = await buildApi.getDefinitions(project, name, repositoryId, repositoryType, queryOrder, top, continuationToken, minMetricsTime, definitionIds, path, builtAfter, notBuiltAfter, includeAllProperties, includeLatestBuilds, taskIdFilter, processType, yamlFilename);
38
+ return {
39
+ content: [{ type: "text", text: JSON.stringify(buildDefinitions, null, 2) }],
40
+ };
41
+ });
42
+ server.tool(BUILD_TOOLS.get_definition_revisions, "Retrieves a list of revisions for a specific build definition.", {
43
+ project: z.string().describe("Project ID or name to get the build definition revisions for"),
44
+ definitionId: z.number().describe("ID of the build definition to get revisions for"),
45
+ }, async ({ project, definitionId }) => {
46
+ const connection = await connectionProvider();
47
+ const buildApi = await connection.getBuildApi();
48
+ const revisions = await buildApi.getDefinitionRevisions(project, definitionId);
49
+ return {
50
+ content: [{ type: "text", text: JSON.stringify(revisions, null, 2) }],
51
+ };
52
+ });
53
+ server.tool(BUILD_TOOLS.get_builds, "Retrieves a list of builds for a given project.", {
54
+ project: z.string().describe("Project ID or name to get builds for"),
55
+ definitions: z.array(z.number()).optional().describe("Array of build definition IDs to filter builds"),
56
+ queues: z.array(z.number()).optional().describe("Array of queue IDs to filter builds"),
57
+ buildNumber: z.string().optional().describe("Build number to filter builds"),
58
+ minTime: z.date().optional().describe("Minimum finish time to filter builds"),
59
+ maxTime: z.date().optional().describe("Maximum finish time to filter builds"),
60
+ requestedFor: z.string().optional().describe("User ID or name who requested the build"),
61
+ reasonFilter: z.number().optional().describe("Reason filter for the build (see BuildReason enum)"),
62
+ statusFilter: z.number().optional().describe("Status filter for the build (see BuildStatus enum)"),
63
+ resultFilter: z.number().optional().describe("Result filter for the build (see BuildResult enum)"),
64
+ tagFilters: z.array(z.string()).optional().describe("Array of tags to filter builds"),
65
+ properties: z.array(z.string()).optional().describe("Array of property names to include in the results"),
66
+ top: z.number().optional().describe("Maximum number of builds to return"),
67
+ continuationToken: z.string().optional().describe("Token for continuing paged results"),
68
+ maxBuildsPerDefinition: z.number().optional().describe("Maximum number of builds per definition"),
69
+ deletedFilter: z.number().optional().describe("Filter for deleted builds (see QueryDeletedOption enum)"),
70
+ queryOrder: z.nativeEnum(BuildQueryOrder).default(BuildQueryOrder.QueueTimeDescending).optional().describe("Order in which builds are returned"),
71
+ branchName: z.string().optional().describe("Branch name to filter builds"),
72
+ buildIds: z.array(z.number()).optional().describe("Array of build IDs to retrieve"),
73
+ repositoryId: z.string().optional().describe("Repository ID to filter builds"),
74
+ repositoryType: z.enum(["TfsGit", "GitHub", "BitbucketCloud"]).optional().describe("Type of repository to filter builds"),
75
+ }, async ({ project, definitions, queues, buildNumber, minTime, maxTime, requestedFor, reasonFilter, statusFilter, resultFilter, tagFilters, properties, top, continuationToken, maxBuildsPerDefinition, deletedFilter, queryOrder, branchName, buildIds, repositoryId, repositoryType, }) => {
76
+ const connection = await connectionProvider();
77
+ const buildApi = await connection.getBuildApi();
78
+ const builds = await buildApi.getBuilds(project, definitions, queues, buildNumber, minTime, maxTime, requestedFor, reasonFilter, statusFilter, resultFilter, tagFilters, properties, top, continuationToken, maxBuildsPerDefinition, deletedFilter, queryOrder, branchName, buildIds, repositoryId, repositoryType);
79
+ return {
80
+ content: [{ type: "text", text: JSON.stringify(builds, null, 2) }],
81
+ };
82
+ });
83
+ server.tool(BUILD_TOOLS.get_log, "Retrieves the logs for a specific build.", {
84
+ project: z.string().describe("Project ID or name to get the build log for"),
85
+ buildId: z.number().describe("ID of the build to get the log for"),
86
+ }, async ({ project, buildId }) => {
87
+ const connection = await connectionProvider();
88
+ const buildApi = await connection.getBuildApi();
89
+ const logs = await buildApi.getBuildLogs(project, buildId);
90
+ return {
91
+ content: [{ type: "text", text: JSON.stringify(logs, null, 2) }],
92
+ };
93
+ });
94
+ server.tool(BUILD_TOOLS.get_log_by_id, "Get a specific build log by log ID.", {
95
+ project: z.string().describe("Project ID or name to get the build log for"),
96
+ buildId: z.number().describe("ID of the build to get the log for"),
97
+ logId: z.number().describe("ID of the log to retrieve"),
98
+ startLine: z.number().optional().describe("Starting line number for the log content, defaults to 0"),
99
+ endLine: z.number().optional().describe("Ending line number for the log content, defaults to the end of the log"),
100
+ }, async ({ project, buildId, logId, startLine, endLine }) => {
101
+ const connection = await connectionProvider();
102
+ const buildApi = await connection.getBuildApi();
103
+ const logLines = await buildApi.getBuildLogLines(project, buildId, logId, startLine, endLine);
104
+ return {
105
+ content: [{ type: "text", text: JSON.stringify(logLines, null, 2) }],
106
+ };
107
+ });
108
+ server.tool(BUILD_TOOLS.get_changes, "Get the changes associated with a specific build.", {
109
+ project: z.string().describe("Project ID or name to get the build changes for"),
110
+ buildId: z.number().describe("ID of the build to get changes for"),
111
+ continuationToken: z.string().optional().describe("Continuation token for pagination"),
112
+ top: z.number().default(100).describe("Number of changes to retrieve, defaults to 100"),
113
+ includeSourceChange: z.boolean().optional().describe("Whether to include source changes in the results, defaults to false"),
114
+ }, async ({ project, buildId, continuationToken, top, includeSourceChange }) => {
115
+ const connection = await connectionProvider();
116
+ const buildApi = await connection.getBuildApi();
117
+ const changes = await buildApi.getBuildChanges(project, buildId, continuationToken, top, includeSourceChange);
118
+ return {
119
+ content: [{ type: "text", text: JSON.stringify(changes, null, 2) }],
120
+ };
121
+ });
122
+ server.tool(BUILD_TOOLS.run_build, "Triggers a new build for a specified definition.", {
123
+ project: z.string().describe("Project ID or name to run the build in"),
124
+ definitionId: z.number().describe("ID of the build definition to run"),
125
+ sourceBranch: z.string().optional().describe("Source branch to run the build from. If not provided, the default branch will be used."),
126
+ }, async ({ project, definitionId, sourceBranch }) => {
127
+ const connection = await connectionProvider();
128
+ const buildApi = await connection.getBuildApi();
129
+ const build = await buildApi.queueBuild({ definition: { id: definitionId }, sourceBranch }, project);
130
+ return {
131
+ content: [{ type: "text", text: JSON.stringify(build, null, 2) }],
132
+ };
133
+ });
134
+ server.tool(BUILD_TOOLS.get_status, "Fetches the status of a specific build.", {
135
+ project: z.string().describe("Project ID or name to get the build status for"),
136
+ buildId: z.number().describe("ID of the build to get the status for"),
137
+ }, async ({ project, buildId }) => {
138
+ const connection = await connectionProvider();
139
+ const buildApi = await connection.getBuildApi();
140
+ const build = await buildApi.getBuildReport(project, buildId);
141
+ return {
142
+ content: [{ type: "text", text: JSON.stringify(build, null, 2) }],
143
+ };
144
+ });
145
+ }
146
+ export { BUILD_TOOLS, configureBuildTools };
@@ -0,0 +1,36 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { z } from "zod";
4
+ const CORE_TOOLS = {
5
+ list_project_teams: "core_list_project_teams",
6
+ list_projects: "core_list_projects",
7
+ };
8
+ function configureCoreTools(server, tokenProvider, connectionProvider) {
9
+ server.tool(CORE_TOOLS.list_project_teams, "Retrieve a list of teams for the specified Azure DevOps project.", {
10
+ project: z.string().describe("The name or ID of the Azure DevOps project."),
11
+ mine: z.boolean().optional().describe("If true, only return teams that the authenticated user is a member of."),
12
+ top: z.number().optional().describe("The maximum number of teams to return. Defaults to 100."),
13
+ skip: z.number().optional().describe("The number of teams to skip for pagination. Defaults to 0."),
14
+ }, async ({ project, mine, top, skip }) => {
15
+ const connection = await connectionProvider();
16
+ const coreApi = await connection.getCoreApi();
17
+ const teams = await coreApi.getTeams(project, mine, top, skip, false);
18
+ return {
19
+ content: [{ type: "text", text: JSON.stringify(teams, null, 2) }],
20
+ };
21
+ });
22
+ server.tool(CORE_TOOLS.list_projects, "Retrieve a list of projects in your Azure DevOps organization.", {
23
+ stateFilter: z.enum(["all", "wellFormed", "createPending", "deleted"]).default("wellFormed").describe("Filter projects by their state. Defaults to 'wellFormed'."),
24
+ top: z.number().optional().describe("The maximum number of projects to return. Defaults to 100."),
25
+ skip: z.number().optional().describe("The number of projects to skip for pagination. Defaults to 0."),
26
+ continuationToken: z.number().optional().describe("Continuation token for pagination. Used to fetch the next set of results if available."),
27
+ }, async ({ stateFilter, top, skip, continuationToken }) => {
28
+ const connection = await connectionProvider();
29
+ const coreApi = await connection.getCoreApi();
30
+ const projects = await coreApi.getProjects(stateFilter, top, skip, continuationToken, false);
31
+ return {
32
+ content: [{ type: "text", text: JSON.stringify(projects, null, 2) }],
33
+ };
34
+ });
35
+ }
36
+ export { CORE_TOOLS, configureCoreTools };
@@ -0,0 +1,72 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ import { ReleaseDefinitionExpands, ReleaseDefinitionQueryOrder, ReleaseExpands, ReleaseStatus, ReleaseQueryOrder, } from "azure-devops-node-api/interfaces/ReleaseInterfaces.js";
4
+ import { z } from "zod";
5
+ const RELEASE_TOOLS = {
6
+ get_release_definitions: "release_get_definitions",
7
+ get_releases: "release_get_releases",
8
+ };
9
+ function configureReleaseTools(server, tokenProvider, connectionProvider) {
10
+ server.tool(RELEASE_TOOLS.get_release_definitions, "Retrieves list of release definitions for a given project.", {
11
+ project: z.string().describe("Project ID or name to get release definitions for"),
12
+ searchText: z.string().optional().describe("Search text to filter release definitions"),
13
+ expand: z.nativeEnum(ReleaseDefinitionExpands).default(ReleaseDefinitionExpands.None).describe("Expand options for release definitions"),
14
+ artifactType: z.string().optional().describe("Filter by artifact type"),
15
+ artifactSourceId: z.string().optional().describe("Filter by artifact source ID"),
16
+ top: z.number().optional().describe("Number of results to return (for pagination)"),
17
+ continuationToken: z.string().optional().describe("Continuation token for pagination"),
18
+ queryOrder: z.nativeEnum(ReleaseDefinitionQueryOrder).default(ReleaseDefinitionQueryOrder.NameAscending).describe("Order of the results"),
19
+ path: z.string().optional().describe("Path to filter release definitions"),
20
+ isExactNameMatch: z.boolean().optional().default(false).describe("Whether to match the exact name of the release definition. Default is false."),
21
+ tagFilter: z.array(z.string()).optional().describe("Filter by tags associated with the release definitions"),
22
+ propertyFilters: z.array(z.string()).optional().describe("Filter by properties associated with the release definitions"),
23
+ definitionIdFilter: z.array(z.string()).optional().describe("Filter by specific release definition IDs"),
24
+ isDeleted: z.boolean().default(false).describe("Whether to include deleted release definitions. Default is false."),
25
+ searchTextContainsFolderName: z.boolean().optional().describe("Whether to include folder names in the search text"),
26
+ }, async ({ project, searchText, expand, artifactType, artifactSourceId, top, continuationToken, queryOrder, path, isExactNameMatch, tagFilter, propertyFilters, definitionIdFilter, isDeleted, searchTextContainsFolderName, }) => {
27
+ const connection = await connectionProvider();
28
+ const releaseApi = await connection.getReleaseApi();
29
+ const releaseDefinitions = await releaseApi.getReleaseDefinitions(project, searchText, expand, artifactType, artifactSourceId, top, continuationToken, queryOrder, path, isExactNameMatch, tagFilter, propertyFilters, definitionIdFilter, isDeleted, searchTextContainsFolderName);
30
+ return {
31
+ content: [
32
+ { type: "text", text: JSON.stringify(releaseDefinitions, null, 2) },
33
+ ],
34
+ };
35
+ });
36
+ server.tool(RELEASE_TOOLS.get_releases, "Retrieves a list of releases for a given project.", {
37
+ project: z.string().optional().describe("Project ID or name to get releases for"),
38
+ definitionId: z.number().optional().describe("ID of the release definition to filter releases"),
39
+ definitionEnvironmentId: z.number().optional().describe("ID of the definition environment to filter releases"),
40
+ searchText: z.string().optional().describe("Search text to filter releases"),
41
+ createdBy: z.string().optional().describe("User ID or name who created the release"),
42
+ statusFilter: z.nativeEnum(ReleaseStatus).optional().default(ReleaseStatus.Active).describe("Status of the releases to filter (default: Active)"),
43
+ environmentStatusFilter: z.number().optional().describe("Environment status to filter releases"),
44
+ minCreatedTime: z.date().optional().default(() => {
45
+ const sevenDaysAgo = new Date();
46
+ sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
47
+ return sevenDaysAgo;
48
+ }).describe("Minimum created time for releases (default: 7 days ago)"),
49
+ maxCreatedTime: z.date().optional().default(() => new Date()).describe("Maximum created time for releases (default: now)"),
50
+ queryOrder: z.nativeEnum(ReleaseQueryOrder).optional().default(ReleaseQueryOrder.Ascending).describe("Order in which to return releases (default: Ascending)"),
51
+ top: z.number().optional().describe("Number of releases to return"),
52
+ continuationToken: z.number().optional().describe("Continuation token for pagination"),
53
+ expand: z.nativeEnum(ReleaseExpands).optional().default(ReleaseExpands.None).describe("Expand options for releases"),
54
+ artifactTypeId: z.string().optional().describe("Filter releases by artifact type ID"),
55
+ sourceId: z.string().optional().describe("Filter releases by artifact source ID"),
56
+ artifactVersionId: z.string().optional().describe("Filter releases by artifact version ID"),
57
+ sourceBranchFilter: z.string().optional().describe("Filter releases by source branch"),
58
+ isDeleted: z.boolean().optional().default(false).describe("Whether to include deleted releases (default: false)"),
59
+ tagFilter: z.array(z.string()).optional().describe("Filter releases by tags"),
60
+ propertyFilters: z.array(z.string()).optional().describe("Filter releases by properties"),
61
+ releaseIdFilter: z.array(z.number()).optional().describe("Filter by specific release IDs"),
62
+ path: z.string().optional().describe("Path to filter releases"),
63
+ }, async ({ project, definitionId, definitionEnvironmentId, searchText, createdBy, statusFilter, environmentStatusFilter, minCreatedTime, maxCreatedTime, queryOrder, top, continuationToken, expand, artifactTypeId, sourceId, artifactVersionId, sourceBranchFilter, isDeleted, tagFilter, propertyFilters, releaseIdFilter, path, }) => {
64
+ const connection = await connectionProvider();
65
+ const releaseApi = await connection.getReleaseApi();
66
+ const releases = await releaseApi.getReleases(project, definitionId, definitionEnvironmentId, searchText, createdBy, statusFilter, environmentStatusFilter, minCreatedTime, maxCreatedTime, queryOrder, top, continuationToken, expand, artifactTypeId, sourceId, artifactVersionId, sourceBranchFilter, isDeleted, tagFilter, propertyFilters, releaseIdFilter, path);
67
+ return {
68
+ content: [{ type: "text", text: JSON.stringify(releases, null, 2) }],
69
+ };
70
+ });
71
+ }
72
+ export { RELEASE_TOOLS, configureReleaseTools };