Provides tools for managing Git repositories within Azure DevOps, including resolving repository IDs, listing branches, and fetching unified diffs for code analysis.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Azure DevOps MCP Serverlist active pull requests for the road-api repository"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Azure DevOps MCP Server
A Model Context Protocol (MCP) server that provides AI-powered tools for interacting with Azure DevOps repositories, pull requests, and work items. Built with FastMCP for seamless integration with Claude and other MCP-compatible AI assistants.
Features
Project Discovery - List all accessible Azure DevOps projects
Repository Management - Resolve repository IDs, list branches
Pull Request Operations - List, create, inspect, and comment on PRs
Work Item Management - Create PBIs, Bugs, and custom work items
Diff Analysis - Fetch complete unified diffs with original and modified content
Code Review - Built-in review policy and automated review capabilities
PR-Work Item Linking - Link pull requests to work items
Auto-Discovery - Automatic tool and resource registration
Extensible Architecture - Simple pattern for adding new functionality
Project Structure
AzureDevopsMcp/
├── src/
│ ├── config.py # Global MCP instance & configuration
│ ├── client.py # HTTP client for Azure DevOps API
│ ├── server.py # Server entry point
│ ├── utils/
│ │ └── helpers.py # Helper functions (repo resolution, blob fetching)
│ ├── tools/
│ │ ├── __init__.py # Auto-import tool modules
│ │ ├── repository.py # Repository & project tools
│ │ ├── pull_requests.py # Pull request tools
│ │ └── work_items.py # Work item tools (PBI, Bug, etc.)
│ └── policies/
│ ├── __init__.py # Auto-import policy modules
│ └── review_policy.py # Code review policy resource
├── main.py # Application entry point
├── requirements.txt # Python dependencies
├── .env # Environment configuration
└── README.mdSetup
1. Clone and Install
git clone <repository-url>
cd AzureDevopsMcp
pip install -r requirements.txt2. Configure Environment
Create a .env file in the project root:
ADO_ORG_URL=https://dev.azure.com/YourOrganization
ADO_PROJECT=YourDefaultProject
ADO_PAT=your_personal_access_token_hereGetting a Personal Access Token (PAT):
Go to Azure DevOps → User Settings → Personal Access Tokens
Create new token with permissions:
Code (Read & Write)- for repository and PR operationsPull Request Threads (Read & Write)- for PR commentsWork Items (Read & Write)- for creating/updating work items
Copy the token to your
.envfile
3. Run the Server
python main.pyThe server will run in stdio mode, ready to accept MCP protocol requests.
Available Tools
Project & Repository Tools
list_projects() -> List[Dict]
Lists all Azure DevOps projects you have access to.
Returns: List of projects with name, id, description, and state.
Usage: Call this before creating work items to discover available projects.
resolve_repo_id(repo_key: str, project: str = None) -> str
Converts a repository name to its GUID identifier.
Parameters:
repo_key- Repository name (e.g., "my-api") or GUID
Returns: Repository GUID
list_branches(repo_id: str, filter_name: str = None, top: int = 100) -> List[Dict]
Lists branches in a repository.
Parameters:
repo_id- Repository GUID fromresolve_repo_idfilter_name- Optional filter by name prefix (e.g., "feature/")top- Maximum number of branches to return
Returns: List of branches with name, fullName, isDefault, creator, objectId
Pull Request Tools
list_pull_requests(repo_id: str, status: str = "active", top: int = 10) -> List[Dict]
Lists pull requests for a repository.
Parameters:
repo_id- Repository GUIDstatus- Filter:"active","completed","abandoned"top- Maximum number of PRs
get_pull_request(repo_id: str, pr_id: int) -> str
Retrieves detailed information about a specific pull request.
create_pull_request(repo_id: str, source_branch: str, target_branch: str, title: str, description: str = None, work_item_ids: List[int] = None) -> Dict
Creates a new pull request.
Parameters:
repo_id- Repository GUIDsource_branch- Full ref name (e.g., "refs/heads/feature/my-feature")target_branch- Full ref name (e.g., "refs/heads/main")title- PR titledescription- Optional PR descriptionwork_item_ids- Optional list of work item IDs to link
Returns: Created PR details including id, url, title, status
set_pr_description(repo_id: str, pr_id: int, description: str) -> Dict
Updates the description of an existing pull request.
LLM Instructions: The description should include a structured format with:
Summary section with bullet points
Test plan section with checkboxes
Auto-detected checkboxes for tests and documentation based on diff analysis
get_pull_request_full_diff(repo_id: str, pr_id: int) -> Dict
Fetches complete diff and all review comments for a PR.
add_pull_request_comment(repo_id: str, pr_id: int, comment: str, file_path: str = None, line: int = None) -> str
Adds a comment to a pull request (top-level or inline).
link_pr_to_work_item(repo_id: str, pr_id: int, work_item_id: int, project: str) -> Dict
Links a pull request to a work item.
Work Item Tools
list_work_item_types(project: str) -> List[Dict]
Lists all available work item types in a project.
Usage: Call this to discover what work item types are available (Bug, PBI, Task, etc.).
list_area_paths(project: str, depth: int = 3) -> List[Dict]
Lists all area paths in a project for organizing work items.
list_iteration_paths(project: str, depth: int = 3) -> List[Dict]
Lists all iteration paths (sprints) in a project.
create_product_backlog_item(project: str, title: str, assigned_to: str, ...) -> Dict
Creates a new Product Backlog Item (PBI).
Required Parameters:
project- Project name (uselist_projects()first)title- PBI titleassigned_to- Email or display name of assignee
Optional Parameters:
description- HTML descriptionacceptance_criteria- HTML acceptance criteriaarea_path- Area path for organizationiteration_path- Sprint assignmentpriority- Priority (1-4)tags- Semicolon-separated tags
create_bug(project: str, title: str, assigned_to: str, description: str, steps_to_reproduce: str, expected_behavior: str, ...) -> Dict
Creates a new Bug work item (using custom "Bugs" type with required fields).
Required Parameters:
project- Project nametitle- Bug titleassigned_to- Assigneedescription- Bug descriptionsteps_to_reproduce- Steps to reproduce the bugexpected_behavior- Expected app behavior
Optional Parameters:
environment- Environment (default: "Dev")area_path,iteration_path,priority,tags
create_work_item(project: str, work_item_type: str, title: str, assigned_to: str, ...) -> Dict
Creates a work item of ANY type. Most flexible tool for custom work item types.
Parameters:
work_item_type- Exact type name fromlist_work_item_types()custom_fields- Dict of custom field reference names to values
Example with custom fields:
create_work_item(
project="MyProject",
work_item_type="Bugs",
title="Fix login error",
assigned_to="john@company.com",
custom_fields={
"Custom.Environment": "Dev",
"Custom.Stepstoreproduce": "1. Go to login\n2. Click submit",
"Custom.Expectedappbehavior": "User should be logged in"
}
)Resources
policy://review - Code Review Policy
Official code review standards and expectations for PR reviews.
Usage: LLMs should load this resource before performing automated code reviews.
Extending the Server
Adding a New Tool
Step 1: Create your tool module in src/tools/
# src/tools/my_tools.py
from ..config import mcp, ADO_ORG_URL
from ..client import client
@mcp.tool()
def my_new_tool(param: str) -> dict:
"""Tool description for LLM."""
# Implementation
passStep 2: Register in src/tools/__init__.py
from . import my_tools # noqa: F401Adding a New Resource
Step 1: Create resource module in src/policies/
# src/policies/my_policy.py
from ..config import mcp
@mcp.resource(uri="policy://my-policy", name="My Policy", description="...")
def get_my_policy() -> str:
return "Policy content..."Step 2: Register in src/policies/__init__.py
Architecture
Global MCP Instance (
src/config.py) - Single FastMCP instance shared across all modulesAuto-Discovery - Modules self-register by importing in
__init__.pySeparation of Concerns - Tools, resources, utilities, and configuration cleanly separated
Type Safety - Full type hints for better IDE support and error checking
Contributing
Contributions welcome! Please follow the existing code structure and patterns when adding new functionality.
This server cannot be installed
Resources
Looking for Admin?
Admins can modify the Dockerfile, update the server description, and track usage metrics. If you are the server author, to access the admin panel.