Skip to content

Conversation

@vchomakov
Copy link
Member

Add MCP Registry Publishing to Release Workflow

Summary

Extends the release workflow to automatically publish the Redis MCP Server to the Model Context Protocol Registry alongside PyPI releases.

What's Changed

New Job: publish-mcp-registry

Adds automated publishing to the MCP Registry using GitHub OIDC authentication:

  • Triggers: Runs on GitHub releases or manual workflow dispatch (when not in dry-run mode)
  • Authentication: Uses GitHub OIDC (id-token: write permission) for secure, keyless publishing
  • Version Sync: Automatically updates server.json with the release version
  • Validation: Verifies server.json is valid JSON before publishing
  • Dry-run Support: Respects the existing dry_run input to test without publishing

Updated server.json

  • Removed OCI/Docker package entry (until Docker image versioning is resolved)
  • Kept PyPI package configuration for registry publishing

Enhanced Success Notifications

  • Added MCP Registry link to success notifications
  • Updated messaging to reflect dual publishing (PyPI + MCP Registry)

How It Works

  1. Version Detection: Extracts version from release tag or manual input
  2. Update server.json: Injects the version into the MCP server manifest
  3. Download Publisher: Fetches the official mcp-publisher CLI tool
  4. Validate: Ensures server.json is valid JSON
  5. Authenticate: Uses GitHub OIDC to authenticate with the registry
  6. Publish: Submits the server to the MCP Registry

Workflow Steps

publish-mcp-registry:
  - Checkout repository
  - Update server.json version
  - Install MCP Publisher CLI
  - Verify server.json is valid
  - Login to MCP Registry (via GitHub OIDC)
  - Publish to registry

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR extends the release workflow to automatically publish the Redis MCP Server to the Model Context Protocol Registry alongside PyPI releases, using GitHub OIDC authentication for secure, keyless publishing.

Key Changes:

  • Added publish-mcp-registry job that updates server.json with release version and publishes to MCP Registry via OIDC
  • Removed OCI/Docker package entry from server.json (deferred until Docker versioning is resolved)
  • Enhanced success notifications to include MCP Registry links

Reviewed Changes

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

File Description
server.json Removed Docker/OCI package entry, keeping only PyPI configuration for registry publishing
.github/workflows/release.yml Added new publish-mcp-registry job with version sync, MCP Publisher CLI installation, OIDC authentication, and publishing steps; updated success notifications to reflect dual publishing

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@bobymicroby bobymicroby left a comment

Choose a reason for hiding this comment

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

lgtm

@redis redis deleted a comment from Copilot AI Nov 14, 2025
@redis redis deleted a comment from Copilot AI Nov 14, 2025
@redis redis deleted a comment from Copilot AI Nov 14, 2025
@redis redis deleted a comment from Copilot AI Nov 14, 2025
@redis redis deleted a comment from Copilot AI Nov 14, 2025
@redis redis deleted a comment from Copilot AI Nov 14, 2025
@vchomakov vchomakov requested a review from Copilot November 14, 2025 16:23
Copilot finished reviewing on behalf of vchomakov November 14, 2025 16:27
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

notify-success:
runs-on: ubuntu-latest
needs: [validate-release, build-and-publish, publish-mcp-registry]
if: success()
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The notify-success job depends on publish-mcp-registry, but that job is conditionally skipped when dry_run is enabled. When a dependency is skipped, GitHub Actions also skips dependent jobs unless they use if: always() or similar conditions.

This means success notifications won't appear during dry-run scenarios. To ensure notifications always run when prior jobs succeed (even if some are skipped), update the condition:

notify-success:
  runs-on: ubuntu-latest
  needs: [validate-release, build-and-publish, publish-mcp-registry]
  if: ${{ always() && !cancelled() && needs.build-and-publish.result == 'success' }}

This ensures notifications run as long as the build succeeded, regardless of whether MCP publishing was skipped.

Suggested change
if: success()
if: ${{ always() && !cancelled() && needs.build-and-publish.result == 'success' }}

Copilot uses AI. Check for mistakes.
- name: ⚙️ Install MCP Publisher
run: |
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xzf - mcp-publisher
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The MCP Publisher installation has multiple issues:

  1. Security: Downloads from /releases/latest/download/ without verifying checksums or signatures
  2. Error handling: The tar command will fail silently if the download fails or tarball is corrupted
  3. Reliability: Uses latest instead of pinning to a specific version

Recommended improvements:

# Pin to specific version and add error handling
VERSION="v1.0.0"  # Replace with actual version
ARCH="$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
DOWNLOAD_URL="https://github.com/modelcontextprotocol/registry/releases/download/${VERSION}/mcp-publisher_${ARCH}.tar.gz"

if ! curl -fL "$DOWNLOAD_URL" | tar xzf - mcp-publisher; then
  echo "Error: Failed to download or extract mcp-publisher"
  exit 1
fi

if [ ! -f mcp-publisher ]; then
  echo "Error: mcp-publisher binary not found after extraction"
  exit 1
fi

