Services → Azure DevOps

Connect Azure DevOps

Projects, repositories, pull requests, pipelines, builds and their logs, environments and deployments, classic releases, work items and agent pools — thirty-two tools, one Personal Access Token, nothing to install. Azure DevOps is where "what was deployed, and which step failed" is answered.

Tier 2 A Personal Access Token with Read scopes only ~5 min profile azuredevops/read-only

Setting this up with your own agent? Give it these instructions.

The whole setup

  1. In Azure DevOps, open User settings → Personal access tokens → New Token.
  2. Name it prodpeek. Organization: the one you will enter as the upstream. Expiration: 90 days or less.
  3. Scopes: Custom defined. Tick only these:
ScopePermission
BuildRead
CodeRead
Project and TeamRead
Work ItemsRead
ReleaseRead
Variable GroupsRead
Agent PoolsRead
EnvironmentRead & manage — *optional*, see below
  1. Create, and copy the token.
  2. In Prodpeek: Services → Add a service, pick azuredevops/read-only, set the upstream to https://dev.azure.com/your-org, paste the PAT, Test connection.

Environment has no Read-only scope

list_environments and list_environment_deployments answer "what is in prod right now", and they need Environment · Read & manage — Azure DevOps has no Read form of it. That scope can also manage environments and their approval checks. If that trade is not worth it to you, leave it off: those two tools will be refused by Azure DevOps and everything else works.

The upstream is the organisation, not a project. If you paste https://dev.azure.com/acme/Shop/_git/api, Prodpeek says so and tells you to use https://dev.azure.com/acme. https://acme.visualstudio.com and an on-premises collection URL (https://tfs.example.com/tfs/DefaultCollection) work too.

Why there is no MCP server to install

Microsoft publishes an Azure DevOps MCP server. Its hosted form authenticates with OAuth as a signed-in user — the same model as Grafana Cloud's and Cloudflare's, and unusable for the same reason: Prodpeek is a server-side gateway holding a stored team credential, with no browser and no signed-in user.

The Azure DevOps REST API takes a Personal Access Token, which is exactly the shape Prodpeek is built around. So it speaks it directly.

What your agent can then do


azuredevops__list_builds                     did the last deploy fail, and on which branch
azuredevops__get_build_timeline              which step failed, and the error it raised
azuredevops__get_build_log                   the end of that step's log, as plain text
azuredevops__list_environment_deployments    what is in prod right now, and since when
azuredevops__list_pipeline_runs              recent runs of one pipeline
azuredevops__list_commits                    what changed just before this broke
azuredevops__list_pull_requests              which PR carried that change, and who approved it
azuredevops__get_item                        the deploy config at that commit
azuredevops__list_releases                   classic releases, and each environment's status
azuredevops__list_variable_groups            whether DB_HOST is even set (values removed)
azuredevops__list_agents                     whether the self-hosted agent is online
azuredevops__get_work_item                   the incident ticket, with its links

get_build_timeline is the one to start with: one call names the failing step and the error it raised, and get_build_log then reads just that log. Read the end of the log first — list_build_logs gives the line count, and each call returns at most 2000 lines.

What it refuses, and the ones that matter

Service connections have no tool. _apis/serviceendpoint/endpoints is the map of every credential the organisation holds for Azure, AWS, container registries and clusters. There is no code path in the adapter that builds that path.

Secure files, PATs and agent registration tokens have no tool. Signing keys and kubeconfigs; the organisation's other tokens; the token that lets a machine join your build pool.

Variable values are removed. list_variable_groups and get_release keep every variable's name and whether it is secret, and replace every value. Secret values arrive empty from Azure DevOps anyway; the others are frequently secrets somebody forgot to tick. list_agents never asks for an agent's capabilities, which are its environment variables.

Free-form WIQL has no tool. It is a POST. run_query runs a *saved* query by id instead, which is a GET.

Queuing a build has no tool, and it is the one people ask for. "Just re-run the pipeline" sounds harmless. A pipeline that deploys is a production change.

Why Tier 2

The Tier 1 half is real: a PAT made from Read scopes refuses every write in this profile *at Azure DevOps*, independently of the gateway. Keep it that way.

It is Tier 2 anyway. The Environment scope has no Read-only form, and several allowed reads return source code and build logs, which hold whatever was committed or printed. The roll-up decides the label.

Azure DevOps also offers no honest introspection: a PAT cannot ask which scopes it holds. So this profile carries no scope probe, and [prove](../use/prove.md) reports the scope as *not introspectable* rather than claiming a check it never made.

Checking the credential really cannot write


ORG=https://dev.azure.com/your-org
PROJECT="Your Project"

# Should succeed, and name the identity the PAT belongs to
curl -sS -u ":$PAT" "$ORG/_apis/connectionData?api-version=7.1-preview" | head -c 300

# Should be REFUSED: queue a build of a definition that does not exist
curl -sS -o /dev/null -w '%{http_code}\n' -u ":$PAT" -X POST \
-H 'Content-Type: application/json' -d '{"definition":{"id":999999999}}' \
"$ORG/$(printf %s "$PROJECT" | sed 's/ /%20/g')/_apis/build/builds?api-version=7.1"

A 401 or 403 on the second is the vendor fence doing its half. A 404 ("definition not found") means the PAT could queue builds and only the made-up id stopped it — remake it without Build · Read & execute. The definition id is deliberately one that cannot exist, so the check never queues anything.