Skip to content

feat: Claude Desktop extension (.mcpb) build and release pipeline - #224

Merged
jmrplens merged 2 commits into
mainfrom
feat/mcpb-desktop-extension
Jul 7, 2026
Merged

feat: Claude Desktop extension (.mcpb) build and release pipeline#224
jmrplens merged 2 commits into
mainfrom
feat/mcpb-desktop-extension

Conversation

@jmrplens

@jmrplens jmrplens commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Packages the server as a one-click MCPB desktop extension for Claude Desktop (macOS + Windows), as groundwork for submitting to the Anthropic connectors directory.

What's included

  • mcpb/manifest.json — MCPB v0.3 manifest: binary server type, darwin universal entry point with a win32 platform override, user_config (URL, keychain-backed token, tool surface, tier, read-only, safe mode, TLS skip), dynamic surface default, AUTO_UPDATE=false inside the extension. Validates clean with mcpb CLI 2.1.2.
  • mcpb/icon.png — 512×512 render of site/src/assets/logo-light.svg (recommended size for Claude Desktop).
  • GoReleaser — new universal_binaries block producing a darwin fat binary (arm64+amd64); replace: false keeps the per-arch assets that go-selfupdate matches by exact name.
  • scripts/build-mcpb.sh — assembles the bundle from GoReleaser artifacts and packs it with the pinned @anthropic-ai/mcpb CLI.
  • Release workflow — builds and uploads gitlab-mcp-server.mcpb as a release asset; update-server-json-sha.sh now stamps the MCPB manifest version alongside server.json / plugin.json (same commit-back flow).
  • Makefilemake mcpb (local cross-compile + lipo + pack) and make check-mcpb (manifest validation).
  • PRIVACY.md — privacy policy required by the directory submission, linked from the README and the manifest's privacy_policies.
  • README — Claude Desktop row in the one-click install table + Privacy Policy section; new guide docs/guides/claude-desktop-extension.md.

Verification

  • npx @anthropic-ai/mcpb@2.1.2 validate mcpb/manifest.json → schema + icon pass
  • goreleaser check → config valid
  • make mcpb → 39 MB bundle; lipo -info confirms x86_64+arm64; the bundled darwin binary boots over stdio with the manifest's exact env pattern and serves gitlab_find_action / gitlab_execute_action
  • markdownlint-cli2 + format_md_tables --check green

The .mcpb asset will first appear on the next release; the README download button points at releases/latest/download/gitlab-mcp-server.mcpb.

https://claude.ai/code/session_01LJ6D4L6rnms9GqMqqc2tFb

Summary by Sourcery

Add a Claude Desktop (.mcpb) extension distribution for the GitLab MCP server, including local build tooling, release packaging, and documentation and privacy policy updates required for directory submission.

New Features:

  • Provide a packaged Claude Desktop extension (.mcpb) for the GitLab MCP server targeting macOS (universal) and Windows.
  • Introduce a Claude Desktop extension guide covering installation, configuration, and local bundle builds.

Enhancements:

  • Extend the Makefile with targets to build and validate the Claude Desktop extension bundle using a pinned MCPB CLI.
  • Configure GoReleaser to produce a macOS universal binary suitable for use as the extension entry point.
  • Update the release workflow to build, upload, and version-stamp the .mcpb bundle and manifest alongside existing MCP manifests.
  • Add a user-facing privacy policy document and link it from the README and MCPB manifest.
  • Update the README with a Claude Desktop one-click install row and a privacy policy section.

Build:

  • Add GoReleaser universal_binaries configuration for the GitLab MCP server to support a darwin fat binary used in the extension bundle.

CI:

  • Extend the release GitHub Actions workflow to build and publish the Claude Desktop .mcpb bundle and commit MCPB manifest version bumps automatically.

Documentation:

  • Add PRIVACY.md describing data handling, credentials, storage, and update behavior for the server.
  • Document the Claude Desktop extension (.mcpb) in a new how-to guide, referenced from the guides index and README.

Chores:

  • Teach the manifest update script to bump the MCPB manifest version in sync with releases.

Summary by CodeRabbit

  • New Features

    • Added support for a Claude Desktop extension package, including a new downloadable .mcpb release artifact.
    • Added setup guidance and release information for the new desktop extension.
    • Added a privacy policy document with clear data-handling and update details.
  • Bug Fixes

    • Improved release automation so version and metadata updates stay in sync across bundled extension files.

Package the server as a one-click MCPB desktop extension for Claude
Desktop (macOS + Windows):

- mcpb/manifest.json: MCPB v0.3 manifest (binary server type, win32
  platform override, user_config with keychain-backed token, dynamic
  surface default, AUTO_UPDATE=false) + 512x512 icon from the SVG logo
- .goreleaser.yml: darwin universal (fat) binary via universal_binaries
  (replace: false keeps per-arch assets that go-selfupdate matches)
- scripts/build-mcpb.sh: assembles the bundle from GoReleaser artifacts
  and packs it with the pinned @anthropic-ai/mcpb CLI
- release workflow: builds and uploads gitlab-mcp-server.mcpb as a
  release asset; update-server-json-sha.sh stamps the manifest version
  alongside server.json and plugin.json
- Makefile: mcpb (local cross-compile + lipo + pack) and check-mcpb
  (manifest validation) targets
- PRIVACY.md: privacy policy required for the Anthropic connectors
  directory submission, linked from README and the manifest
- README: Claude Desktop row in the one-click install table + privacy
  section; docs/guides/claude-desktop-extension.md how-to

Verified: manifest validates with mcpb CLI 2.1.2, goreleaser check
passes, make mcpb produces a 39 MB bundle whose darwin binary boots
over stdio with the manifest env pattern and serves the dynamic
surface (gitlab_find_action / gitlab_execute_action).

