Skip to main content
Glama

mcp-ado

A FastMCP server for Azure DevOps. It scans your team's work items (by area path), flags anything overdue or stale (not updated in N days), and returns them grouped by assignee.

It also drills into a stalled item (comments, link graph, revision history), reports what is blocking it, reads and writes wiki pages, and can comment on / update / create work items — with writing off by default and gated twice.

Note (2026-08-12): e-mail/notification delivery was removed. Earlier versions could send each assignee an HTML reminder from your own mailbox via delegated Microsoft Graph; the preview_notifications and send_notifications tools, the mailer module, the MAIL_* / ENABLE_SEND / TENANT_ID settings and the azure-identity* dependencies are all gone. This server talks to Azure DevOps only and sends nothing. scan still returns the flagged items grouped by assignee, so a caller can decide what to do with them.

How it works

  1. ADO — a WIQL query returns open (non-done) items UNDER your area path using a PAT (Work Items → Read). Fields are batch-fetched.

  2. Flagging — an item is flagged if its Due/Target date is past, or its ChangedDate is older than STALE_DAYS. Results are grouped by assignee and returned to the caller.

Related MCP server: Azure DevOps MCP Server

Setup

git clone https://github.com/rajivdatta/mcp-ado.git
cd mcp-ado
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
Copy-Item .env.example .env             # then edit .env
Copy-Item targets.example.json targets.json   # optional, see below

Fill in .env:

  • ADO_ORG_URL, ADO_PROJECT, ADO_AREA_PATH, ADO_PAT

  • STALE_DAYS (default 7), optional ADO_WORK_ITEM_TYPES / ADO_EXCLUDE_STATES

  • ADO_ITERATION_PATH — optional; @current auto-detects the sprint whose start/finish dates contain today

  • TRACK_PEOPLE — optional CSV of assignee emails; when set, only those people's items are flagged. Blank = everyone.

  • ENABLE_WRITE — master kill-switch for all writes, default off

Not sure of your area path? After setting org/project/PAT, call list_area_paths to print the tree.

Getting the ADO personal access token

A PAT is the credential this server uses to talk to Azure DevOps. Grant the narrowest scope for the tools you actually intend to use — there is no reason to hand it Full access:

You want

Scopes to grant

Monitoring / scan (the default)

Work Items → Read

get_work_item, blocked_items

Work Items → Read

list_wiki_pages, get_wiki_page

Wiki → Read

add_work_item_comment, update_work_item, create_work_item

Work Items → Read & Write

create_or_update_wiki_page

Wiki → Read & Write

Read-only is the right default: with ENABLE_WRITE=false (the shipped value) the write tools refuse before making any request, so a read-only PAT loses you nothing.

  1. Sign in to your Azure DevOps organization: https://dev.azure.com/YOUR_ORG

  2. Open User settings (the icon beside your avatar, top right) → Personal access tokens. Direct link: https://dev.azure.com/YOUR_ORG/_usersSettings/tokens

  3. Click + New Token.

  4. Fill in the token:

    • Name — anything memorable, e.g. mcp-ado

    • Organization — the org holding the work items. If you belong to several, a token scoped to one org will not work against another.

    • Expiration — pick the shortest window you'll tolerate re-issuing.

  5. Under Scopes, choose Custom defined, then expand Work Items and tick Read. Leave everything else unchecked.

  6. Click Create, then copy the token immediately — Azure DevOps shows it exactly once and you cannot retrieve it afterwards.

  7. Paste it into .env as ADO_PAT=..., then verify with the test_connection tool, which reports the open-item count on success.

.env is listed in .gitignore, so the token stays out of git. Keep it that way — a PAT is a bearer credential, so anyone holding it has your read access until it expires or you revoke it.

