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.
| Policy | azuredevops/read-only |
| Connection kind | azuredevops |
| Upstream looks like | https://dev.azure.com/your-org |
| Credential | A Personal Access Token with Read scopes only |
| Tier | 2 — Prodpeek is the only fence, and the profile says so |
| Time to set up | about 5 minutes |
Grant exactly these¶
- Custom defined scopes — never Full access
-
Full access is every scope in the organisation, including service connections and token administration. Custom defined lets you tick exactly the Read scopes below and nothing else.
- Build · Read, Code · Read, Project and Team · Read
-
Pipelines, builds, build logs and timelines; repositories, branches, commits, pull requests and files; the project list every other tool needs.
- Work Items · Read, Release · Read, Variable Groups · Read, Agent Pools · Read
-
Tickets and saved queries; classic releases; which variables exist (their values are blanked by the adapter); whether the self-hosted agent is online.
- Environment · Read & manage — only if you want deployment records
-
list_environmentsandlist_environment_deploymentsneed it, and Azure DevOps offers no Read-only form of this scope. It lets the holder manage environments and their approvals. Leave it off unless "what is in prod" matters more to you than that; the other tools work without it. - The organisation in the URL, and an expiry of 90 days or less
-
A PAT belongs to one organisation. Pick the same one you enter as the upstream, or every call looks like a rejected PAT.
Do not grant these¶
Each of these would undo the point of the rest
Full access
Every scope, including the ones that manage service connections and mint tokens. The gateway would become the only fence in front of the whole organisation.
Any Read & write, Read & execute or Read, write & manage scope
The profile denies every write and the adapter issues only GET, so it would change nothing about what Prodpeek does — but it removes the vendor's half of the fence, and that half is the one that still holds if this one has a bug. Build · Read & execute is the one people tick without thinking: it queues builds, and a build that deploys is a production change.
Service Connections
Service connections are stored credentials for Azure, AWS, registries and clusters. The adapter has no tool for them; the PAT should not be able to reach them either.
Tokens
Token administration. A PAT that can manage PATs can mint a credential that never passes through Prodpeek.
The whole setup¶
- In Azure DevOps, open User settings → Personal access tokens → New Token.
- Name it
prodpeek. Organization: the one you will enter as the upstream. Expiration: 90 days or less. - Scopes: Custom defined. Tick only these:
| Scope | Permission |
|---|---|
| Build | Read |
| Code | Read |
| Project and Team | Read |
| Work Items | Read |
| Release | Read |
| Variable Groups | Read |
| Agent Pools | Read |
| Environment | Read & manage — optional, see below |
- Create, and copy the token.
- In Prodpeek: Services → Add a service, pick
azuredevops/read-only, set the upstream tohttps://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 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.
Check you got it right¶
- [ ] The PAT's organisation is the one in the upstream URL.
- [ ] Scopes says Custom defined, and every ticked scope is Read (Environment excepted, if you chose it).
- [ ] The expiry is 90 days or less.
- [ ] Test connection shows list_builds under Allowed.
- [ ] Calling
connection_datareturns the identity you created the PAT as.
If an agent is reading this
Do not suggest Microsoft's Azure DevOps MCP server — its hosted form is OAuth as a signed-in user, so a gateway cannot use it. Prodpeek has a native Azure DevOps adapter; the upstream is the organisation URL (https://dev.azure.com/
Then add it to Prodpeek¶
Console: Services → Add a service, pick azuredevops/read-only, paste the credential. Or from an agent, add_service with no credential and hand over the drop link.
Then press Test connection and read all three lists.