Claude-Session: https://claude.ai/code/session_01LJ6D4L6rnms9GqMqqc2tFb
Copilot AI review requested due to automatic review settings July 7, 2026 21:55
@sourcery-ai

sourcery-ai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a complete build and release pipeline to package the GitLab MCP server as a Claude Desktop (.mcpb) extension, including a versioned MCPB manifest, local/CI build scripts, GoReleaser universal binary config, README/docs updates, and a privacy policy for directory submission.

File-Level Changes

Change Details Files
Introduce Makefile targets and helper script to build and validate a Claude Desktop .mcpb extension bundle locally.
  • Add MCPB_CLI_VERSION pin and check-mcpb target that runs the official mcpb CLI to validate the manifest.
  • Add mcpb target that cross-compiles darwin arm64/amd64 binaries, merges them with lipo, builds a Windows amd64 binary, and calls scripts/build-mcpb.sh to produce dist/gitlab-mcp-server.mcpb.
  • Wire check-mcpb and mcpb into the main Makefile convenience target list.
Makefile
scripts/build-mcpb.sh
Configure GoReleaser to emit a macOS universal binary used as the Claude Desktop extension entrypoint.
  • Add a universal_binaries section that builds a fat darwin binary (arm64+amd64) named gitlab-mcp-server from the existing gitlab-mcp-server build.
  • Keep per-arch darwin artifacts by setting replace: false so go-selfupdate continues to work.
.goreleaser.yml
Extend the release workflow to build, upload, and version-stamp the .mcpb extension alongside existing manifests.
  • Add a job step that runs scripts/build-mcpb.sh with the tag-derived VERSION, prints a SHA256, and uploads gitlab-mcp-server.mcpb as a release asset via gh.
  • Update the manifest-commit step to include mcpb/manifest.json when present and adjust the commit message to mention the Claude Desktop extension.
  • Extend scripts/update-server-json-sha.sh to set the version field in mcpb/manifest.json from the release VERSION if the file exists.
.github/workflows/release.yml
scripts/update-server-json-sha.sh
Add the MCPB manifest and icon defining the Claude Desktop extension configuration, server wiring, and user-configurable settings.
  • Create mcpb/manifest.json using MCPB v0.3 schema with binary server type, darwin entrypoint and win32 override, environment mapping from user_config, and AUTO_UPDATE disabled.
  • Declare tool metadata for gitlab_find_action and gitlab_execute_action, compatibility for Claude Desktop >=0.10.0 on darwin/win32, and privacy_policies pointing to PRIVACY.md and GitLab’s privacy page.
  • Add mcpb/icon.png (512x512) referenced by the manifest as the extension icon.
mcpb/manifest.json
mcpb/icon.png
Document the Claude Desktop extension and privacy behavior for users and directory submission.
  • Add a Claude Desktop Extension guide describing install steps, local build commands, bundle composition, and release workflow behavior.
  • Update docs/guides/README.md to include the new guide in the how-to table.
  • Add a Privacy Policy (PRIVACY.md) detailing data flows, credentials handling, logging, and update behavior.
  • Update README.md with a Claude Desktop row in the one-click install table, description of the native .mcpb extension behavior, and a Privacy Policy section referencing PRIVACY.md.
docs/guides/claude-desktop-extension.md
docs/guides/README.md
PRIVACY.md
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jmrplens, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3a44ae43-5726-4a27-9800-c0cd21d8dafc

📥 Commits

Reviewing files that changed from the base of the PR and between a60bef4 and ddce507.

⛔ Files ignored due to path filters (1)
  • mcpb/icon.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • docs/guides/claude-desktop-extension.md
📝 Walkthrough

Walkthrough

This PR adds Claude Desktop extension (MCPB) support: a new manifest and build script, Makefile targets, GoReleaser universal binary config, release workflow integration to build/upload the artifact, version-sync updates, and accompanying README/guide/privacy documentation.

Changes

Claude Desktop Extension (MCPB)

Layer / File(s) Summary
MCPB manifest definition
mcpb/manifest.json
Defines server identity/version, binary entry point, env-variable mapping, base tools, and full user_config schema.
MCPB build script
scripts/build-mcpb.sh
Parses version/dist args, discovers GoReleaser binaries, assembles bundle, stamps manifest version, and packs the .mcpb output.
Build tooling and release pipeline wiring
Makefile, .goreleaser.yml, scripts/update-server-json-sha.sh, .github/workflows/release.yml
Adds mcpb/check-mcpb Make targets, macOS universal binary GoReleaser config, manifest version stamping in the sync script, and release workflow steps to build/upload the .mcpb artifact and commit mcpb/manifest.json.
Documentation and privacy policy
PRIVACY.md, docs/guides/claude-desktop-extension.md, docs/guides/README.md, README.md
Adds a full privacy policy, a Claude Desktop extension setup guide, a guides index entry, and README install/privacy sections.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CI as release.yml
  participant UpdateScript as update-server-json-sha.sh
  participant BuildScript as build-mcpb.sh
  participant GoReleaser
  participant GitHubRelease as GitHub Release

  CI->>UpdateScript: run version sync
  UpdateScript->>UpdateScript: update mcpb/manifest.json version
  CI->>BuildScript: build-mcpb.sh <tag_version>
  BuildScript->>GoReleaser: locate universal macOS + Windows binaries
  BuildScript->>BuildScript: assemble bundle, stamp manifest, pack .mcpb
  CI->>GitHubRelease: upload gitlab-mcp-server.mcpb
Loading

Possibly related PRs

  • jmrplens/gitlab-mcp-server#33: Both PRs modify scripts/update-server-json-sha.sh and the release workflow to stage/commit additional manifest/version files alongside server.json.

