# Release Process - FreeCAD Robust MCP Suite
FreeCAD Robust MCP Suite - MCP Server, Bridge Workbench, and Macros for AI assistant integration

Skip to content

# Release Process

This project uses component-specific versioning. Each component (MCP Server, Workbench) has its own version and release cycle, allowing independent updates without affecting other components.

## Quick Start

The complete release workflow in order:

    # 1. Pre-release checks
    just release::status                        # Check which components have unreleased changes
    just release::changes-since mcp-server      # View specific changes (or workbench)
    just all                                    # Run all quality checks (must pass)

    # 2. Update release notes
    just release::draft-notes mcp-server        # Generate draft notes from commits
    # Then edit the component's RELEASE_NOTES.md file (see "Release Notes Files" below)

    # 3. Version bump (workbench only - MCP Server uses setuptools-scm)
    just release::bump-workbench 1.0.0

    # 4. Commit changes
    git add -A
    git commit -m "chore: bump workbench to 1.0.0"  # or appropriate component/message

    # 5. Create & push tag (triggers CI/CD automatically)
    just release::tag-workbench 1.0.0           # or tag-mcp-server

    # 6. Monitor release at GitHub Actions, then verify
    just release::list-tags
    just release::latest-versions

Component | Bump Command | Tag Command
--- | --- | ---
MCP Server | (none - uses setuptools-scm) | `just release::tag-mcp-server X.Y.Z`
Workbench | `just release::bump-workbench X.Y.Z` | `just release::tag-workbench X.Y.Z`

## Components and Their Release Targets

Component | Tag Format | Releases To
--- | --- | ---
MCP Server | `robust-mcp-server-vX.Y.Z` | PyPI/TestPyPI*, Docker Hub, GitHub Release
Robust MCP Bridge Workbench | `robust-mcp-workbench-vX.Y.Z` | GitHub Release (archive)

*Stable releases (`X.Y.Z`) publish to PyPI; non-stable releases (alpha, beta, rc) publish to TestPyPI only.

## Version Format

All versions follow Semantic Versioning 2.0:

- `X.Y.Z` - Stable release (published to PyPI only)
- `X.Y.Z-alpha` or `X.Y.Z-alpha.N` - Alpha pre-release (published to TestPyPI only)
- `X.Y.Z-beta` or `X.Y.Z-beta.N` - Beta pre-release (published to TestPyPI only)
- `X.Y.Z-rc.N` - Release candidate (published to TestPyPI only)

## Release Workflow Overview

Releases follow a two-step process:

1. Bump: Update version in all source files locally, then commit
2. Tag: Create and push the git tag (triggers CI/CD)

This ensures the version in source files matches the git tag on the same commit.

    ┌─────────────────────────────────────────────────────────────────┐
    │  1. just release::bump-<component> X.Y.Z                        │
    │     └── Updates version in all relevant files                   │
    │                                                                 │
    │  2. git add -A && git commit -m "chore: bump ... to X.Y.Z"      │
    │     └── Commit the version changes                              │
    │                                                                 │
    │  3. just release::tag-<component> X.Y.Z                         │
    │     └── Verifies versions match, then creates & pushes tag      │
    │                                                                 │
    │  4. GitHub Actions workflow runs automatically                  │
    │     └── Verifies versions, builds, and publishes release        │
    └─────────────────────────────────────────────────────────────────┘

## Pre-Release Checklist

Before creating any release, complete these steps:

### 1. Check Release Status

See which components have unreleased changes:

    just release::status

This shows the number of commits since the last release for each component.

### 2. Review Changes

View the specific changes for the component you're releasing:

    # For MCP Server
    just release::changes-since mcp-server

    # For Workbench
    just release::changes-since workbench

### 3. Run All Quality Checks

Ensure all tests and checks pass:

    just all

For a more thorough check including integration tests:

    just all-with-integration

### 4. Update Release Notes

Each component has its own `RELEASE_NOTES.md` file. Release workflows automatically extract the relevant section for GitHub Releases.

#### Release Notes Files

Component | Release Notes File
--- | ---
MCP Server | `src/freecad_mcp/RELEASE_NOTES.md`
Robust MCP Bridge Workbench | `addon/FreecadRobustMCPBridge/RELEASE_NOTES.md`

#### Draft Release Notes

Use the `draft-notes` command to generate a starting point from conventional commits:

    # Generate draft notes for a component
    just release::draft-notes mcp-server
    just release::draft-notes workbench

This categorizes commits by type (feat, fix, refactor, etc.) to help you write the release notes.

#### Release Notes Format

Add a new version section at the top of the component's `RELEASE_NOTES.md`:

    ## Version X.Y.Z (YYYY-MM-DD)

    Release notes for changes between vA.B.C and vX.Y.Z.

    ### Added

    - New feature description

    ### Changed

    - Changed behavior description

    ### Fixed

    - Bug fix description

Important: The version header format must match exactly for the GitHub Release workflow to extract it:

- Format: `## Version X.Y.Z (YYYY-MM-DD)`
- Example: `## Version 1.0.0 (2026-01-15)`

The release workflows automatically extract the version section and include it in the GitHub Release body.

## Releasing Each Component

### MCP Server Release

