Skip to content

fix(cli): stamp printed MCP versions in bundles#2817

Merged
mergify[bot] merged 4 commits into
mainfrom
fix/issue-2387-mcp-versions
Jun 7, 2026
Merged

fix(cli): stamp printed MCP versions in bundles#2817
mergify[bot] merged 4 commits into
mainfrom
fix/issue-2387-mcp-versions

Conversation

@tmchow

@tmchow tmchow commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Intent

Issue: Closes #2387

Printed CLI MCPB bundles no longer present the Printing Press generator release as the bundle's own version, and generated MCP servers no longer default to a release-looking 1.0.0 serverInfo version before release stamping.

Approach

Generate-time manifest.json now uses a neutral 0.0.0 placeholder because the printed CLI release tag is not known during generation. The bundle path accepts --version and stamps that printed CLI release version into the manifest bytes inside the .mcpb archive without mutating the on-disk manifest.

Generated HTTP and device MCP server mains now default their ldflag-overridable version variable to 0.0.0-dev; the existing goreleaser -X main.version={{ .Version }} injection remains the release-time source of truth.

Scope

Primary area: MCPB packaging and generated MCP server version metadata.

Why this belongs in this repo: the bug appears in every future printed CLI generated or bundled by the Printing Press, so the fix belongs in the generator and bundle command rather than in one published CLI.

Catalog Justification

Embedded catalog fit: N/A

Distinct blueprint pattern: N/A

Closest existing entries checked: N/A

Source provenance: N/A

Auth and tenant assumptions: N/A

Safe default surface: N/A

Generation path: N/A

Stale-body check: N/A

Risk

The main risk is release workflow adoption: published CLI workflows must pass cli-printing-press bundle --version <release> to stamp non-placeholder MCPB versions. Generated MCP server releases still receive the tag via existing goreleaser ldflags, and generate-time artifacts intentionally remain placeholders.

Output Contract

Generated MCP server main.go files now emit var version = "0.0.0-dev" and still pass that variable to server.NewMCPServer. Golden fixtures cover HTTP, stdio, and device generated MCP mains. scripts/verify-generator-output.sh compiled representative generated modules for HTTP, device, and MCP-first cases.

Verification

  • Generator/template change: verified generated output, including emitted-code assertions or compiled generated CLI output
  • Generator/template change: covered the affected fallback or variant shape, not only happy-path fixtures
  • Generator/template change: checked emitted definitions and call sites for matching gates
  • go test ./internal/pipeline ./internal/cli ./internal/generator -run 'Test(BuildMCPBBundle|WriteMCPBManifest|NewBundleCmd|GenerateMCPMainRemoteOptIn|GeneratedBLEDeviceEmitsMCPSurface)'
  • scripts/golden.sh verify
  • scripts/verify-generator-output.sh generate-golden-api generate-device-ble generate-mcp-api
  • go test ./...
  • go build -o ./cli-printing-press ./cmd/cli-printing-press
  • golangci-lint run ./...
  • Headless read-only review: no findings

AI / Automation Disclosure

  • No AI or automation was used
  • Human-reviewed: AI or automation was used, and a human reviewed the work for intent, fit, and obvious issues before submission
  • AI-reviewed only: an AI agent reviewed the work, but no human reviewed it before submission
  • Fully automated: generated and submitted without human review for this specific change

@mergify

mergify Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🟢 require-ready-label-and-ci

Wonderful, this rule succeeded.
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0
  • check-success = build-and-test
  • check-success = generated-test
  • check-success = go-lint
  • check-success = golden
  • check-success = pr-title
  • check-success = test
  • any of:
    • label = ready-to-merge
    • all of:
      • head = release-please--branches--main
      • title ~= ^chore\(main\): release
  • any of:
    • -files ~= ^(\.github/workflows/|\.github/scripts/|scripts/|\.github/CODEOWNERS$)
    • author = tmchow
    • approved-reviews-by = mvanhorn
    • approved-reviews-by = tmchow
    • author = mvanhorn
  • any of:
    • check-success = Greptile Review
    • label = queued
    • check-neutral = Greptile Review
    • check-skipped = Greptile Review
    • head ~= ^mergify/merge-queue/
    • all of:
      • head = release-please--branches--main
      • title ~= ^chore\(main\): release

@greptile-apps

