ADO MCP
This project uses FastMCP 2.0 python sdk to interact with Azure DevOps.
Setup
-
Install Dependencies:
task install -
Set up Authentication: The MCP server supports multiple authentication methods (in order of precedence):
Option 1: Personal Access Token (PAT)
Environment Variable Method:
task setup-envThis creates a
.envfile with your Personal Access Token (PAT) and other necessary variables.Direct Configuration:
export AZURE_DEVOPS_EXT_PAT="your-personal-access-token" export ADO_ORGANIZATION_URL="https://dev.azure.com/YourOrg"
Option 2: Azure CLI Authentication (Recommended)
If you already use Azure CLI, you can authenticate using your existing session:
# Login to Azure (if not already logged in) az login # The MCP server will automatically use your Azure CLI credentials task run
Benefits of Azure CLI authentication:
- No need to manage Personal Access Tokens
- Uses your existing Azure credentials
- More secure than storing PATs
- Automatically refreshes tokens
Note: Azure CLI authentication requires the user to be logged in with an account that has access to the Azure DevOps organization.
Testing
-
Run Tests:
task test
-
Test Coverage:
task coverage
Usage
-
Run the MCP Server:
task run -
Inspect the MCP Server:
task inspect
Working with Azure DevOps URLs
Understanding Azure DevOps URL Structure
When working with Azure DevOps URLs from the web interface, it's important to understand the difference between build/run IDs and pipeline definition IDs:
Example URL: https://dev.azure.com/RussellBoley/ado-mcp/_build/results?buildId=324&view=results
- Organization:
RussellBoley(from the URL path) - Project:
ado-mcp(from the URL path) - buildId=324: This is a run ID (specific execution instance), NOT a pipeline definition ID
Getting Pipeline Information from Build URLs
To work with a specific build/run from an Azure DevOps URL:
-
Extract URL components:
- Organization:
RussellBoley - Project:
ado-mcp - Build/Run ID:
324(frombuildIdparameter)
- Organization:
-
Use
get_build_by_idto find the pipeline:# Get build details to find the pipeline definition build_details = await client.call_tool("get_build_by_id", { "project_id": "49e895da-15c6-4211-97df-65c547a59c22", # ado-mcp project ID "build_id": 324 # The buildId from the URL }) # Extract pipeline information pipeline_id = build_details.data["definition"]["id"] # e.g., 84 pipeline_name = build_details.data["definition"]["name"] # e.g., "log-test-complex"
-
Then use pipeline-specific tools:
# Get detailed run information run_details = await client.call_tool("get_pipeline_run", { "project_id": "49e895da-15c6-4211-97df-65c547a59c22", "pipeline_id": pipeline_id, # 84 "run_id": 324 # Same as buildId }) # Get failure analysis if needed failure_summary = await client.call_tool("get_pipeline_failure_summary", { "project_id": "49e895da-15c6-4211-97df-65c547a59c22", "pipeline_id": pipeline_id, "run_id": 324 })
Common Mistake to Avoid
❌ Don't do this:
# This will fail - you can't guess the pipeline_id
await client.call_tool("get_pipeline_run", {
"project_id": "49e895da-15c6-4211-97df-65c547a59c22",
"pipeline_id": 15, # Wrong! This is just a guess
"run_id": 324
})
✅ Do this instead:
# First, get the build details to find the correct pipeline_id
build_data = await client.call_tool("get_build_by_id", {
"project_id": "49e895da-15c6-4211-97df-65c547a59c22",
"build_id": 324 # buildId from URL
})
pipeline_id = build_data.data["definition"]["id"] # Now you have the correct pipeline_id
# Then use it for pipeline-specific operations
await client.call_tool("get_pipeline_run", {
"project_id": "49e895da-15c6-4211-97df-65c547a59c22",
"pipeline_id": pipeline_id, # Correct pipeline_id
"run_id": 324
})
Available Tools for Build/Pipeline Analysis
get_build_by_id: Get build details and extract pipeline information from a build/run IDget_pipeline_run: Get detailed run information (requires both pipeline_id and run_id)get_pipeline_failure_summary: Analyze failures with root cause analysisget_failed_step_logs: Get logs for failed stepsget_pipeline_timeline: Get execution timelinelist_pipeline_logs: List all available logsget_log_content_by_id: Get specific log contentrun_pipeline_and_get_outcome: Run a pipeline and wait for completion with analysis
Metadata
Release files for ado-mcp-raboley 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ado_mcp_raboley-0.0.1.tar.gz | 49.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ado_mcp_raboley-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 78.6 kB
Release files / ado_mcp_raboley-0.0.1.tar.gz
| Download URL | ado_mcp_raboley-0.0.1.tar.gz |
|---|---|
| Size | 49.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa4078647f9f607a4b65e68c9ac9cd7bce406d48e8f13b4c7d3385d1ad03d042
|
|
BLAKE2b-256 checksum How to use checksums |
6246217e1bd6198e61612f4c6195202e23895a42eaeea1399c4f2a2b3308f32e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.20
|
Release files / ado_mcp_raboley-0.0.1-py3-none-any.whl
| Download URL | ado_mcp_raboley-0.0.1-py3-none-any.whl |
|---|---|
| Size | 29.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a5fb5eaaf617772e74a65a50685c80d8f300498622afcd457fb28db8c4b7e9a5
|
|
BLAKE2b-256 checksum How to use checksums |
75de94e944b80c093c9a47d972f71332fe09df5999be30b579c552daf82eb502
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.7.20
|
Security for ado-mcp-raboley 0.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.