The MCP Server is the main Python package. It uses `setuptools-scm` to derive version from git tags at build time, so there's no version bump step needed.

    # 1. Ensure all changes are committed
    git status  # Should show clean working tree

    # 2. Update src/freecad_mcp/RELEASE_NOTES.md and commit
    git add src/freecad_mcp/RELEASE_NOTES.md
    git commit -m "docs: update release notes for MCP Server v1.0.0"

    # 3. Create and push the release tag
    just release::tag-mcp-server 1.0.0

What happens automatically:

1. GitHub Actions validates the tag format
2. Builds Python wheel and source distribution (version from tag)
3. Tests installation on Ubuntu and macOS
4. Publishes to PyPI (or TestPyPI for alpha, beta, and rc versions)
5. Builds multi-architecture Docker image (amd64 + arm64)
6. Pushes to Docker Hub as `spkane/freecad-robust-mcp:1.0.0`
7. Creates GitHub Release with wheel and tar.gz artifacts

Pre-release versions:

    # Alpha (goes to TestPyPI only)
    just release::tag-mcp-server 1.0.0-alpha.1

    # Beta (goes to TestPyPI only)
    just release::tag-mcp-server 1.0.0-beta.1

    # Release candidate (goes to TestPyPI only)
    just release::tag-mcp-server 1.0.0-rc.1

### Robust MCP Bridge Workbench Release

The workbench is a FreeCAD addon that provides the Robust MCP Bridge GUI.

    # 1. Bump version in source files
    just release::bump-workbench 1.0.0

    # 2. Review and commit the changes
    git diff  # Review changes
    git add -A
    git commit -m "chore: bump workbench to 1.0.0"

    # 3. Create and push the release tag
    just release::tag-workbench 1.0.0

Files updated by `bump-workbench`:

- `addon/FreecadRobustMCPBridge/freecad_mcp_bridge/__init__.py` (`__version__`)
- `package.xml` (workbench section: `<version>` and `<date>`)

What happens automatically:

1. GitHub Actions validates the tag format
2. Verifies version in source files matches tag
3. Creates archive (tar.gz and zip)
4. Creates GitHub Release with the archives

## Verifying a Release

### Check GitHub Actions

After pushing a tag, monitor the release workflow:

1. Go to GitHub Actions
2. Find the workflow run triggered by your tag
3. Verify all steps complete successfully

### Verify Published Artifacts

For MCP Server:

    # Check PyPI
    pip index versions freecad-robust-mcp

    # Check Docker Hub
    docker pull spkane/freecad-robust-mcp:1.0.0

For Workbench:

- Check the GitHub Releases page for the archive downloads
- Verify the `package.xml` version was updated

## Managing Release Tags

### List All Tags

    # All tags grouped by component
    just release::list-tags

    # Latest version of each component
    just release::latest-versions

### Delete a Tag (If Needed)

If a release has issues and needs to be removed:

    just release::delete-tag robust-mcp-server-v1.0.0

Deleting Published Releases

Deleting a tag does not unpublish from PyPI or Docker Hub. Contact the respective registries to remove published artifacts if necessary.

### Preview a Release (Dry Run)

To see what a release tag would look like without creating it:

    just release::dry-run-tag mcp-server 1.0.0
    just release::dry-run-tag workbench 1.0.0

## Troubleshooting

### Release Workflow Failed

1. Check the GitHub Actions logs for the specific error
2. Common issues:
3. Invalid version format (must be semver)
4. Version mismatch between source files and tag
5. Missing secrets (PyPI token, Docker credentials)
6. Tests failing during the release build

### Version Mismatch Error

If the workflow fails with "Version mismatch":

    # You forgot to bump the version before tagging
    # Delete the tag
    just release::delete-tag <full-tag-name>

    # Bump the version
    just release::bump-<component> X.Y.Z

    # Commit the changes
    git add -A && git commit -m "chore: bump <component> to X.Y.Z"

    # Create the tag again
    just release::tag-<component> X.Y.Z

### Tag Already Exists

If you try to create a tag that already exists:

    # Delete the existing tag first
    just release::delete-tag robust-mcp-server-v1.0.0

    # Then create the new tag
    just release::tag-mcp-server 1.0.0

### Wrong Version Released

1. Delete the tag: `just release::delete-tag <tag>`
2. Create a new release with the correct version
3. For PyPI: you cannot re-upload the same version; increment the patch version instead

## Release Cadence Recommendations

- MCP Server: Release when there are significant new features or important bug fixes
- Workbench: Release in sync with server changes that affect the bridge protocol

## Quick Reference

    # Check what needs releasing
    just release::status

    # View changes for a component
    just release::changes-since mcp-server

    # Draft release notes from commits
    just release::draft-notes mcp-server
    just release::draft-notes workbench

    # Bump versions (for workbench only)
    just release::bump-workbench 1.0.0

    # Commit version changes
    git add -A && git commit -m "chore: bump <component> to X.Y.Z"

    # Create releases (verifies versions, creates and pushes tag)
    just release::tag-mcp-server 1.0.0
    just release::tag-workbench 1.0.0

    # List existing releases
    just release::list-tags
    just release::latest-versions

    # Extract changelog for a version (used by CI)
    just release::extract-changelog mcp-server 1.0.0

    # Delete a tag if needed
    just release::delete-tag <full-tag-name>

2026-01-18
2026-01-07