When it stops working. PATs expire, and an expired or revoked token fails every call. If test_connection starts returning an authentication error — or an HTML sign-in page instead of JSON — re-issue the token at the same Personal access tokens page and update .env. Two other causes worth ruling out: the token was scoped to a different organization than ADO_ORG_URL, or it lacks the Work Items → Read scope. Some organizations also restrict who may create PATs at all; if + New Token is unavailable, your Azure DevOps administrator has to permit it.

The PAT is now the server's only credential — with e-mail removed there is no second sign-in path and no Graph token.

Scanning more than one team

Drop a targets.json next to server.py to scan several project/area/iteration combinations in one pass (org + PAT stay global in .env):

[
  { "name": "Data", "project": "YOUR_PROJECT",
    "area_path": "YOUR_PROJECT\\Your Team", "iteration_path": "@current" }
]

Items are de-duplicated by id across targets, and a person with flagged items in several targets is reported once, with their items merged into a single group. Without targets.json, the ADO_PROJECT / ADO_AREA_PATH / ADO_ITERATION_PATH env values are used as a single target.

Tools

Read-only

Tool

Purpose

list_targets

Show the resolved scan targets

test_connection

Verify PAT + config, show open-item count

list_area_paths

Print area-path tree for a project

current_iteration

Show configured vs resolved sprint (@current)

scan

Flag overdue/stale items grouped by assignee

get_work_item

One item in full — fields, links, comments, revision history

blocked_items

Blocked items and what is blocking them

list_wiki_pages

Wiki page hierarchy

get_wiki_page

One wiki page's markdown (+ etag)

Changes something — each gated twice

Tool

Needs

Purpose

add_work_item_comment

ENABLE_WRITE + confirm

Post a discussion comment

update_work_item

ENABLE_WRITE + confirm

Change state / assignee / dates / any field

create_work_item

ENABLE_WRITE + confirm

Create an item, optionally under a parent

create_or_update_wiki_page

ENABLE_WRITE + confirm (+ allow_overwrite)

Write a wiki page

Safety model. Nothing in Azure DevOps changes unless you opt in twice: the .env master switch (ENABLE_WRITE, default off) and an explicit confirm=True on the call. Extra guards:

  • update_work_item and create_work_item accept validate_only=True, which asks Azure DevOps to validate the change and save nothing — a real dry run against the server, usable even with ENABLE_WRITE=false.

  • create_or_update_wiki_page always reads the page first and reports what would change. Overwriting an existing page also needs allow_overwrite=True, because the whole page is replaced, not merged — and the response echoes the previous content so an unwanted overwrite is recoverable.

  • Nothing leaves your machine except Azure DevOps API calls — there is no mail path and no second credential.

Drilling into a stalled item

scan returns a dozen summary fields per item — enough to flag it, not enough to explain it. get_work_item adds the discussion, the parent/child chain, and a per-revision changelog, so you can tell a genuinely untouched item from one being nudged without progress:

scan(only_flagged=True) → get_work_item(id=33740, include_history=True)

blocked_items answers the related question — is this stalled because of someone else? It reports items whose state/tags declare them blocked, plus items with an unfinished predecessor link, naming the blocker. Chasing an assignee whose work is gated on another open item wastes everyone's time, so check this before acting on a scan result.

Suggested flow

test_connection → scan → get_work_item / blocked_items on anything flagged

Register with Claude

Add to your MCP config (claude_desktop_config.json for Desktop, or via claude mcp add for Claude Code):

{
  "mcpServers": {
    "ado": {
      "command": "C:\\path\\to\\mcp-ado\\.venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\mcp-ado\\server.py"]
    }
  }
}

Notes

  • Scheduling. For a recurring check, ask Claude to run scan on a schedule, or drive it from Windows Task Scheduler with a small script that imports server.py and calls scan().

  • Dates are compared in UTC.

  • Dependencies are now just mcp, requests and python-dotenv. The azure-identity / azure-identity-broker packages existed only for the Graph mail sign-in and were dropped; you can prune them from an existing .venv with pip uninstall azure-identity azure-identity-broker.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers