# ⭐ Azure DevOps MCP Server (Safe Fork)

This is a hardening fork of the official Azure DevOps MCP Server that removes tools capable of irrevocable changes.

Upstream (original) GitHub repository:

`https://github.com/microsoft/azure-devops-mcp`

Fork source (private) Azure DevOps repo:

`https://dev.azure.com/LiventusInc/Liventus/_git/azure-devops-mcp-safe`

This TypeScript project provides a **local** MCP server for Azure DevOps, enabling you to safely access Azure DevOps data and perform safe operations that make no irrevocable changes to your Azure DevOps environment.

> 🚨 **Public Preview:** This project is in public preview. Tools and features may change before general availability.

## 📄 Table of Contents

1. [📺 Overview](#-overview)
2. [🏆 Expectations](#-expectations)
3. [🔀 Fork Versioning](#-fork-versioning)
4. [📜 Release Notes](#-release-notes)
5. [⚙️ Supported Tools](#️-supported-tools)
6. [🔌 Installation & Getting Started](#-installation--getting-started)
7. [📝 Troubleshooting](#-troubleshooting)
8. [🎩 Examples & Best Practices](#-samples--best-practices)
9. [🙋‍♀️ Frequently Asked Questions](#️-frequently-asked-questions)
10. [📌 Contributing](#-contributing)

## 📺 Overview

The Azure DevOps MCP Server brings Azure DevOps context to your agents. Try prompts like:

- "List my ADO projects"
- "List ADO Builds for 'Contoso'"
- "List ADO Releases for 'Contoso'"
- "List ADO Repos for 'Contoso'"
- "List test plans for 'Contoso'"
- "List teams for project 'Contoso'"
- "List iterations for project 'Contoso'"
- "List my work items for project 'Contoso'"
- "List work items in current iteration for 'Contoso' project and 'Contoso Team'"

## 🏆 Expectations

The Azure DevOps MCP Server (Safe Fork) is built from tools that are concise, simple, focused, and easy to use—each designed for a specific scenario. We intentionally avoid complex tools that try to do too much, and more importantly, **we only provide safe operations that make no irrevocable changes to your Azure DevOps environment**. This includes read-only operations (queries, retrieving data) and safe creation operations (adding comments, creating new work items, opening pull requests). The goal is to provide a secure abstraction layer over the REST APIs, making data access straightforward and letting the language model handle complex reasoning without risk of data loss or corruption.

### Remote Token Security: Stateless Client-Held Tokens

For the hosted server (`https://ado-mcp.liventus.com`), the server stores **no user tokens at rest** — there is no server-side session store at all:

- Every credential issued to an MCP client is a self-contained **AES-256-GCM encrypted blob** (see `src/oauth/token-crypto.ts`). The client holds the ciphertext; only the server holds the decryption keys, loaded **directly from Azure Key Vault at boot** via managed identity (`TOKEN_ENCRYPTION_KEY_VAULT_URL`) — the raw key material never appears in app configuration or environment variables.
- Keys are **versioned** (see `src/oauth/token-keys.ts`): each blob records the key generation it was sealed with, and the server reloads the ring from Key Vault hourly. A scheduled Container Apps Job **rotates the key automatically every month** — existing tokens keep decrypting under older enabled versions, so nobody is signed out — and disabling a version in Key Vault invalidates every token sealed under it: a kill switch without the mass sign-out. Every rotation and key read is recorded in Key Vault's `AuditEvent` diagnostics.
- The Entra ID refresh token travels inside the client's encrypted `refresh_token` blob. It is unreadable to the client and unusable without the server — and a server-side compromise yields nothing, because nothing is stored.
- Refresh-token blobs are cryptographically bound to the OAuth `client_id` they were issued to (bound as GCM additional authenticated data), so a stolen blob cannot be redeemed under a different client registration, and they carry a rolling **90-day inactivity ceiling** (`REFRESH_TOKEN_MAX_AGE_MS`) reset on every rotation.
- Access-token blobs are capped at a **1-hour lifetime**, so an Entra-side revocation (account disabled, sign-in sessions revoked) takes effect at the next refresh.
- Sign-in persists as long as the Entra ID refresh token stays valid (a 90-day sliding inactivity window under default tenant policy) and the rolling ceiling above, so users authenticate once rather than on a short server-imposed timer.
- Refresh-token rotation is governed by Entra ID: every refresh returns a new Entra refresh token, sealed into a fresh blob. Note that Entra does **not** guarantee invalidation of the prior refresh token on rotation for confidential web clients (its strict reuse/theft detection applies to SPAs), so a previously issued blob may remain redeemable until Entra-side conditions revoke the underlying token. Per-user revocation is therefore an **Entra-side operation** — revoke the user's sign-in sessions (`Revoke-MgUserSignInSession` / "Revoke sessions" in the portal) or disable the account, which takes effect at the next refresh (≤1 hour, per the access-token cap above). The Key Vault key kill switch revokes all users at once.

No Redis or other shared session storage is required for multi-replica hosting — any replica can decrypt and serve any request.

## 🔀 Fork Versioning

This fork uses **semantic versioning with prerelease identifiers** to signal Liventus customizations while maintaining a clear upgrade path to official upstream releases.

### Version Format

```
MAJOR.MINOR.PATCH-liventus.N
```

Example: `2.7.0-liventus.1`

### How It Works

- Each Liventus customization increments `N` (e.g., `2.7.0-liventus.1` → `2.7.0-liventus.2`)
- When the upstream version changes, the counter resets (e.g., `2.7.1-liventus.1`)
- The base version (`MAJOR.MINOR.PATCH`) always tracks the upstream version so feature parity is immediately clear

### Benefits

✅ **Clarity** — Version string explicitly signals this is a fork with customizations  
✅ **Feature parity** — Base version number directly correlates to upstream features available  
✅ **Change tracking** — Counter increments reflect number of Liventus-specific changes  
✅ **Compliance** — Follows [Semantic Versioning 2.0.0](https://semver.org/) specification

## 📜 Release Notes

Liventus-specific releases on top of upstream **2.7.0**, newest first. Each entry cites the Azure DevOps
pull request it shipped in where one exists; early releases were committed directly to `main`.

### 2.7.0-liventus.15 — 2026-08-06

- **`wit_query_by_wiql` gains an optional `idsOnly` parameter.** A WIQL result never carries field values
  (`SELECT` only populates the `columns` metadata), so every row returns as an API reference object of
  `{ id, url }` — and that `url` is derivable from the id beside it. On a large result it *is* the response:
  a measured 200-row tree query returned 65KB, of which 30KB was url text, to convey ids that fit in 799
  bytes. Past a client's response-size limit the whole payload is spilled to a file the agent can no longer
  read. With `idsOnly: true` a flat query returns `{ count, ids }` and a tree query
  `{ count, relations: [{ rel, source, target }] }` with bare numeric ids; `columns`, `queryType` and `asOf`
  are unchanged. **Defaults to `false`, so existing callers see byte-identical output.**

### 2.7.0-liventus.14 — 2026-07-09 (PR 488)

- **Completely stateless authentication.** Server-side session storage is gone entirely — no Redis, no
  session store — replaced by 90-day client-held encrypted tokens. The trade is coarser-grained token
  revocation for the elimination of an entire class of server-side state.
- Longer dynamic client-id cache timeout, fixing `invalid client_id` errors after 24 hours.
- Fixed infinite recursion on explicit session logout, failed session connections, and `user=unknown` in
  server logs; the exact token auth flow is now logged so the path taken is unambiguous.
- Dependency upgrades to clear security vulnerabilities; added unit tests for coverage gaps; legacy Redis
  documentation removed rather than left to mislead.

### 2.7.0-liventus.13 — 2026-07-08 (PRs 487, 490)

- Reduced authentication prompts and fixed frequent MCP server disconnects.
- Removed Redis access-key auth in favour of AAD, with additional authenticated data so a stolen encrypted
  key cannot be replayed into a new malicious session.

### 2.7.0-liventus.12 — 2026-07-02 (PR 483)

- MCP server is dynamically named, so multiple endpoints are distinguishable in a client's tool list.
- `project` is now optional on work item tools that do not require it.
- Unit test coverage added for `wit_get_work_item_history` and `wit_my_commented_work_items`.

### 2.7.0-liventus.11 — 2026-07-08 (PR 482)

- Correct handling of the PKCE `code_challenge`.
- Claude.ai connector setup instructions and MCP client configuration corrections.

### 2.7.0-liventus.10 — 2026-06-30 (PR 481)

- Managed Azure Redis session storage support.
- Graceful elicitation fallback; work item history now tracks scheduling fields.

### 2.7.0-liventus.9 — 2026-06-06 (PR 476)

- Tool steering for a silent failure: work item creation tools ignore parent/child relationships, and a
  separate linking call is required. The tools now say so rather than appearing to succeed.

### 2.7.0-liventus.8 — 2026-06-05 (PR 470)

- Session storage security improvements.
- OAuth authorization codes are pinned to their `client_id` and redirect URIs.

### 2.7.0-liventus.7.2 — 2026-06-04 (PR 469)

- Retry logic for the MCP server instance's health and descriptor checks.
- Deployment pipeline fix; MCP registry instructions corrected to the actual process.

### 2.7.0-liventus.7.1 — 2026-06-03 (PR 467)

- Fixed the Docker build, which excluded `LICENSE.md`.

### 2.7.0-liventus.7 — 2026-06-03 (PR 466)

- Registry configuration, documentation, and licensing visibility updates.

### 2.7.0-liventus.6 — 2026-06-03 (PR 465)

- Added the organization-wide work item reporting tool (`wit_account_my_work_items`), with a cap on field
  filters so one call cannot fan out into hundreds of API requests.
- Tool steering for organization auto-selection by alias and for "my work items" with no project specified.
- README updated with the missing tools.

### 2.7.0-liventus.5 — 2026-06-01

- OAuth signing key fixes; client `state` is now passed to the OAuth callback (RFC 6749 §4.1.2).

### 2.7.0-liventus.4 — 2026-05-31

- OAuth registration fixes and refresh token support.
- Fixed security flaws, a memory leak, and multi-org endpoint errors.

### 2.7.0-liventus.3 — 2026-05-31

- RFC 7591 dynamic client registration, enabling Claude Code as an OAuth client.

### 2.7.0-liventus.2 — 2026-05-30

- Multi-org MCP server endpoint for general tool usage, plus a help document at the base `/` URL.

### 2.7.0-liventus.1 — 2026-05-29

- First release under the fork versioning scheme; deployment steps corrected.

### Before the fork versioning scheme

The safe fork itself landed in PR 413 (2025-08-10): every potentially destructive tool was removed along
with its tests and documentation, `wiki_create_or_update_page` was later restored on the grounds that wiki
history is git-backed and therefore reversible, and the release pipeline moved to Azure Artifacts with
CycloneDX SBOM generation for supply-chain transparency.

## ⚙️ Supported Tools

Interact with these Azure DevOps services:

### 🧿 Core

- **core_list_project_teams**: Retrieve a list of teams for the specified Azure DevOps project.
- **core_list_projects**: Retrieve a list of projects in your Azure DevOps organization.
- **core_get_identity_ids**: Retrieve Azure DevOps identity IDs for a list of unique names.

### 🧭 Organization Discovery

- **ado_list_organizations**: List Azure DevOps organizations accessible to the authenticated user, including optional aliases for human-readable org-name matching.

### ⚒️ Work

- **work_list_team_iterations**: Retrieve a list of iterations for a specific team in a project.
- **work_list_iterations**: List all iterations in a specified Azure DevOps project.
- **work_create_iterations**: Create new iterations in a specified Azure DevOps project.
- **work_assign_iterations**: Assign existing iterations to a specific team in a project.
- **work_get_team_capacity**: Get the team capacity of a specific team and iteration in a project.
- **work_get_iteration_capacities**: Get an iteration's capacity for all teams in iteration and project.
- **work_get_team_settings**: Get team settings including default iteration, backlog iteration, and default area path for a team.

### 📅 Work Items

- **wit_account_my_work_items**: Retrieve account-level "My Work" items without requiring a project; supports optional in-memory filters. Use this when **no project is explicitly provided**, even if organization/client is specified.
- **wit_my_work_items**: Retrieve a list of work items relevant to the authenticated user. Use this **only when project is explicitly known or requested**; the project parameter is required.
- **wit_list_backlogs**: Retrieve a list of backlogs for a given project and team.
- **wit_list_backlog_work_items**: Retrieve a list of backlogs for a given project, team, and backlog category.
- **wit_get_work_item**: Get a single work item by ID.
- **wit_get_work_items_batch_by_ids**: Retrieve a list of work items by IDs in batch.
- **wit_create_work_item**: Create a new work item in a specified project and work item type. For parent/child relationships, create first and then link with **wit_work_items_link**.
- **wit_list_work_item_comments**: Retrieve a list of comments for a work item by ID.
- **wit_list_work_item_revisions**: Retrieve list of revisions for a work item by ID.
- **wit_get_work_items_for_iteration**: Retrieve a list of work items for a specified iteration.
- **wit_add_work_item_comment**: Add a comment to a work item by ID.
- **wit_add_child_work_items**: Create one or more child work items of a specific work item type for the given parent ID.
- **wit_link_work_item_to_pull_request**: Link a single work item to an existing pull request.
- **wit_get_work_item_type**: Get a specific work item type.
- **wit_get_query**: Get a query by its ID or path.
- **wit_get_query_results_by_id**: Retrieve the results of a work item query given the query ID.
- **wit_work_items_link**: Link work items together in batch. Use this right after **wit_create_work_item** when a request asks to both create and link work items.

#### Create + Link Workflow (Important)

When a request includes creating work items and linking hierarchy in one prompt, use this sequence:

1. Call **wit_create_work_item** to create each work item.
2. Call **wit_work_items_link** to create parent/child relations.

Do not rely on setting parent/child fields during create (for example, `System.Parent`) as a replacement for explicit relation linking.

- **wit_add_artifact_link**: Add artifact links (repository, branch, commit, builds) to work items.
- **wit_get_work_item_attachment**: Get a work item attachment.
- **wit_query_by_wiql**: Execute a WIQL query against Azure DevOps. Pass `idsOnly` to get bare ids and a count instead of the full reference objects, whose per-row `url` dominates the size of a large result.
- **wit_get_work_item_history**: Retrieve a filtered, diff-style history for a work item showing only meaningful field changes (state, assignee, iteration path, title, tags, description) with old and new values per revision.
- **wit_my_commented_work_items**: Find work items where the authenticated user has posted a comment, most recent first.

### 📁 Repositories

- **repo_list_repos_by_project**: Retrieve a list of repositories for a given project.
- **repo_list_pull_requests_by_repo_or_project**: Retrieve a list of pull requests for a given repository or project.
- **repo_list_branches_by_repo**: Retrieve a list of branches for a given repository.
- **repo_list_my_branches_by_repo**: Retrieve a list of your branches for a given repository ID.
- **repo_list_pull_requests_by_commits**: List pull requests associated with commits.
- **repo_list_pull_request_threads**: Retrieve a list of comment threads for a pull request.
- **repo_list_pull_request_thread_comments**: Retrieve a list of comments in a pull request thread.
- **repo_get_repo_by_name_or_id**: Get the repository by project and repository name or ID.
- **repo_get_branch_by_name**: Get a branch by its name.
- **repo_get_pull_request_by_id**: Get a pull request by its ID.
- **repo_get_pull_request_changes**: Get the changes associated with a pull request.
- **repo_create_pull_request**: Create a new pull request.
- **repo_create_branch**: Create a new branch in a repository.
- **repo_add_pull_request_reviewers**: Add reviewers to an existing pull request. (Renamed from `repo_update_pull_request_reviewers` upstream to emphasize additive-only action.)
- **repo_reply_to_comment**: Replies to a specific comment on a pull request.
- **repo_search_commits**: Searches for commits.
- **repo_create_pull_request_thread**: Creates a new comment thread on a pull request.
- **repo_vote_pull_request**: Vote on a pull request (approve, reject, etc.).
- **repo_list_directory**: List the contents of a directory in a repository.
- **repo_get_file_content**: Get the content of a file in a repository.

### 🛰️ Pipelines

- **pipelines_get_build_definitions**: Retrieve a list of build definitions for a given project.
- **pipelines_get_build_definition_revisions**: Retrieve a list of revisions for a specific build definition.
- **pipelines_get_builds**: Retrieve a list of builds for a given project.
- **pipelines_get_build_log**: Retrieve the logs for a specific build.
- **pipelines_get_build_log_by_id**: Get a specific build log by log ID.
- **pipelines_get_build_changes**: Get the changes associated with a specific build.
- **pipelines_get_build_status**: Fetch the status of a specific build.
- **pipelines_create_pipeline**: Create a pipeline definition with YAML configuration.
- **pipelines_get_run**: Get a run for a particular pipeline.
- **pipelines_list_runs**: Get top runs for a particular pipeline.
- **pipelines_run_pipeline**: Start a new run of a pipeline.
- **pipelines_list_artifacts**: List artifacts for a given build.
- **pipelines_download_artifact**: Download a pipeline artifact.

### 🔒 Advanced Security

- **advsec_get_alerts**: Retrieve Advanced Security alerts for a repository.
- **advsec_get_alert_details**: Get detailed information about a specific Advanced Security alert.

### 🧪 Test Plans

- **testplan_create_test_plan**: Create a new test plan in the project.
- **testplan_create_test_case**: Create a new test case work item.
- **testplan_add_test_cases_to_suite**: Add existing test cases to a test suite.
- **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.
- **testplan_list_test_cases**: Get a list of test cases in the test plan.
- **testplan_show_test_results_from_build_id**: Get a list of test results for a given project and build ID.
- **testplan_list_test_suites**: Retrieve a list of test suites in a test plan.
- **testplan_create_test_suite**: Create a test suite in a test plan.

### 📖 Wiki

- **wiki_list_wikis**: List all wikis in a project.
- **wiki_get_wiki**: Get details of a specific wiki.
- **wiki_list_pages**: List pages in a wiki.
- **wiki_get_page**: Get a wiki page by path or URL.
- **wiki_get_page_content**: Get the content of a wiki page.
- **wiki_create_or_update_page**: Create a new wiki page, or update an existing one. (Wiki history is preserved via git — changes are reversible.)

### 🔎 Search

- **search_code**: Get code search results for a given search text.
- **search_wiki**: Get wiki search results for a given search text.
- **search_workitem**: Get work item search results for a given search text.

### 🏓 MCP Apps

- **mcp_apps_ping**: A simple ping tool to verify the MCP server is running.

## 🔌 Installation & Getting Started

For the best experience, use Visual Studio Code and GitHub Copilot. See the [getting started documentation](./docs/GETTINGSTARTED.md) to use our MCP Server with other tools such as Visual Studio 2022, Claude Code, and Cursor.

### Prerequisites

1. Install [VS Code](https://code.visualstudio.com/download) or [VS Code Insiders](https://code.visualstudio.com/insiders)
2. Install [Node.js](https://nodejs.org/en/download) 20+
3. Install [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
4. Open VS Code in an empty folder

### Azure Login

Ensure you are logged in to Azure DevOps via the Azure CLI:

```sh
az login
```

### Installation

#### ✨ Install from Liventus Azure Artifacts Feed

This fork is published to an Azure Artifacts feed instead of npmjs. Create (or update) a project-level `.npmrc` so the package can be resolved by `npx` / `npm` for any of the local (stdio) editor configs below:

```ini
registry=https://registry.npmjs.org/
@liventus:registry=https://pkgs.dev.azure.com/LiventusInc/Public/_packaging/node/npm/registry/
```

(The one‑click npm web badge does not apply for Azure Artifacts.)

### Editor Configurations

#### Visual Studio Code & GitHub Copilot (`.vscode/mcp.json`)

After adding the `.npmrc` above, 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).

##### Steps

In your project, add a `.vscode\mcp.json` file with the following content (package renamed to this fork `@liventus/azure-devops-mcp-safe`):

```json
{
  "inputs": [
    {
      "id": "ado_org",
      "type": "promptString",
      "description": "Azure DevOps organization name  (e.g. 'Contoso-LIV')"
    }
  ],
  "servers": {
    "Azure DevOps Local MCP (Safe, Contoso)": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@liventus/azure-devops-mcp-safe", "${input:ado_org}"]
    }
  }
}
```

Save the file, then click 'Start'.

<img src="./docs/media/start-mcp-server.gif" alt="start mcp server" width="250"/>

In chat, switch to [Agent Mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode).

Click "Select Tools" and choose the available tools.

<img src="./docs/media/configure-mcp-server-tools.gif" alt="configure mcp server tools" width="300"/>

Open GitHub Copilot Chat (or your chosen editor) and try a prompt like `List ADO projects`.

> 💥 We strongly recommend creating a `.github\copilot-instructions.md` in your project (or equivalent instructions for other editors). This will enhance your experience using the Azure DevOps MCP Server with GitHub Copilot Chat / Cursor / Claude.
> To start, just include "`This project uses Azure DevOps. Always check to see if the Azure DevOps MCP server has a tool relevant to the user's request`" in your copilot instructions file.

#### Cursor / Windsurf (`.cursor/mcp.json`)

Create a `.cursor/mcp.json`:

```json
{
  "servers": {
    "Azure DevOps Local MCP (Safe, Contoso)": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@liventus/azure-devops-mcp-safe", "${input:ado_org}"],
      "env": {}
    }
  },
  "inputs": [
    {
      "id": "ado_org",
      "type": "promptString",
      "description": "Azure DevOps organization name (e.g. 'Contoso-LIV')"
    }
  ]
}
```

#### Claude Desktop

Claude Desktop reads its MCP config from `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS), `%APPDATA%\Claude\claude_desktop_config.json` (Windows), or `~/.config/Claude/claude_desktop_config.json` (Linux/WSL2). Open it via **File > Settings > Developer > Edit Config**.

Add one entry per ADO organization. The server uses interactive Microsoft account login by default (a browser window opens on first use and the token is cached):

```json
{
  "mcpServers": {
    "Azure DevOps Local MCP (Safe, MyOrgName)": {
      "command": "node",
      "args": ["/absolute/path/to/azure-devops-mcp-safe/dist/index.js", "MyOrgName"]
    }
  }
}
```

Replace `/absolute/path/to/azure-devops-mcp-safe` with the actual path to your local clone and `MyOrgName` with your ADO organization name.

**Multiple organizations:** Add a separate entry for each org. The key (e.g. `ado-my-org`) is the name Claude uses to identify the server:

```json
{
  "mcpServers": {
    "Azure DevOps Local MCP (Safe, OrgOne)": {
      "command": "node",
      "args": ["/absolute/path/to/dist/index.js", "OrgOne"]
    },
    "Azure DevOps Local MCP (Safe, OrgTwo)": {
      "command": "node",
      "args": ["/absolute/path/to/dist/index.js", "OrgTwo"]
    }
  }
}
```

After saving, fully quit and reopen Claude Desktop. On the first tool call, a browser window will open for Microsoft account authentication.

> **Note:** Claude Desktop does not inherit your shell PATH, so use the full path to `node` (e.g. `/opt/homebrew/bin/node` on macOS with Homebrew) if you see a "command not found" error.

#### Claude Code CLI (`.claude.json`)

The Claude Code CLI supports project-level MCP configuration via a `.claude.json` file in the project root. Add an entry for each ADO organization you want available in that project:

```json
{
  "mcpServers": {
    "Azure DevOps Local MCP (Safe, MyOrgName)": {
      "command": "node",
      "args": ["/absolute/path/to/azure-devops-mcp-safe/dist/index.js", "MyOrgName"]
    }
  }
}
```

Or use `npx` to pull from the Liventus feed without a local build:

```json
{
  "mcpServers": {
    "Azure DevOps Local MCP (Safe, MyOrgName)": {
      "command": "npx",
      "args": ["-y", "@liventus/azure-devops-mcp-safe", "MyOrgName"]
    }
  }
}
```

### 🔄 Differences from Upstream

| Upstream Tool Name                 | Safe Fork Status                             | Rationale                                                                                    |
| ---------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- |
| repo_update_pull_request           | **Removed**                                  | Can modify PR titles, descriptions, statuses, and abandon PRs                                |
| repo_update_pull_request_reviewers | Renamed to `repo_add_pull_request_reviewers` | Add-only; "remove" action stripped                                                           |
| repo_update_pull_request_thread    | **Removed**                                  | Can change thread status (resolve, close)                                                    |
| wit_update_work_item               | **Removed**                                  | Modifies existing work item fields                                                           |
| wit_update_work_item_comment       | **Removed**                                  | Modifies existing comments                                                                   |
| wit_update_work_items_batch        | **Removed**                                  | Batch modifies existing work items                                                           |
| wit_work_item_unlink               | **Removed**                                  | Removes links between work items                                                             |
| wit_my_work_items                  | **Behavior changed**                         | Now project-scoped only; omitted project returns guidance to use `wit_account_my_work_items` |
| pipelines_update_build_stage       | **Removed**                                  | Modifies build stage status                                                                  |
| testplan_update_test_case_steps    | **Removed**                                  | Modifies existing test cases                                                                 |
| work_update_team_capacity          | **Removed**                                  | Modifies team member capacity values                                                         |

## 📝 Troubleshooting

See the [Troubleshooting guide](./docs/TROUBLESHOOTING.md) for help with common issues and logging.

## 🎩 Examples & Best Practices

Explore example prompts in our [Examples documentation](./docs/EXAMPLES.md).

For best practices and tips to enhance your experience with the MCP Server, refer to the [How-To guide](./docs/HOWTO.md).

## 🙋‍♀️ Frequently Asked Questions

For answers to common questions about the Azure DevOps MCP Server, see the [Frequently Asked Questions](./docs/FAQ.md).

## 📌 Contributing

We welcome contributions! During preview, please file issues for bugs, enhancements, or documentation improvements.

See our [Contributions Guide](./CONTRIBUTING.md) for:

- 🛠️ Development setup
- ✨ Adding new tools
- 📝 Code style & testing
- 🔄 Pull request process

## 🤝 Code of Conduct

This project follows the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For questions, see the [FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [open@microsoft.com](mailto:open@microsoft.com).

## 📈 Project Stats

<!-- Star history badge removed for private fork -->

## 🏆 Hall of Fame

Thanks to all contributors who make this project awesome! ❤️

<!-- Contributors badge omitted for private Azure DevOps repo -->

> Generated with [contrib.rocks](https://contrib.rocks)

## License

Licensed under the [MIT License](./LICENSE.md).

---

_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._

<!-- version: 2023-04-07 [Do not delete this line, it is used for analytics that drive template improvements] -->