greptile-apps Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes MCPB bundle versioning by decoupling the generate-time manifest from the release tag: manifest.json now emits a 0.0.0 placeholder, and the new --version flag on cli-printing-press bundle stamps the real release version into the ZIP's manifest bytes without touching the on-disk file. Generated MCP server mains also drop the misleading 1.0.0 default in favour of 0.0.0-dev, keeping goreleaser ldflags as the authoritative injection point.

  • Version stamping: BuildMCPBBundle accepts a Version field in BundleParams and uses rewriteMCPBManifestVersion (a map[string]any round-trip) to patch the version inside the ZIP only, preserving all custom manifest fields and leaving the on-disk manifest.json byte-for-byte unchanged.
  • Semver validation: validateBundleVersion enforces v-prefix rejection and semver shape at the CLI layer using both a custom regex and golang.org/x/mod/semver.IsValid; invalid inputs exit with ExitInputError and a clear message.
  • Golden fixtures & tests: All four golden main.go files updated; new tests cover version stamping, on-disk immutability, and rejection of malformed version strings.

Confidence Score: 5/5

Safe to merge; the change is well-scoped and the on-disk manifest is never mutated by the version-stamp path.

The core logic — stamping the version into ZIP bytes while leaving the on-disk manifest unchanged — is straightforward and thoroughly tested. Both the --version validation and the manifest rewrite have dedicated subtests covering happy paths, immutability of on-disk files, and rejection of invalid inputs. Golden fixture updates and compiled-output verification are included. The one style note (dead manifest.Version assignment) has no runtime impact.

No files require special attention.

Important Files Changed

Filename Overview
internal/pipeline/mcpb_bundle.go Adds Version to BundleParams and rewriteMCPBManifestVersion to stamp version into ZIP bytes without mutating the on-disk manifest; dead manifest.Version struct assignment noted.
internal/pipeline/mcpb_manifest.go Removes PrintingPressVersion/version.Version fallbacks from bundleVersion; now always returns "0.0.0" placeholder; bundleVersion() parameter removed cleanly.
internal/cli/bundle.go Adds --version flag with validateBundleVersion enforcing v-prefix rejection and semver shape; passes Version through to BundleParams; well-tested.
internal/generator/templates/main_mcp.go.tmpl Changes generated MCP server default version from "1.0.0" to "0.0.0-dev" so goreleaser ldflags injection is the sole release-time source of truth.
internal/cli/bundle_test.go Adds tests verifying version stamp propagates into ZIP but not on-disk manifest, and that invalid version strings are rejected with clear error messages.
internal/pipeline/mcpb_bundle_test.go New subtest confirms version stamping preserves custom top-level and nested JSON fields while leaving the on-disk manifest byte-for-byte unchanged.

Sequence Diagram

sequenceDiagram
    participant CI as Release CI
    participant CLI as cli-printing-press bundle
    participant BV as validateBundleVersion
    participant BB as BuildMCPBBundle
    participant Disk as manifest.json (disk)
    participant ZIP as .mcpb ZIP

    CI->>CLI: "bundle <dir> --version 1.2.3"
    CLI->>BV: validateBundleVersion("1.2.3")
    BV-->>CLI: ok
    CLI->>Disk: ReadFile manifest.json (version: "0.0.0")
    CLI->>BB: "BundleParams{Version: "1.2.3"}"
    BB->>BB: rewriteMCPBManifestVersion(bytes, "1.2.3")
    BB->>ZIP: write manifest with version "1.2.3"
    BB->>ZIP: write MCP binary
    Disk-->>Disk: unchanged ("0.0.0")
    BB-->>CLI: nil
    CLI-->>CI: wrote demo.mcpb
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor Fix All in Conductor

Reviews (3): Last reviewed commit: "fix(cli): use cutprefix for bundle versi..." | Re-trigger Greptile

Comment thread internal/pipeline/mcpb_manifest.go
Comment thread internal/cli/bundle.go
@tmchow tmchow added the ready-to-merge Allow Mergify to queue and merge this PR when protections pass label Jun 7, 2026
@tmchow

tmchow commented Jun 7, 2026

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify mergify Bot added the queued PR is in the Mergify merge queue label Jun 7, 2026
mergify Bot added a commit that referenced this pull request Jun 7, 2026
mergify Bot added a commit that referenced this pull request Jun 7, 2026
mergify Bot added a commit that referenced this pull request Jun 7, 2026
mergify Bot added a commit that referenced this pull request Jun 7, 2026
@mergify mergify Bot merged commit e4bc665 into main Jun 7, 2026
30 checks passed
@mergify mergify Bot deleted the fix/issue-2387-mcp-versions branch June 7, 2026 23:17
@mergify

mergify Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 26 minutes 51 seconds in the queue, including 19 minutes 29 seconds running CI.

Required conditions to merge

@mergify mergify Bot removed the queued PR is in the Mergify merge queue label Jun 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Allow Mergify to queue and merge this PR when protections pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cli: printed CLI's MCPB manifest reports Press version (4.11.0) instead of release tag; MCP serverInfo hardcodes 1.0.0

1 participant