Skip to content

Releases: eXoz00rd/AzureMCP

v0.2.1 — no cookies carried between HTTP callers

Choose a tag to compare

@github-actions github-actions released this 24 Sep 12:46
c478dda

A security fix for the HTTP server. Upgrade every deployment that serves more than one user.

Security

  • The server no longer keeps cookies from Azure DevOps. Over HTTP every caller shares one pooled connection handler, and in 0.2.0 it stored the cookies Azure DevOps set and sent them with later requests from other callers, next to those callers' own PATs. Each request now carries its caller's PAT and nothing another caller left behind. A new end-to-end test calls as two users in turn and fails if any request carries a cookie issued to someone else (#64)

stdio — the NuGet tool used by Copilot, Claude Code, and other local clients — serves a single user and was not affected.

Upgrading

  • Docker: docker pull ghcr.io/exoz00rd/azuremcp:0.2.1 and recreate the container. Deployments following latest or 0.2 pick it up on their next pull
  • Helm: helm upgrade to chart 0.2.1
  • Open WebUI: the plugin is unchanged; nothing to do

62 tools, 470 tests.

Full changelog: v0.2.0...v0.2.1

v0.2.0 — the server as a container beside Open WebUI, with each user's own PAT

Choose a tag to compare

@github-actions github-actions released this 24 Sep 09:39
1ae9576

The server now runs as its own container next to Open WebUI. It serves MCP over Streamable HTTP, holds no PAT of its own, and every request carries the caller's own PAT, so Azure DevOps attributes every comment, vote, and queued build to the person who asked. stdio stays the default: Copilot, Claude Code, and every existing client keep working unchanged.

Added

  • Streamable HTTP transport — ADOS_TRANSPORT=http serves a stateless MCP endpoint behind a shared bearer token. The guard runs on the endpoint routing selects, rejects unknown browser origins, and allows anonymous access only on loopback (#55)
  • Each caller's own PAT — every HTTP request carries its caller's PAT in X-Azure-DevOps-Pat. ADOS_PAT is refused over HTTP, so no request can fall back to a shared identity (#56, #61)
  • Health endpoint and container logging — /healthz answers probes without a token, and a healthy start logs nothing (#57, #63)
  • Container image — ghcr.io/exoz00rd/azuremcp:0.2.0 for linux/amd64 and linux/arm64 on the chiseled ASP.NET 10 runtime: non-root, no shell, signed with cosign, with a build provenance attestation and an SBOM (#58)
  • Helm chart — oci://ghcr.io/exoz00rd/charts/azuremcp with a hardened pod, a NetworkPolicy admitting only Open WebUI, and an internal certificate authority from a ConfigMap that keeps the public roots (#59)

Changed

  • The Open WebUI plugin calls the server over HTTP instead of downloading and starting a binary inside Open WebUI. Its valves are now the server URL, the server's token, and the timeout; the collection URL and certificate authority moved to the server. The self-contained linux-x64 binary is no longer attached (#60)
  • The NuGet package needs the ASP.NET Core runtime in every mode, stdio included. The .NET 10 SDK already ships it (#55)

Upgrading from 0.1.3 with Open WebUI

The 0.1.3 plugin started the server inside Open WebUI; this one needs the server running beside it. Deploy the image or the chart first (Running over HTTP), then replace the plugin's code with azure_devops_openwebui.py from this release and set its valves: server_url (for example http://azuremcp:8080/mcp) and server_token. Replacing the code of the existing tool keeps the PAT each user already entered; a newly created tool starts without them.

Assets

File Purpose
azure_devops_openwebui.py the Open WebUI plugin, generated from the tools this release registers

62 tools, 469 tests.

Full changelog: v0.1.3...v0.2.0

v0.1.3 — Open WebUI plugin with per-user PATs, clearer connection errors

Choose a tag to compare

@github-actions github-actions released this 23 Sep 13:16
bae7cfb

Open WebUI can now use this server. The release ships a tool plugin that runs inside Open WebUI, starts the server on demand, and passes each user their own PAT — one instance serves many users without sharing a credential.

Added

  • Open WebUI plugin (azure_devops_openwebui.py) — generated from the tools this server registers, so it never drifts from them. It downloads the self-contained server below, verifies its SHA-256 before running it, and starts it for the duration of a single call with the calling user's own PAT taken from Open WebUI's per-user valves (#49, #51)
  • Support for an internal certificate authority — paste its PEM into the plugin's ca_certificate valve and it is merged with the container's system roots into the trust bundle handed to the server. Certificate validation is never disabled (#52)

Changed

  • A server that cannot be reached is now explained instead of surfacing a raw socket or SSL failure. The message names the collection and what to verify. An untrusted certificate is reported on the first attempt, because retrying it can only produce the same answer (#53)

Assets

File Purpose
azure_devops_openwebui.py the Open WebUI plugin, with this release's download URL and checksum already set
AzureDevOpsServer.Mcp-linux-x64 self-contained server the plugin downloads on first use
AzureDevOpsServer.Mcp-linux-x64.sha256 checksum of that binary

Using it with Open WebUI

  1. As an administrator, open Workspace → Tools → +, paste azure_devops_openwebui.py, and save
  2. Open the tool's Valves and set collection_url (plus ca_certificate when the server uses an internal authority)
  3. Grant access to the users or groups that should see the tool
  4. Each user opens Integrations → Tools → Valves in a chat and enters their own PAT

Requires Open WebUI 0.11.x on linux-x64, and outbound access to this release from the Open WebUI container.

62 tools, 416 tests.

Full changelog: v0.1.2...v0.1.3

v0.1.2 — richer work item reads, safer writes, clearer errors

Choose a tag to compare

@eXoz00rd eXoz00rd released this 14 Sep 10:58
2c235e7

Ten fixes and additions since v0.1.1, focused on work item reads/writes and truncation/error reporting.

Changed

  • Breaking: update_work_item, create_work_item, link_work_item, and add_work_item_attachment now return a minimal WorkItemWriteResult (id, rev, changed fields, success) instead of the full WorkItem.

Added

  • includeRelations on get_work_item and get_work_items fetches relations without requiring a full fields expansion.
  • expectedRevision on update_work_item lets a caller require a specific revision before writing; a mismatch is reported with the current revision instead of silently overwriting a concurrent change.
  • descriptionFormat on get_work_item, get_work_items, and get_work_item_revisions (html default, text) strips markup and decodes entities from rich-text fields.

Fixed

  • Eight list tools reported no truncation when a result exactly filled its cap. list_branches, list_commits, list_pull_requests, list_my_pull_requests, list_releases, list_release_approvals, list_builds, and get_work_item_revisions now request one extra item and report truncation the same way list_repository_items and list_work_item_comments already did.
  • get_work_items failed with an opaque server error on an oversized id batch, and project pagination had no upper bound and could loop forever on a malformed continuation token. Both are now bounded client-side with a clear error.
  • Authentication failures collapsed every 401/203 response into one generic message. It now reports the actual request URI, HTTP status, and the server's offered WWW-Authenticate schemes, without ever including the Authorization header or the PAT.

Known issues

  • The write-path changes above (expectedRevision, the minimal write result shape) are verified only against stub Azure DevOps handlers in this release, not yet against a real Azure DevOps Server.

62 tools, 391 tests.

Full changelog: v0.1.1...v0.1.2

v0.1.1 — safer votes, real comment ids, streamed responses

Choose a tag to compare

@eXoz00rd eXoz00rd released this 10 Sep 21:12
edcdb38

Five fixes and one API correction since v0.1.0, plus release/CI hygiene.

Changed

  • Breaking: add_work_item_comment now posts through _apis/wit/workItems/{id}/comments instead of writing to System.History, and returns a WorkItemComment (real id, version) instead of the whole WorkItem. It also accepts an optional project parameter, matching list_work_item_comments.

Added

  • get_work_item_comment reads a single work item comment by id.

Fixed

  • vote_on_pull_request silently cleared the reviewer's required flag. The PUT only sent { vote }, and that endpoint replaces the whole reviewer resource. The client now looks up the reviewer's current isRequired before voting and includes it in the request.
  • Unsafe HTTP methods (POST/PATCH/PUT/DELETE) were retried automatically on transient Azure DevOps failures, which could create duplicate work items, comments, releases, attachments, or queued builds when a request succeeded but its response was lost. Only GET still retries.
  • Repository file content was fully buffered before maxChars could limit it. Large files now stream through a byte-level JSON decoder instead of being materialized in full first.
  • Build logs stream instead of buffering the whole response.
  • The NuGet package version is now the single source for the MCP manifest version, so the two can no longer disagree.

An end-to-end smoke test now covers the stdio MCP transport, and CI enforces a test coverage threshold.

Known issues

  • add_work_item_comment and get_work_item_comment (above) are verified only against stub Azure DevOps handlers in this release, not yet against a real Azure DevOps Server.

62 tools, 263 tests.

Full changelog: v0.1.0...v0.1.1

v0.1.0 — first stable release

Choose a tag to compare

@eXoz00rd eXoz00rd released this 12 Aug 11:36

The first non-preview release. Nine previews landed 60 tools, toolset/read-only configuration, and on-premises-specific error handling; this one is a compatibility fix found through real on-premises use.

Fixed

  • create_or_update_wiki_page failed with 405 Method Not Allowed against some on-premises Azure DevOps Server installations. The page-version lookup that runs before every write sent an HTTP HEAD request, and not every on-prem server accepts HEAD on that route — the client never got as far as sending the PUT. The lookup now uses GET instead, which is confirmed to work, with If-Match semantics unchanged.

60 tools, 185 tests.

Full changelog: v0.1.0-preview.9...v0.1.0

v0.1.0-preview.9 — pull request/work item links and correct optional-parameter schemas

Choose a tag to compare

@eXoz00rd eXoz00rd released this 12 Aug 11:36

Closes the pull request ↔ work item gap and fixes a schema bug that made every optional tool parameter look required to MCP clients.

Added

  • link_pull_request_to_work_item builds the vstfs artifact URL from the pull request itself and creates the ArtifactLink relation, so linking no longer requires constructing the URL by hand
  • link_work_item accepts an explicit artifactLinkName and infers it from known vstfs URLs when omitted
  • Azure DevOps error responses now reach the caller with their real status and message — AzureDevOpsClientException derives from McpException instead of being wrapped in a generic ArgumentException

Fixed

  • Every optional tool parameter was marked required in the generated JSON schema. Nullable parameters had no default value in the C# signature, so the schema generator listed them as required regardless of their type — a strict MCP client could demand a value for a parameter that was meant to be optional. Nullable parameters (and injected cancellation tokens) now default to null, and a test asserts this holds across every toolset.
  • Dropped a stale note claiming the repository is private

60 tools, 185 tests.

Full changelog: v0.1.0-preview.8...v0.1.0-preview.9

v0.1.0-preview.8 — toolsets, read-only mode, better ergonomics

Choose a tag to compare

@eXoz00rd eXoz00rd released this 11 Aug 00:31

Fifty-nine tools had become a cost rather than a feature: the tool list weighs about 34 KB in every request, and clients cap how many tools they accept. This release makes the surface configurable and the server easier for a model to use correctly.

Added

  • ADOS_TOOLSETS exposes only the areas a team uses (projects, workitems, queries, repositories, pullrequests, builds, releases, wiki). workitems,pullrequests drops the list from 59 tools to 27. An unknown name fails at startup with the list of valid ones.
  • ADOS_READ_ONLY=true removes every write tool, leaving 40 read-only tools — for agents that may look at Azure DevOps but not change it, without relying on PAT scopes alone.
  • MCP instructions sent on connect: the configured collection, the default project, whether the server is read-only, and how to use the tools well (field lists for work items, timeline before logs, raise a limit instead of assuming something is missing, and do not perform write actions unasked).
  • Output schemas on all tools, so clients receive structured results instead of opaque JSON.

Fixed

  • query_work_items did not work in v0.1.0-preview.7. Its attributes decorated a private helper method, so the registered tool returned the default project name instead of running the WIQL query, and the real method was never registered. The tool count stayed the same, which is why smoke tests missed it.
  • Errors now carry the Azure DevOps message (for example TF401019: The Git repository ... does not exist.) instead of the full error envelope with typeKey, errorCode, and eventId.

169 tests.

Full changelog: v0.1.0-preview.7...v0.1.0-preview.8

v0.1.0-preview.7 — wiki writes, work item depth, release gates

Choose a tag to compare

@eXoz00rd eXoz00rd released this 11 Aug 00:30

Closes the remaining write gaps outside Git. Git writes are deliberately left out: local git tooling does that better, and the agent already has it.

Added

  • Wiki: create_or_update_wiki_page handles both creating and replacing a page, sending If-Match with the page ETag only when the page already exists
  • Work items: list_work_item_comments (reads the discussion, not just appends to it), get_work_item_revisions, link_work_item (parent, child, related, predecessor, successor, or a raw relation such as ArtifactLink for commits and pull requests), add_work_item_attachment (uploads text content and links it in one call)
  • Pull requests: update_pull_request (title, description, auto-complete), add_pull_request_reviewer and remove_pull_request_reviewer, accepting an identity id, an account name, or me
  • Releases: list_release_approvals, update_release_approval, and deploy_release_environment — deployment automation now gets past approval gates
  • Projects: get_project with process template and version control type

Configuration

ADOS_API_VERSION_WIT_COMMENTS overrides the API version for the work item comments endpoint, which is still preview on on-premises servers.

59 tools, 150 tests.

Known issue

query_work_items is broken in this version: its attributes decorated a private helper, so the tool returned the project name instead of running the WIQL query. Fixed in v0.1.0-preview.8 — upgrade if you use that tool.

Full changelog: v0.1.0-preview.6...v0.1.0-preview.7

v0.1.0-preview.6 — pull request insight

Choose a tag to compare

@eXoz00rd eXoz00rd released this 11 Aug 00:30

Makes pull requests fully answerable: the server could already cast a vote, but could not tell you who approved anything.

Added

  • list_my_pull_requests — pull requests across every repository of a project, with createdByMe and assignedToMe filters resolved from the signed-in identity
  • get_pull_request_policies — policy evaluations (required builds, minimum reviewers, linked work items) with status and blocking flag; explains why a pull request cannot be completed
  • list_pull_request_work_items — work items linked to a pull request
  • reply_to_pull_request_thread — replies inside an existing thread instead of starting a new one
  • set_pull_request_thread_status — resolves threads as fixed, wontFix, closed, byDesign, or pending

Changed

  • Pull requests now return reviewer votes, mergeStatus, isDraft, creation and closed dates, and the repository reference. These come from the same response the server already fetched, so nothing extra is requested.

47 tools, 119 tests.

Full changelog: v0.1.0-preview.5...v0.1.0-preview.6