Suggested labels: documentation

Poem

A bundle hops out, shiny and new,
.mcpb packed with a manifest too 🐇
Lipo glues arm and amd into one,
Privacy pages shine in the sun,
CI uploads it, the release is done!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a Claude Desktop extension build and release pipeline.
Description check ✅ Passed The description is substantive and covers the change, verification, and key deliverables, though it does not use the repository's template sections exactly.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mcpb-desktop-extension

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • The MCPB CLI version is pinned separately in the Makefile (MCPB_CLI_VERSION) and in scripts/build-mcpb.sh (MCPB_VERSION); consider centralizing this into a single definition to avoid version drift between validation and packing.
  • scripts/build-mcpb.sh locates binaries with find patterns like *darwin_all* and *windows_amd64*, which couples the bundle build to GoReleaser’s directory naming; if possible, tighten this to the specific GoReleaser IDs/paths to make it more robust against future config changes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The MCPB CLI version is pinned separately in the Makefile (`MCPB_CLI_VERSION`) and in `scripts/build-mcpb.sh` (`MCPB_VERSION`); consider centralizing this into a single definition to avoid version drift between validation and packing.
- `scripts/build-mcpb.sh` locates binaries with `find` patterns like `*darwin_all*` and `*windows_amd64*`, which couples the bundle build to GoReleaser’s directory naming; if possible, tighten this to the specific GoReleaser IDs/paths to make it more robust against future config changes.

## Individual Comments

### Comment 1
<location path="Makefile" line_range="691" />
<code_context>
 	scripts/check-openplugin.sh

+# Pin the MCPB packer CLI for supply-chain integrity (also pinned in scripts/build-mcpb.sh).
+MCPB_CLI_VERSION := 2.1.2
+
+## check-mcpb: validate the Claude Desktop extension manifest (mcpb/manifest.json).
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The MCPB CLI version is now pinned in two places (Makefile and scripts/build-mcpb.sh), which can easily drift out of sync.

Because MCPB_CLI_VERSION here and MCPB_VERSION in scripts/build-mcpb.sh are independent, they can diverge, causing local `make check-mcpb` and release bundling to use different MCPB versions. Please centralize this version (e.g., via a shared env file, a Make variable passed into the script, or generating the script from a template) so it’s defined in only one place.

Suggested implementation:

```
# Pin the MCPB packer CLI for supply-chain integrity.
# This is the single source of truth; scripts/build-mcpb.sh reads MCPB_CLI_VERSION from the environment.
MCPB_CLI_VERSION := 2.1.2

```

```
mcpb:
	@command -v lipo >/dev/null || { echo "ERROR: lipo is required (macOS Xcode CLT)"; exit 1; }
	@set -e; \
	VER=$$(tr -d '[:space:]' < VERSION); \
	MCPB_CLI_VERSION=$(MCPB_CLI_VERSION) scripts/build-mcpb.sh "$$VER"; \

```

To fully implement the centralization and avoid drift, you should also:

1. Update `scripts/build-mcpb.sh` to remove its internal `MCPB_VERSION` (or similarly named) constant and instead read the CLI version from the environment, e.g.:
   ```sh
   : "${MCPB_CLI_VERSION:?MCPB_CLI_VERSION must be set}"
   npx --yes @anthropic-ai/mcpb@"${MCPB_CLI_VERSION}" ...
   ```
2. Ensure that everywhere `scripts/build-mcpb.sh` is invoked (if there are other callers besides the `mcpb` Make target), it either:
   - relies on the Makefile `mcpb` target, or
   - explicitly sets `MCPB_CLI_VERSION` in the environment to keep the single source of truth.
3. Optionally add a brief comment at the top of `scripts/build-mcpb.sh` noting that `MCPB_CLI_VERSION` is expected to be provided by the Makefile so future changes don’t reintroduce a second version pin.
</issue_to_address>

