Work an Azure DevOps organization — repositories and pull requests, pipeline runs and their artifacts, and work items queried with WIQL.
Azure DevOps ships in the w6w first-party pack. It declares 19 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.azuredevopsAzure DevOps brings an organization’s repositories, pipelines and work items into a workflow. Browse repositories and branches, read commit history, and open, inspect and comment on pull requests — as a draft by default, since merging stays a human decision this app deliberately never automates. Pipeline actions list, run, queue and cancel builds, and read a run’s artifacts and results, distinguishing a genuine pass from one that only partially succeeded.
Work items are the deepest integration: create and update Bugs, Tasks, User Stories or whatever a project’s process defines, and query with WIQL — resolved into full field data automatically, since Azure DevOps’s own query API only returns bare IDs. Custom fields pass through untouched alongside the well-known ones, so a team’s own tracking fields keep working.
The app also normalizes some of Azure DevOps’s rougher edges for a workflow author: branch names work whether an endpoint expects a bare name or a full ref, and reviewer votes are read by their meaning rather than their raw numeric encoding. It deliberately never deletes or merges anything, and never edits pipeline definitions or branch policies — those stay in version control and in human hands.
Three routes to the same 19 actions. The Workflow tab is generated from Azure DevOps's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.
branch-list Azure DevOps has no branches endpoint — only refs, where branches and tags differ by prefix alone. This filters to one and returns both the full refs and the bare names.
build-artifact-list What a pipeline run produced, with download URLs. An empty list means either the run failed early or its artifacts were cleaned up — `build-get` tells you which.
build-cancel Ask a run to stop. The status becomes `cancelling`, not cancelled — the agent stops when the current step ends, and `always()` steps still run.
build-definition-list Pipelines and, in one call, how each last did. The latest run and the latest COMPLETED run are different fields, and only the second says whether it is broken.
build-get One run, with `finished` and `succeeded` as explicit booleans. `partiallySucceeded` is not folded into success — a step failed, and a deployment should stop and ask.
build-list Pipeline runs. `result` does not exist until `status` is completed — so checking for failure on a running build reads undefined and concludes it passed.
build-queue Queue a pipeline run. It returns QUEUED — nothing has compiled — and the branch selects the pipeline definition as well as the code, since the YAML lives in the repo.
commit-list Commit history, filterable by branch, author and date. The branch is a BARE name here, unlike the pull request endpoints in the same API, so this normalises it.
project-list The projects this token can SEE — Azure DevOps says nothing about the rest. An empty list on a real organization means a missing Project and Team scope, not an empty account.
pull-request-create Open a pull request. Defaults to DRAFT, against Azure DevOps's own default — an unattended workflow otherwise notifies reviewers and starts a validation build on every run.
pull-request-get One pull request by id alone — no repository needed. Reviewer votes are numbers where -10 is a rejection, so they can only be compared, never summed.
pull-request-list Pull requests, defaulting to ACTIVE ones. Azure DevOps ignores an unrecognised filter rather than rejecting it, so a mistyped one silently returns the default set.
pull-request-thread-create Start a comment thread — on the overview, or anchored to a line of the diff. An `active` thread blocks the merge where policy requires comments resolved.
repository-get One repository, by name or id. `defaultBranch` comes back as a full `refs/heads/…` ref, which is what the other git calls expect.
repository-list Git repositories in a project — Azure DevOps nests them, so two projects can hold the same name. Disabled repositories are still listed and reject every operation.
work-item-create Create a Bug, Task or story. Azure DevOps wants a JSON Patch document here, not an object — this builds it, and qualifies `title` to `System.Title` for you.
work-item-get One work item. Its values are namespaced — `System.Title`, not `title` — so this returns both the raw fields and the common ones flattened under short names.
work-item-query Run a WIQL query and get work items back. WIQL itself returns only IDS — whatever the SELECT said — so this fetches the fields for you in batches.
work-item-update Change named fields; everything else is left alone. Setting `history` appends a comment rather than overwriting — the supported way for an automation to say why.
A workflow step names the app and the action, and the editor fills in the
connection when you pick one. This is the Step shape from the
workflow spec, carrying Azure DevOps's real ids.
{
"manifestVersion": "2",
"name": "azuredevops-example",
"steps": [
{
"id": "branch-list",
"uses": {
"app": "io.w6w.azuredevops",
"action": "branch-list",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"project": "<project>",
"repository": "<repository>"
}
}
]
}branch-list build-artifact-list build-definition-list build-get build-list +14 more actions available
Every app-specific value here is a blank you have to fill in. An
app action is reached through the connection that authenticates it, so the
address is a connection id, not the app id — and connections belong to your account,
so a public page cannot know yours. Create one for Azure DevOps, then fill in
the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the
parameters that action declares. The call itself is real — the shape is transcribed
from the studio's own snippet builder, which prints the same kind of blanks — but
nothing in it is specific to Azure DevOps. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { W6wClient, isActionRun } from "@w6w/sdk";
// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();
const envelope = await client.run({
urn: "conn_YOUR_CONNECTION_ID",
action: "branch-list",
payload: {
project: "<value>",
repository: "<value>",
// kind: "<value>",
// contains: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action branch-list --payload '{"project":"<value>","repository":"<value>"}' Give an AI agent Azure DevOps — without giving it Azure DevOps's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.
One tool call{
"name": "w6w_invoke",
"arguments": {
"ref": "app:io.w6w.azuredevops#branch-list",
"input": {
"project": "<project>",
"repository": "<repository>"
}
}
}
Every tool names its target with a single ref. The
app: form above doesn't name a connection at all — the
host resolves which of the caller's Azure DevOps connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.
Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.
Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.
Azure DevOps's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.
The MCP surface is part of the hosted platform. Azure DevOps itself is MIT, and the runtime that executes it is source-available (FSL).
Azure DevOps declares its own checks, so its health is a property of the app rather than something the host guesses at.
Repos, Pipelines, Boards and Core services, each reported by name. Health is per geography, so an outage elsewhere is named rather than counted blindly.
Whether this connection's organization answers and what its token can see. A missing scope answers 404 rather than 403, so zero visible projects usually means a scope, not an outage.