Verify Release
Verify that a published release of modelcontextprotocol/csharp-sdk fully shipped. Publishing a
GitHub release triggers two workflows in parallel, and the release is not done until both have
succeeded and both of their outputs are confirmed live.
| Workflow | File | Trigger | Produces |
|---|---|---|---|
| Release | .github/workflows/release.yml |
release: published |
NuGet packages published to NuGet.org |
| Publish Docs | .github/workflows/docs.yml |
release: published |
The versioned docs site at https://csharp.sdk.modelcontextprotocol.io |
Use the shared release branch reference for branch roles and release tag conventions.
Safety: This skill is read-only by default. It inspects workflow runs, releases, and published artifacts. The only actions it may take are re-running a failed workflow or dispatching a docs refresh, and both require explicit user confirmation.
Process
Work through each step sequentially. Present findings at each step and get user confirmation before taking any action.
Step 1: Identify the Release
The user may provide:
- A version or tag (e.g.,
2.0.0-preview.1,v1.3.1) — use directly - No context — list recent releases with
gh release list --limit 10and ask the user to select
Confirm the release is published, not a draft:
gh release view {tag} --json tagName,isDraft,isPrerelease,publishedAt,targetCommitish,url
If the release is still a draft, stop. Neither workflow has run — nothing is published, and no verification is possible. Tell the user the draft must be published in the GitHub UI first, and that publishing is a deliberate human action this skill will not perform.
Record the tag, the published timestamp, and the target commitish for the following steps.
Step 2: Locate Both Workflow Runs
Find the runs triggered by publishing this release. A release-event run carries the tag name in
headBranch, which is an exact identifier — use it rather than correlating on timestamps:
gh run list --workflow release.yml --event release --branch v{version} --limit 5 --json databaseId,status,conclusion,headBranch,headSha,createdAt,url
gh run list --workflow docs.yml --event release --branch v{version} --limit 5 --json databaseId,status,conclusion,headBranch,headSha,createdAt,url
Do not identify runs by "the most recent run" or "created at or after publishedAt." Those
match any release published in the same window, so a concurrent or closely-following release —
including a servicing patch published from another branch minutes later — can be reported as this
release's result, showing a green run for the wrong tag. Confirm headBranch equals v{version}
on every run before evaluating it.
Cross-check headSha against the release's target commitish recorded in Step 1. A mismatch means
the tag moved between drafting and publishing, and the run validated something other than what was
reviewed — stop and report it rather than evaluating the run.
If more than one run matches the tag, the workflow was re-run; evaluate the latest attempt and say that earlier attempts existed rather than silently reporting only the newest.
Present both runs with their status, conclusion, and URL. Watch them together — they run concurrently and either can fail independently. Do not report success for the release until both are accounted for.
If a run cannot be found for either workflow, report which one is missing and check whether the
workflow is disabled or whether its if repository guard excluded the run (both workflows only run
in the modelcontextprotocol/csharp-sdk repository, not in forks).
Step 3: Evaluate the Release Workflow
Report the run's conclusion. If it failed, identify the failing job and step and summarize the error:
gh run view {run-id} --log-failed
A failure here does not roll back the release — the GitHub release and its tag remain, and the workflow is simply re-run once the cause is addressed. Re-running is safe and is usually the right first move. Recommend it, but do not re-run without explicit user confirmation.
Never run
dotnet nuget pushand never handle NuGet API keys. Package publishing happens only through the workflow.
Step 4: Evaluate the Publish Docs Workflow
Report the run's conclusion, accounting for these docs-specific behaviors:
- Superseded runs are not failures. The workflow uses a
pagesconcurrency group withcancel-in-progress: true. Every run rediscovers the current releases and rebuilds the whole site from scratch, so a newer run fully supersedes the one it cancels. Report a cancelled run as superseded and follow the newer run instead. - Version discovery reads published releases. For each major version >= 1, the workflow takes
the most recently published non-draft release tagged
v{MAJOR}.*. A draft release contributes nothing. - Every major is rebuilt. A release-triggered run builds each major from its latest release tag
into its own path (
/v1/,/v2/). A manual dispatch defaults to the same release-tag content, or can build every major fromrelease/{MAJOR}.x, usingmainfor its matching major, by selectingdocs_source=latest-branches. A new MAJOR adds a new path; the site root redirects to the newest release, prereleases included. - Orchestration comes from
main. The scripts and picker assets are always checked out frommain. Release-triggered and default manual runs use release-tag content; a manualdocs_source=latest-branchesrun uses source-branch content. A docs fix that lives only in a release branch will not affect orchestration.
If it failed, summarize the failing step. Common causes are a docs build failure in one version's
worktree (make generate-docs) or a Pages deployment error.
Step 5: Confirm the Published Packages
Confirm the exact released version is listed for each shipping package on NuGet.org.
Listing can lag a successful workflow run by several minutes. If the workflow succeeded but the version is not yet visible, say so explicitly and offer to re-check — do not report this as a failure. Distinguish "published but not yet indexed" from "not published."
Report each package with its status, and flag any shipping package missing from the release.
Step 6: Confirm the Documentation Site
Confirm https://csharp.sdk.modelcontextprotocol.io reflects this release:
- Version path — the major-version path for this release (for example
/v2/) is live and serving the new content. - Version picker — the picker offers this release's major version.
- Root redirect — the site root redirects to the expected default version, which is the newest release by publish date, prereleases included.
- Versioning page — the slugged versioning page for this release,
https://csharp.sdk.modelcontextprotocol.io/v{MAJOR}/versioning.html, resolves. Release notes link to it from the Breaking Changes section, and for the first release of a new MAJOR that path only comes into existence with this workflow run. Confirm the release notes use the slugged form and not the unslugged/versioning.html, which tracks the site default and can silently repoint when a later MAJOR ships.
GitHub Pages caches aggressively, so a short delay after a successful deploy is normal. Distinguish "deployed but not yet propagated" from "deployed wrong."
Step 7: Report
Summarize the verification as a table covering both workflows and both published outputs, and state plainly whether the release is fully verified or what remains outstanding.
| Check | Status |
|---|---|
| Release workflow | ✅ succeeded — {run URL} |
| Publish Docs workflow | ✅ succeeded — {run URL} |
| Packages on NuGet.org | ✅ {version} listed for all N packages |
| Docs site | ✅ /v2/ live, picker updated, root redirects |
Remediation
Both remediations require explicit user confirmation.
Re-run a failed workflow:
gh run rerun {run-id} --failed
Rebuild the released docs — use the default release-tags source to retry a failed Pages
deployment after a release, without minting a product release:
gh workflow run docs.yml --field docs_source=release-tags
Refresh docs without a new release — select latest-branches to rebuild every published major
from its current source branch (release/{MAJOR}.x, using main for its matching major):
gh workflow run docs.yml --field docs_source=latest-branches
The workflow fails instead of silently using a release tag when any major has no matching branch.
Edge Cases
- Release is still a draft — stop; neither workflow has run. The user must publish in the GitHub UI.
- Docs run cancelled — expected under the
pagesconcurrency group; report as superseded and follow the newer run. - Only one workflow ran — check whether the other is disabled, or whether the repository guard excluded it (forks do not run either workflow).
- Workflow succeeded but NuGet version not listed — indexing lag; re-check before reporting a failure.
- Workflow succeeded but docs not visible — Pages caching; re-check before reporting a failure.
- Docs site missing the new major version — confirm the release is published and non-draft, then confirm the tag matches
v{MAJOR}.*. - Root redirects to an unexpected version — the default is the newest release by publish date, including prereleases. A prerelease published after a stable release becomes the default; this is by design.
- Release workflow failed after partial publish — some packages may already be on NuGet.org. NuGet versions cannot be unpublished; re-running skips already-published versions. Report exactly which packages are listed before recommending a re-run.
- Versioning link is unslugged or points at the wrong MAJOR — release notes must link to
/v{MAJOR}/versioning.htmlfor the released version. Report it so the user can correct the body; the unslugged form tracks the site default and will repoint when a later MAJOR ships. - Verifying an older release — the docs workflow only ever reflects each major's latest release, so an older release's docs path will have been overwritten by a newer one. Verify packages only and note this.