### Comment 2
<location path="scripts/build-mcpb.sh" line_range="47-49" />
<code_context>
+# Locate the GoReleaser artifacts. Binary paths live in per-target build
+# directories (dist/<id>_<goos>_<goarch>[_<goamd64>]/); the darwin universal
+# binary comes from the universal_binaries step (goarch "all").
+find_binary() {
+  local pattern="$1" name="$2" found
+  found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" | head -n1)
+  if [[ -z "$found" ]]; then
+    echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Binary discovery via `find ... | head -n1` is somewhat brittle and can pick an unintended artifact if multiple paths match.

Because this uses `head -n1`, the chosen binary depends on filesystem ordering; leftover or additional GoReleaser artifacts could cause the wrong file to be selected. Prefer matching the exact expected GoReleaser directory structure (e.g., `gitlab-mcp-server_darwin_all/gitlab-mcp-server`, `gitlab-mcp-server_windows_amd64/gitlab-mcp-server.exe`), or at least verify that exactly one match exists and fail if there are zero or multiple matches, to avoid silently bundling an unintended binary.

Suggested implementation:

```
# Locate the GoReleaser artifacts. Binary paths live in per-target build
# directories (dist/<id>_<goos>_<goarch>[_<goamd64>]/); the darwin universal
# binary comes from the universal_binaries step (goarch "all").
find_binary() {
  local pattern="$1" name="$2"
  local matches
  mapfile -t matches < <(find "$DIST_DIR" -type f -path "$pattern" -name "$name")

  if (( ${#matches[@]} == 0 )); then
    echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
    exit 1
  elif (( ${#matches[@]} > 1 )); then
    echo "ERROR: multiple $name files matching $pattern under $DIST_DIR; refusing to pick one automatically" >&2
    printf 'Matches:\n' >&2
    printf '  %s\n' "${matches[@]}" >&2
    exit 1
  fi

  echo "${matches[0]}"
}

# These patterns are intended to match the exact GoReleaser output directories:
#   dist/gitlab-mcp-server_darwin_all/gitlab-mcp-server
#   dist/gitlab-mcp-server_windows_amd64/gitlab-mcp-server.exe
DARWIN_BIN=$(find_binary "$DIST_DIR/gitlab-mcp-server_darwin_all/*" "gitlab-mcp-server")
WINDOWS_BIN=$(find_binary "$DIST_DIR/gitlab-mcp-server_windows_amd64/*" "gitlab-mcp-server.exe")

```

If your GoReleaser IDs or output directory names differ from `gitlab-mcp-server_darwin_all` and `gitlab-mcp-server_windows_amd64`, adjust the two `find_binary` call patterns accordingly to match the actual `dist/<id>_<goos>_<goarch>` layout produced by your `goreleaser.yaml`. If additional platforms (e.g., `linux_amd64`) are bundled, add corresponding `find_binary` invocations using similarly strict patterns so they also benefit from the single-match validation.
</issue_to_address>

### Comment 3
<location path="docs/guides/claude-desktop-extension.md" line_range="58" />
<code_context>
+
+## Privacy and directory submission
+
+The manifest's `privacy_policies` points to [PRIVACY.md](../../PRIVACY.md) and
+the [GitLab Privacy Statement](https://about.gitlab.com/privacy/). Directory
+submissions for desktop extensions go through Anthropic's
</code_context>
<issue_to_address>
**nitpick (typo):** Minor subject–verb agreement tweak in the "privacy_policies" sentence.

Because the field name is plural, “The manifest’s `privacy_policies` points to…” reads a bit off. Consider “The `privacy_policies` field points to…” or “The `privacy_policies` entries point to…” for clearer subject–verb agreement.

```suggestion
The `privacy_policies` field points to [PRIVACY.md](../../PRIVACY.md) and
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread Makefile
scripts/check-openplugin.sh

# Pin the MCPB packer CLI for supply-chain integrity (also pinned in scripts/build-mcpb.sh).
MCPB_CLI_VERSION := 2.1.2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): The MCPB CLI version is now pinned in two places (Makefile and scripts/build-mcpb.sh), which can easily drift out of sync.

Because MCPB_CLI_VERSION here and MCPB_VERSION in scripts/build-mcpb.sh are independent, they can diverge, causing local make check-mcpb and release bundling to use different MCPB versions. Please centralize this version (e.g., via a shared env file, a Make variable passed into the script, or generating the script from a template) so it’s defined in only one place.

Suggested implementation:

# Pin the MCPB packer CLI for supply-chain integrity.
# This is the single source of truth; scripts/build-mcpb.sh reads MCPB_CLI_VERSION from the environment.
MCPB_CLI_VERSION := 2.1.2

mcpb:
	@command -v lipo >/dev/null || { echo "ERROR: lipo is required (macOS Xcode CLT)"; exit 1; }
	@set -e; \
	VER=$$(tr -d '[:space:]' < VERSION); \
	MCPB_CLI_VERSION=$(MCPB_CLI_VERSION) scripts/build-mcpb.sh "$$VER"; \

To fully implement the centralization and avoid drift, you should also:

  1. Update scripts/build-mcpb.sh to remove its internal MCPB_VERSION (or similarly named) constant and instead read the CLI version from the environment, e.g.:
    : "${MCPB_CLI_VERSION:?MCPB_CLI_VERSION must be set}"
    npx --yes @anthropic-ai/mcpb@"${MCPB_CLI_VERSION}" ...
  2. Ensure that everywhere scripts/build-mcpb.sh is invoked (if there are other callers besides the mcpb Make target), it either:
    • relies on the Makefile mcpb target, or
    • explicitly sets MCPB_CLI_VERSION in the environment to keep the single source of truth.
  3. Optionally add a brief comment at the top of scripts/build-mcpb.sh noting that MCPB_CLI_VERSION is expected to be provided by the Makefile so future changes don’t reintroduce a second version pin.

Comment thread scripts/build-mcpb.sh
Comment on lines +47 to +49
find_binary() {
local pattern="$1" name="$2" found
found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" | head -n1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Binary discovery via find ... | head -n1 is somewhat brittle and can pick an unintended artifact if multiple paths match.

Because this uses head -n1, the chosen binary depends on filesystem ordering; leftover or additional GoReleaser artifacts could cause the wrong file to be selected. Prefer matching the exact expected GoReleaser directory structure (e.g., gitlab-mcp-server_darwin_all/gitlab-mcp-server, gitlab-mcp-server_windows_amd64/gitlab-mcp-server.exe), or at least verify that exactly one match exists and fail if there are zero or multiple matches, to avoid silently bundling an unintended binary.

Suggested implementation:

# Locate the GoReleaser artifacts. Binary paths live in per-target build
# directories (dist/<id>_<goos>_<goarch>[_<goamd64>]/); the darwin universal
# binary comes from the universal_binaries step (goarch "all").
find_binary() {
  local pattern="$1" name="$2"
  local matches
  mapfile -t matches < <(find "$DIST_DIR" -type f -path "$pattern" -name "$name")

  if (( ${#matches[@]} == 0 )); then
    echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
    exit 1
  elif (( ${#matches[@]} > 1 )); then
    echo "ERROR: multiple $name files matching $pattern under $DIST_DIR; refusing to pick one automatically" >&2
    printf 'Matches:\n' >&2
    printf '  %s\n' "${matches[@]}" >&2
    exit 1
  fi

  echo "${matches[0]}"
}

# These patterns are intended to match the exact GoReleaser output directories:
#   dist/gitlab-mcp-server_darwin_all/gitlab-mcp-server
#   dist/gitlab-mcp-server_windows_amd64/gitlab-mcp-server.exe
DARWIN_BIN=$(find_binary "$DIST_DIR/gitlab-mcp-server_darwin_all/*" "gitlab-mcp-server")
WINDOWS_BIN=$(find_binary "$DIST_DIR/gitlab-mcp-server_windows_amd64/*" "gitlab-mcp-server.exe")

If your GoReleaser IDs or output directory names differ from gitlab-mcp-server_darwin_all and gitlab-mcp-server_windows_amd64, adjust the two find_binary call patterns accordingly to match the actual dist/<id>_<goos>_<goarch> layout produced by your goreleaser.yaml. If additional platforms (e.g., linux_amd64) are bundled, add corresponding find_binary invocations using similarly strict patterns so they also benefit from the single-match validation.


## Privacy and directory submission

The manifest's `privacy_policies` points to [PRIVACY.md](../../PRIVACY.md) and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (typo): Minor subject–verb agreement tweak in the "privacy_policies" sentence.

Because the field name is plural, “The manifest’s privacy_policies points to…” reads a bit off. Consider “The privacy_policies field points to…” or “The privacy_policies entries point to…” for clearer subject–verb agreement.

Suggested change
The manifest's `privacy_policies` points to [PRIVACY.md](../../PRIVACY.md) and
The `privacy_policies` field points to [PRIVACY.md](../../PRIVACY.md) and

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class packaging and release support for distributing gitlab-mcp-server as a Claude Desktop MCPB (.mcpb) desktop extension (macOS universal + Windows), including manifest/versioning automation and user-facing documentation needed for directory submission.

Changes:

  • Introduces the MCPB bundle (manifest + icon) and a build script to assemble/pack a .mcpb from GoReleaser artifacts.
  • Extends release automation to build/upload the .mcpb asset and to version-stamp mcpb/manifest.json alongside existing manifests.
  • Updates documentation/README to cover Claude Desktop installation and adds a new PRIVACY.md policy referenced by the manifest.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/update-server-json-sha.sh Also stamps MCPB manifest version during releases.
scripts/build-mcpb.sh New script to assemble and pack gitlab-mcp-server.mcpb from dist artifacts.
README.md Adds Claude Desktop download row and links to privacy policy.
PRIVACY.md New privacy policy for connector submission requirements.
mcpb/manifest.json New MCPB v0.3 manifest for Claude Desktop (binary server + user_config).
Makefile Adds mcpb/check-mcpb targets and pins MCPB CLI version.
docs/guides/README.md Adds guide index entry for the Claude Desktop extension.
docs/guides/claude-desktop-extension.md New how-to guide for installing/building the .mcpb extension.
.goreleaser.yml Adds macOS universal binary output for the extension entry point.
.github/workflows/release.yml Builds/uploads .mcpb on release and commits MCPB manifest version bumps.
mcpb/icon.png Adds 512×512 icon for Claude Desktop extension listing.

Comment thread scripts/build-mcpb.sh
Comment on lines +47 to +55
find_binary() {
local pattern="$1" name="$2" found
found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" | head -n1)
if [[ -z "$found" ]]; then
echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
exit 1
fi
echo "$found"
}
# 6. Update MCPB (Claude Desktop extension) manifest version (if present)
MCPB_JSON="mcpb/manifest.json"
if [[ -f "$MCPB_JSON" ]]; then
jq --arg v "$VERSION" '.version = $v' "$MCPB_JSON" > tmp.$$.json && mv tmp.$$.json "$MCPB_JSON"
Comment thread PRIVACY.md
Comment on lines +27 to +34
- **GitHub (auto-update only).** When the auto-update feature is enabled
(`AUTO_UPDATE=true`, the default for standalone binaries), the server
periodically checks GitHub Releases on this repository for new versions and
downloads signed binaries from there. No personal data is sent — it is a
standard HTTPS request to `api.github.com`, subject to the
[GitHub Privacy Statement](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement).
The Claude Desktop extension (`.mcpb`) ships with auto-update **disabled**;
updates arrive through new extension versions instead.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for building and packaging the Claude Desktop extension (.mcpb) for the GitLab MCP Server. It adds configuration for macOS universal binaries in GoReleaser, new Makefile targets, a build script (scripts/build-mcpb.sh), a manifest file (mcpb/manifest.json), a privacy policy (PRIVACY.md), and comprehensive documentation. Feedback on the changes suggests two improvements in scripts/build-mcpb.sh: first, replacing head -n1 in the pipeline to prevent potential SIGPIPE failures when set -o pipefail is active, and second, adding a pre-execution check to verify that npx is installed.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread scripts/build-mcpb.sh
Comment on lines +47 to +55
find_binary() {
local pattern="$1" name="$2" found
found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" | head -n1)
if [[ -z "$found" ]]; then
echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
exit 1
fi
echo "$found"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using head -n1 in a pipeline when set -o pipefail is active can cause the script to fail with exit code 141 (SIGPIPE) if find produces multiple matches and exits after head closes the pipe. To prevent this, we can safely extract the first match using Bash parameter expansion instead of a pipeline.

Suggested change
find_binary() {
local pattern="$1" name="$2" found
found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" | head -n1)
if [[ -z "$found" ]]; then
echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
exit 1
fi
echo "$found"
}
find_binary() {
local pattern="$1" name="$2" found
found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" 2>/dev/null)
found="${found%%$'\\n'*}"
if [[ -z "$found" ]]; then
echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
exit 1
fi
echo "$found"
}

Comment thread scripts/build-mcpb.sh
Comment on lines +39 to +42
if ! command -v jq &> /dev/null; then
echo "ERROR: jq is required but not installed" >&2
exit 1
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The script uses npx to pack the bundle, but it does not verify if npx is installed before running. Adding a check for npx alongside jq provides a friendlier error message if Node.js/npm is missing.

Suggested change
if ! command -v jq &> /dev/null; then
echo "ERROR: jq is required but not installed" >&2
exit 1
fi
if ! command -v jq &> /dev/null; then
echo "ERROR: jq is required but not installed" >&2
exit 1
fi
if ! command -v npx &> /dev/null; then
echo "ERROR: npx is required but not installed (Node.js/npm)" >&2
exit 1
fi

@coderabbitai coderabbitai Bot added the documentation Improvements or additions to documentation label Jul 7, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 112-121: The Claude Desktop extension packaging step in the
release workflow can fail the entire job even though it is non-essential. Update
the build-and-upload block that runs build-mcpb.sh, sha256sum, and gh release
upload so transient failures do not block later release steps, either by making
this step non-fatal or by adding retry/guarding around the npx/build/upload
portion. Keep the core release flow intact so the "Publish to MCP Registry" and
manifest-commit steps still run when this packaging step hits an intermittent
error.

In `@Makefile`:
- Around line 697-711: The mcpb target body is too long and should be moved into
a script to satisfy checkmake. Extract the cross-compile and lipo packaging
steps from the mcpb recipe into a new helper script (for example, a local build
script alongside scripts/build-mcpb.sh), then have the mcpb target simply invoke
that script and the existing packaging script. Keep the version reading and
artifact paths behavior the same, and use the mcpb target plus
scripts/build-mcpb.sh as the main symbols to locate the flow.

In `@mcpb/manifest.json`:
- Line 3: Update the manifest schema version in mcpb/manifest.json from
manifest_version 0.3 to 0.4. This is a simple version bump in the manifest JSON,
and the key to change is manifest_version so the file matches the newer MCPB
CLI-supported schema.

In `@README.md`:
- Around line 67-74: The README setup guidance conflates Docker/stdio clients
with the Claude Desktop extension. Update the install instructions around the
Claude Desktop row and the self-managed GitLab note so Claude Desktop users are
told to configure the required gitlab_url in the extension’s settings UI, while
the GITLAB_URL env var is mentioned only for Docker/stdio MCP clients. Use the
existing Claude Desktop, settings UI, and GITLAB_URL references to split the
guidance clearly.

In `@scripts/build-mcpb.sh`:
- Around line 47-58: The find_binary helper is currently selecting the first
match from find, which can silently pick the wrong GoReleaser artifact when
multiple binaries exist under DIST_DIR. Update find_binary in the build-mcpb.sh
script to detect ambiguous results for the gitlab-mcp-server and
gitlab-mcp-server.exe lookups, and fail with a clear error if more than one
match is found, or otherwise ensure dist/ is cleaned before resolving DARWIN_BIN
and WINDOWS_BIN.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6942e432-4003-44f8-a605-0ea9e17d2712

📥 Commits

Reviewing files that changed from the base of the PR and between e9ab877 and a60bef4.

⛔ Files ignored due to path filters (1)
  • mcpb/icon.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • .github/workflows/release.yml
  • .goreleaser.yml
  • Makefile
  • PRIVACY.md
  • README.md
  • docs/guides/README.md
  • docs/guides/claude-desktop-extension.md
  • mcpb/manifest.json
  • scripts/build-mcpb.sh
  • scripts/update-server-json-sha.sh

Comment on lines +112 to +121
- name: Build and upload Claude Desktop extension (.mcpb)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
VERSION="${GITHUB_REF#refs/tags/v}"
bash scripts/build-mcpb.sh "${VERSION}"
sha256sum dist/gitlab-mcp-server.mcpb
gh release upload "v${VERSION}" dist/gitlab-mcp-server.mcpb --clobber

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Non-essential MCPB step can block the rest of the release job.

This step has no retry and no continue-on-error, unlike the curl calls elsewhere in this job that use --retry 3 --retry-connrefused (Lines 135-136). A transient npx fetch failure or gh release upload hiccup here will abort the job before "Publish to MCP Registry" and the manifest-commit step run, even though the core GoReleaser release already succeeded — turning a packaging nicety into a release blocker.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 112 - 121, The Claude Desktop
extension packaging step in the release workflow can fail the entire job even
though it is non-essential. Update the build-and-upload block that runs
build-mcpb.sh, sha256sum, and gh release upload so transient failures do not
block later release steps, either by making this step non-fatal or by adding
retry/guarding around the npx/build/upload portion. Keep the core release flow
intact so the "Publish to MCP Registry" and manifest-commit steps still run when
this packaging step hits an intermittent error.

Comment thread Makefile
Comment on lines +697 to +711
## mcpb: build the Claude Desktop extension bundle (dist/gitlab-mcp-server.mcpb).
## Cross-compiles the darwin universal binary (lipo) and the windows/amd64 binary,
## then assembles and packs the bundle with scripts/build-mcpb.sh.
mcpb:
@command -v lipo >/dev/null || { echo "ERROR: lipo is required (macOS Xcode CLT)"; exit 1; }
@set -e; \
VER=$$(tr -d '[:space:]' < VERSION); \
rm -rf dist/local_darwin_arm64 dist/local_darwin_amd64 dist/local_darwin_all dist/local_windows_amd64; \
mkdir -p dist/local_darwin_arm64 dist/local_darwin_amd64 dist/local_darwin_all dist/local_windows_amd64; \
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -trimpath -ldflags "-s -w -X main.version=$$VER" -o dist/local_darwin_arm64/gitlab-mcp-server ./cmd/server; \
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -trimpath -ldflags "-s -w -X main.version=$$VER" -o dist/local_darwin_amd64/gitlab-mcp-server ./cmd/server; \
lipo -create -output dist/local_darwin_all/gitlab-mcp-server dist/local_darwin_arm64/gitlab-mcp-server dist/local_darwin_amd64/gitlab-mcp-server; \
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -trimpath -ldflags "-s -w -X main.version=$$VER" -o dist/local_windows_amd64/gitlab-mcp-server.exe ./cmd/server; \
bash scripts/build-mcpb.sh "$$VER"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract mcpb target body into a script.

Static analysis (checkmake) flags this target's body length. Given the project already externalizes MCPB packaging logic into scripts/build-mcpb.sh, consider moving the cross-compile + lipo steps into a small script (e.g. scripts/build-mcpb-local.sh) invoked by this target, consistent with the pattern used elsewhere in this PR.

🧰 Tools
🪛 checkmake (0.3.2)

[warning] 700-700: Target body for "mcpb" exceeds allowed length of 5 lines (10).

(maxbodylength)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 697 - 711, The mcpb target body is too long and should
be moved into a script to satisfy checkmake. Extract the cross-compile and lipo
packaging steps from the mcpb recipe into a new helper script (for example, a
local build script alongside scripts/build-mcpb.sh), then have the mcpb target
simply invoke that script and the existing packaging script. Keep the version
reading and artifact paths behavior the same, and use the mcpb target plus
scripts/build-mcpb.sh as the main symbols to locate the flow.

Source: Linters/SAST tools

Comment thread mcpb/manifest.json
@@ -0,0 +1,131 @@
{
"$schema": "https://raw.githubusercontent.com/modelcontextprotocol/mcpb/main/dist/mcpb-manifest.schema.json",
"manifest_version": "0.3",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What manifest_version values does @anthropic-ai/mcpb 2.1.2 CLI support and validate?

💡 Result:

The @anthropic-ai/mcpb CLI tool version 2.1.2 supports and validates manifest_version values "0.1", "0.2", and "0.3" [1][2]. The tool includes versioned schemas for these manifest versions, which are used to validate the structure of the manifest.json file [1][2]. The package explicitly exports these schemas, including a union schema capable of validating manifests from any of these supported versions (0.1, 0.2, and 0.3) [2]. When using the mcpb validate command, the CLI checks the provided manifest against these schema definitions to ensure it conforms to the required specification [3]. While "0.3" is commonly cited in documentation as a current version [4][5], the CLI architecture maintains backward compatibility by including schemas for the older versions [1][2].

Citations:


🌐 Web query:

Current MCPB manifest schema version and whether @anthropic-ai/mcpb 2.1.2 supports manifest_version 0.4

💡 Result:

The current MCPB manifest schema version is 0.4 [1][2][3]. Yes, the @anthropic-ai/mcpb package version 2.1.2 supports manifest_version 0.4 [2]. The package includes specific Zod and JSON schemas for version 0.4, as well as an "any" union schema that validates manifests across supported versions [4][2]. Documentation also explicitly notes that the 0.4 manifest version introduces the "uv" runtime type [2][5][6].

Citations:


Bump mcpb/manifest.json to manifest_version: "0.4"
The pinned MCPB CLI already supports the 0.4 schema, so keeping 0.3 leaves this manifest on an older version.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mcpb/manifest.json` at line 3, Update the manifest schema version in
mcpb/manifest.json from manifest_version 0.3 to 0.4. This is a simple version
bump in the manifest JSON, and the key to change is manifest_version so the file
matches the newer MCPB CLI-supported schema.

Comment thread README.md
Comment on lines +67 to +74
<tr>
<td><b>Claude Desktop</b></td>
<td><a href="https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server.mcpb"><img alt="Download .mcpb extension" src="https://img.shields.io/badge/Download-.mcpb_extension-d97757?style=flat-square&amp;logo=claude&amp;logoColor=white" /></a></td>
<td>settings UI (keychain)</td>
</tr>
</table>

Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope. Self-managed GitLab? Add a `GITLAB_URL` env var in your client's MCP config after install.
Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). The **Claude Desktop** row instead downloads a native [.mcpb desktop extension](docs/guides/claude-desktop-extension.md) (macOS universal + Windows, no Docker) — open it with Claude Desktop and fill in the settings. Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope. Self-managed GitLab? Add a `GITLAB_URL` env var in your client's MCP config after install.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clarify the self-managed GitLab instruction for Claude Desktop.

The Claude Desktop extension uses the settings UI (gitlab_url is a required user_config field), so the GITLAB_URL env-var advice only applies to the Docker/stdio clients. Split this into client-specific guidance to avoid sending Claude Desktop users down the wrong setup path.

Proposed fix
-Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). The **Claude Desktop** row instead downloads a native [.mcpb desktop extension](docs/guides/claude-desktop-extension.md) (macOS universal + Windows, no Docker) — open it with Claude Desktop and fill in the settings. Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope. Self-managed GitLab? Add a `GITLAB_URL` env var in your client's MCP config after install.
+Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). The **Claude Desktop** row instead downloads a native [.mcpb desktop extension](docs/guides/claude-desktop-extension.md) (macOS universal + Windows, no Docker) — open it with Claude Desktop and fill in the settings.
+Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope.
+For the Docker-based options, add `GITLAB_URL` in your client's MCP config after install. For Claude Desktop, set the URL in the extension settings UI.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<tr>
<td><b>Claude Desktop</b></td>
<td><a href="https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server.mcpb"><img alt="Download .mcpb extension" src="https://img.shields.io/badge/Download-.mcpb_extension-d97757?style=flat-square&amp;logo=claude&amp;logoColor=white" /></a></td>
<td>settings UI (keychain)</td>
</tr>
</table>
Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope. Self-managed GitLab? Add a `GITLAB_URL` env var in your client's MCP config after install.
Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). The **Claude Desktop** row instead downloads a native [.mcpb desktop extension](docs/guides/claude-desktop-extension.md) (macOS universal + Windows, no Docker) — open it with Claude Desktop and fill in the settings. Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope. Self-managed GitLab? Add a `GITLAB_URL` env var in your client's MCP config after install.
<tr>
<td><b>Claude Desktop</b></td>
<td><a href="https://github.com/jmrplens/gitlab-mcp-server/releases/latest/download/gitlab-mcp-server.mcpb"><img alt="Download .mcpb extension" src="https://img.shields.io/badge/Download-.mcpb_extension-d97757?style=flat-square&amp;logo=claude&amp;logoColor=white" /></a></td>
<td>settings UI (keychain)</td>
</tr>
</table>
Each button registers the **Docker**-based server (auto-pulls the image on first run; you need [Docker](https://www.docker.com/) installed). The **Claude Desktop** row instead downloads a native [.mcpb desktop extension](docs/guides/claude-desktop-extension.md) (macOS universal + Windows, no Docker) — open it with Claude Desktop and fill in the settings.
Need a token? [Create a Personal Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) with the **`api`** scope.
For the Docker-based options, add `GITLAB_URL` in your client's MCP config after install. For Claude Desktop, set the URL in the extension settings UI.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 67 - 74, The README setup guidance conflates
Docker/stdio clients with the Claude Desktop extension. Update the install
instructions around the Claude Desktop row and the self-managed GitLab note so
Claude Desktop users are told to configure the required gitlab_url in the
extension’s settings UI, while the GITLAB_URL env var is mentioned only for
Docker/stdio MCP clients. Use the existing Claude Desktop, settings UI, and
GITLAB_URL references to split the guidance clearly.

Comment thread scripts/build-mcpb.sh
Comment on lines +47 to +58
find_binary() {
local pattern="$1" name="$2" found
found=$(find "$DIST_DIR" -type f -path "$pattern" -name "$name" | head -n1)
if [[ -z "$found" ]]; then
echo "ERROR: no $name matching $pattern under $DIST_DIR — run GoReleaser first" >&2
exit 1
fi
echo "$found"
}

DARWIN_BIN=$(find_binary "*darwin_all*" "gitlab-mcp-server")
WINDOWS_BIN=$(find_binary "*windows_amd64*" "gitlab-mcp-server.exe")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== scripts/build-mcpb.sh ==\n'
cat -n scripts/build-mcpb.sh | sed -n '1,220p'

printf '\n== Makefile targets mentioning mcpb or dist/local_ ==\n'
rg -n "mcpb|dist/local_|goreleaser|DIST_DIR" Makefile scripts -S

printf '\n== Candidate build scripts and cleanup references ==\n'
rg -n "rm -rf .*dist|clean.*dist|dist/" -S . --glob '!**/node_modules/**'

Repository: jmrplens/gitlab-mcp-server

Length of output: 22047


Fail on ambiguous binary matches. find_binary takes the first find result, so leftover GoReleaser artifacts alongside the local dist/local_* build can make the bundle pick an arbitrary darwin/windows binary. Reject multiple matches or clean dist/ before selecting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/build-mcpb.sh` around lines 47 - 58, The find_binary helper is
currently selecting the first match from find, which can silently pick the wrong
GoReleaser artifact when multiple binaries exist under DIST_DIR. Update
find_binary in the build-mcpb.sh script to detect ambiguous results for the
gitlab-mcp-server and gitlab-mcp-server.exe lookups, and fail with a clear error
if more than one match is found, or otherwise ensure dist/ is cleaned before
resolving DARWIN_BIN and WINDOWS_BIN.

@jmrplens
jmrplens merged commit c2526c8 into main Jul 7, 2026
19 checks passed
@jmrplens
jmrplens deleted the feat/mcpb-desktop-extension branch July 7, 2026 22:07
@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

jmrplens added a commit that referenced this pull request Jul 7, 2026
Bumps `VERSION` to **2.5.0** — first release carrying the Claude Desktop
extension (`.mcpb`) pipeline (#224).

- `VERSION` 2.4.1 → 2.5.0 (minor: new feature)
- `CLAUDE.md`: version table + project tree (adds `mcpb/`)
- Regenerated: README stats, `llms.txt` / `llms-full.txt`, site stats,
testing docs (`make update-all`)

After merging, tagging the squash commit as `v2.5.0` triggers the
release pipeline (E2E gate → GoReleaser incl. darwin universal binary →
`.mcpb` asset → Docker → MCP Registry → manifest commit-back).

Release-pipeline changes were verified locally end to end: GoReleaser
snapshot → `scripts/build-mcpb.sh` → stamped bundle unpacked, fat binary
(x86_64+arm64) smoke-tested over stdio.

https://claude.ai/code/session_01LJ6D4L6rnms9GqMqqc2tFb

## Summary by Sourcery

Bump the project version to 2.5.0 and regenerate codebase and testing
statistics for the release.

Documentation:
- Update CLAUDE.md with the 2.5.0 version and document the new mcpb/
Claude Desktop extension assets directory.
- Refresh README codebase metrics, hall-of-fame stats, and assorted
project statistics to reflect the latest state.

Tests:
- Regenerate testing documentation metrics and coverage tables to
reflect the current test counts and distribution.

Chores:
- Update the VERSION file and associated llms/site stats artifacts in
preparation for the 2.5.0 release pipeline.
@jmrplens jmrplens added ci Build pipeline, workflows, or lint configuration distribution Release artifacts, packaging, and install channels feature New feature or MCP tool security Security-related issue labels Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Build pipeline, workflows, or lint configuration distribution Release artifacts, packaging, and install channels documentation Improvements or additions to documentation feature New feature or MCP tool security Security-related issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants