release-mcp
Provides tools for managing multi-repo releases on GitLab, including starting releases, reconciling pipeline-driven builds, approving gates, bumping versions, and explaining failures, all via a declarative manifest and run state stored in a GitLab project.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@release-mcpstart release 1.2.0 on sit with jar-bundle-2 2.3.0"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
release-agent
Deterministic, non-blocking release preparation across a fleet of GitLab repositories —
a reconciler engine over a declarative manifest, exposed as a CLI (release) and an
MCP server (release-mcp) so you can drive releases from GitHub Copilot Chat, Claude,
or any other MCP client in plain language.
Built for the reality of multi-repo products: libraries that must publish before services
can pin them, release branches with iterated tags (v1.0.0-1, -2, ...), a QA gate, a
deploy repo that pins the final versions — and CI pipelines that take 40–50 minutes.
The engine never waits: every command returns in seconds, pipelines run on their own time,
and an idempotent reconcile advances whatever is ready whenever you come back.
How it works
Manifest (
release-manifest.yaml) — declares your repos, their dependency DAG, which files to edit (maven properties, python dependencies, yaml keys), and what variables each pipeline needs. See examples/release-manifest.yaml. The engine hard-codes zero product knowledge — adoption is pure configuration.Run state — one JSON per release, stored in a small dedicated GitLab project. Shared visibility, full history, optimistic locking; any teammate can resume any release.
Reconciler — walks the DAG; per node: create branch → commit version pins → cut tag → trigger pipeline (via the API, so per-release variables travel with the build) → poll → record produced versions → unblock dependents. Nothing is ever created twice.
Gates — a manual checkpoint (e.g.
qa-signoff) the engine will not pass without an explicitrelease approve.Captures & report — manifest-declared regexes grep job logs for values of interest (Sonar URLs, image digests);
release reportassembles the whole release — tags, pipelines, versions, captured values — into markdown, optionally published to the state repo (reports/<coordinate>.md).No LLM in the engine — ever.
release explaindeterministically fetches a failed job's log tail; the model on the client side (Copilot, Claude, ...) interprets it in the same chat.ports.LogExplainerstays as an extension point if you want a hosted model, but nothing requires one.
Related MCP server: GitLab MCP Server
Install
Requires Python 3.13+ and uv.
git clone <this repo> && cd release_agent
uv sync
uv run release --helpConfigure
Everything is environment variables (per-developer PAT model):
Variable | Required | Meaning |
| yes | GitLab base URL, e.g. |
| yes | PAT with |
| no | Second identity used to approve MRs on repos with |
| yes* | Project holding run states + manifest, e.g. |
| no | Branch in the state project (default |
| no | Manifest path in the state project (default |
| no | Local manifest file (overrides the state project copy) |
| yes* | Local state directory instead of a state project (single-user/dev) |
* one of STATE_PROJECT / STATE_DIR is required.
Use — CLI
release start 1.0.0 --env sit \
-i jar_bundle_1_version=1.0.1 -i pydantic_version=10.0.0 -i jar_bundle_2_version=2.3.0
release status 1.0.0 # render the DAG, tags, pipeline URLs
release reconcile 1.0.0 # idempotent tick — run it whenever, it never double-fires
release bump 1.0.0 service-a # next vX.Y.Z-(N+1) after a QA fix
release approve 1.0.0 qa-signoff # clear the manual gate
release explain 1.0.0 service-a # advisory: why did the pipeline fail?Use — MCP (Copilot Chat, Claude, ...)
Register the stdio server with your client, e.g. VS Code .vscode/mcp.json:
{
"servers": {
"release-agent": {
"type": "stdio",
"command": "uv",
"args": ["run", "--directory", "/path/to/release_agent", "release-mcp"],
"env": {
"RELEASE_AGENT_GITLAB_URL": "https://gitlab.example.com",
"RELEASE_AGENT_GITLAB_TOKEN": "${input:gitlab-token}",
"RELEASE_AGENT_STATE_PROJECT": "group/release-state"
}
}
}
}Then just talk: "start release 1.0.0 on sit with jar-bundle-2 2.3.0, jar-bundle-1 jar 1.0.1,
pydantic 10.0.0" → the model calls release_start; later, "advance the release" →
release_reconcile. Tools exposed: release_start, release_status, release_reconcile,
release_approve, release_bump, release_explain, get_manifest.
Prompt cookbook
You say | Tool the model calls |
"Start release 1.2.0 on sit — jar-bundle-1 jar 1.0.2, pydantic 10.1.0, jar-bundle-2 2.4.0" |
|
"What exactly would starting 1.2.0 do?" |
|
"Where's release 1.2.0?" / "Did the jar-bundle-2 build finish?" |
|
"Advance the release" / "Pipelines look done, continue" |
|
"Why is service-a stuck?" |
|
"QA signed off, approve the release" |
|
"Why did service-b fail?" |
|
"Fix is merged on service-b's release branch, rebuild it" |
|
"Which files get edited during a release? What depends on what?" |
|
"What was the last released version of service-a?" |
|
"What releases are in flight?" / "What did we ship last?" |
|
"Here's my updated manifest — is it valid?" |
|
"Take 1.2.0 as far as it can go and tell me what's blocking" | chains reconcile → status → summary |
"Give me the release report" / "…and publish it" |
|
Habits that keep it reliable: always name the coordinate ("release 1.2.0") so the model never guesses which release you mean, and ask to "advance" freely — reconcile never double-fires, so an over-eager prompt costs nothing.
Adapt to your product
Copy examples/release-manifest.yaml and describe your repos, tiers, edits, and pipeline variables.
Create a
release-stateproject in GitLab, commit the manifest there.Gate your CI release/publish jobs to run only from API-triggered tag pipelines (
$CI_COMMIT_TAG && $CI_PIPELINE_SOURCE == "api"— purely additive, design §9). On GitLab 17.7+ also set each project's "Minimum role to use pipeline variables" todeveloper, or API-triggered pipelines with variables are rejected with HTTP 400.Need a new file mutation? Add one function to
EDIT_KINDSin src/release_agent/core/edits.py.Have an LLM endpoint? Implement
ports.LogExplainerand wire it in src/release_agent/bootstrap.py.
Development
uv run pytest # unit + engine tests against an in-memory fake GitLab
uv run ruff check .License
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/stevedevex/orchestrator'
If you have feedback or need assistance with the MCP directory API, please join our Discord server