chmod +x mcp-publisher
Suggested change
curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xzf - mcp-publisher
# Pin to a specific version of MCP Publisher
MCP_PUBLISHER_VERSION="v1.0.0" # TODO: Update to desired version
ARCH="$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
DOWNLOAD_URL="https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}/mcp-publisher_${ARCH}.tar.gz"
if ! curl -fL "$DOWNLOAD_URL" | tar xzf - mcp-publisher; then
echo "Error: Failed to download or extract mcp-publisher"
exit 1
fi
if [ ! -f mcp-publisher ]; then
echo "Error: mcp-publisher binary not found after extraction"
exit 1
fi

Copilot uses AI. Check for mistakes.
Comment on lines +361 to +363
echo "🔌 MCP Registry:"
echo " https://registry.modelcontextprotocol.io/v0/servers?search=redis"
echo ""
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The MCP Registry link is shown unconditionally in the success message, but the publish-mcp-registry job may have been skipped (e.g., during dry-run mode when the job's condition on line 249 is false). This could mislead users into thinking their package was published to the MCP Registry when it wasn't.

Add a conditional check to only show the MCP Registry link when publishing actually occurred:

if [[ "${{ inputs.dry_run }}" != "true" ]]; then
  echo ""
  echo "🔌 MCP Registry:"
  echo "   https://registry.modelcontextprotocol.io/v0/servers?search=redis"
  echo ""
fi
Suggested change
echo "🔌 MCP Registry:"
echo " https://registry.modelcontextprotocol.io/v0/servers?search=redis"
echo ""
if [[ "${{ inputs.dry_run }}" != "true" ]]; then
echo "🔌 MCP Registry:"
echo " https://registry.modelcontextprotocol.io/v0/servers?search=redis"
echo ""
fi

Copilot uses AI. Check for mistakes.
Comment on lines +263 to +278
- name: ⚙️ Verify server.json exists and is valid JSON
run: |
if [ ! -f server.json ]; then
echo "Error: server.json not found"
exit 1
fi
if ! jq empty server.json 2>/dev/null; then
echo "Error: server.json is not valid JSON"
exit 1
fi
echo "Success: server.json is valid JSON"
echo "Original server.json:"
cat server.json
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

This validation step will fail because the checked-out server.json contains $VERSION placeholders, which are not valid JSON. The validation occurs before the version replacement in the next step.

Recommendation: Remove this initial validation step and rely on the validation at lines 302-307 that occurs after the version has been replaced with actual values.

Suggested change
- name: ⚙️ Verify server.json exists and is valid JSON
run: |
if [ ! -f server.json ]; then
echo "Error: server.json not found"
exit 1
fi
if ! jq empty server.json 2>/dev/null; then
echo "Error: server.json is not valid JSON"
exit 1
fi
echo "Success: server.json is valid JSON"
echo "Original server.json:"
cat server.json

Copilot uses AI. Check for mistakes.
"title": "Redis MCP Server",
"description": "Natural language interface designed for agentic applications to manage and search data in Redis.",
"version": "0.3.6",
"version": "$VERSION",
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The $VERSION placeholder in the checked-in server.json file is not valid JSON. This will cause JSON validation to fail when the file is committed to the repository, as $VERSION is not a valid JSON string value.

Consider one of these approaches:

  1. Keep a valid version number in the file (e.g., "0.0.0" or the current version) and update it during the workflow
  2. If $VERSION is intentional, add a step in the workflow to validate the file before the version replacement step

Copilot uses AI. Check for mistakes.
Comment on lines +321 to +325
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
run: ./mcp-publisher login github-oidc

- name: ⚙️ Publish to MCP Registry
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The conditional logic here is inconsistent with the job-level if condition on line 249. This step uses inputs.dry_run != true while the job condition uses !inputs.dry_run.

When inputs.dry_run is not provided (e.g., on a release event), these expressions evaluate differently:

  • !inputs.dry_run evaluates to true (the default for missing boolean inputs)
  • inputs.dry_run != true also evaluates to true

However, for clarity and consistency, use the same expression format throughout. Recommend changing to !inputs.dry_run to match line 249.

Suggested change
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
run: ./mcp-publisher login github-oidc
- name: ⚙️ Publish to MCP Registry
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) }}
run: ./mcp-publisher login github-oidc
- name: ⚙️ Publish to MCP Registry
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) }}

Copilot uses AI. Check for mistakes.
Comment on lines +321 to +325
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
run: ./mcp-publisher login github-oidc

- name: ⚙️ Publish to MCP Registry
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The conditional logic here is inconsistent with the job-level if condition on line 249. This step uses inputs.dry_run != true while the job condition uses !inputs.dry_run.

For clarity and consistency, use the same expression format throughout. Recommend changing to !inputs.dry_run to match line 249.

Suggested change
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
run: ./mcp-publisher login github-oidc
- name: ⚙️ Publish to MCP Registry
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.dry_run != true) }}
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) }}
run: ./mcp-publisher login github-oidc
- name: ⚙️ Publish to MCP Registry
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && !inputs.dry_run) }}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants