chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:37:57 +08:00
commit e30f8ba47c
533 changed files with 115926 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
name: AI Issue Assessment
on:
issues:
types: [opened, labeled]
jobs:
ai-issue-assessment:
runs-on: ubuntu-latest
permissions:
issues: write
models: read
contents: read
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Run AI assessment
uses: github/ai-assessment-comment-labeler@e3bedc38cfffa9179fe4cee8f7ecc93bffb3fee7 # v1.0.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ai_review_label: "request ai review"
issue_number: ${{ github.event.issue.number }}
issue_body: ${{ github.event.issue.body }}
prompts_directory: ".github/prompts"
labels_to_prompts_mapping: "bug,bug-report-review.prompt.yml|default,default-issue-review.prompt.yml"
@@ -0,0 +1,28 @@
name: Close inactive issues
on:
schedule:
- cron: "30 8 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
env:
PR_DAYS_BEFORE_STALE: 30
PR_DAYS_BEFORE_CLOSE: 60
PR_STALE_LABEL: stale
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v10
with:
days-before-issue-stale: ${{ env.PR_DAYS_BEFORE_STALE }}
days-before-issue-close: ${{ env.PR_DAYS_BEFORE_CLOSE }}
stale-issue-label: ${{ env.PR_STALE_LABEL }}
stale-issue-message: "This issue is stale because it has been open for ${{ env.PR_DAYS_BEFORE_STALE }} days with no activity. Leave a comment to avoid closing this issue in ${{ env.PR_DAYS_BEFORE_CLOSE }} days."
close-issue-message: "This issue was closed because it has been inactive for ${{ env.PR_DAYS_BEFORE_CLOSE }} days since being marked as stale."
days-before-pr-stale: ${{ env.PR_DAYS_BEFORE_STALE }}
days-before-pr-close: ${{ env.PR_DAYS_BEFORE_STALE }}
# Start with the oldest items first
ascending: true
repo-token: ${{ secrets.GITHUB_TOKEN }}
+103
View File
@@ -0,0 +1,103 @@
name: "CodeQL"
run-name: ${{ github.event.inputs.code_scanning_run_name }}
on: [push, pull_request, workflow_dispatch]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CODE_SCANNING_REF: ${{ github.event.inputs.code_scanning_ref }}
CODE_SCANNING_BASE_BRANCH: ${{ github.event.inputs.code_scanning_base_branch }}
CODE_SCANNING_IS_ANALYZING_DEFAULT_BRANCH: ${{ github.event.inputs.code_scanning_is_analyzing_default_branch }}
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Only run on the main repository, not on forks
if: github.repository == 'github/github-mcp-server'
runs-on: ${{ fromJSON(matrix.runner) }}
permissions:
actions: read
contents: read
packages: read
security-events: write
continue-on-error: false
strategy:
fail-fast: false
matrix:
include:
- language: actions
category: /language:actions
build-mode: none
runner: '["ubuntu-22.04"]'
- language: go
category: /language:go
build-mode: autobuild
runner: '["ubuntu-22.04"]'
- language: javascript
category: /language:javascript
build-mode: none
runner: '["ubuntu-22.04"]'
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
dependency-caching: ${{ runner.environment == 'github-hosted' }}
queries: "" # Default query suite
packs: github/ccr-${{ matrix.language }}-queries
config: |
paths-ignore:
- third-party
- third-party-licenses.*.md
default-setup:
org:
model-packs: [ ${{ github.event.inputs.code_scanning_codeql_packs }} ]
threat-models: [ ]
- name: Setup proxy for registries
id: proxy
uses: github/codeql-action/start-proxy@v4
with:
registries_credentials: ${{ secrets.GITHUB_REGISTRIES_PROXY }}
language: ${{ matrix.language }}
- name: Configure
uses: github/codeql-action/resolve-environment@v4
id: resolve-environment
with:
language: ${{ matrix.language }}
- name: Setup Go
uses: actions/setup-go@v6
if: matrix.language == 'go' && fromJSON(steps.resolve-environment.outputs.environment).configuration.go.version
with:
go-version: ${{ fromJSON(steps.resolve-environment.outputs.environment).configuration.go.version }}
cache: false
- name: Set up Node.js (for JavaScript CodeQL)
if: matrix.language == 'javascript'
uses: actions/setup-node@v6
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json
- name: Build UI
if: matrix.language == 'go'
uses: ./.github/actions/build-ui
- name: Autobuild
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
env:
CODEQL_PROXY_HOST: ${{ steps.proxy.outputs.proxy_host }}
CODEQL_PROXY_PORT: ${{ steps.proxy.outputs.proxy_port }}
CODEQL_PROXY_CA_CERTIFICATE: ${{ steps.proxy.outputs.proxy_ca_certificate }}
with:
category: ${{ matrix.category }}
+138
View File
@@ -0,0 +1,138 @@
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: "27 0 * * *"
push:
branches: ["main", "next"]
# Publish semver tags as releases.
tags: ["v*.*.*"]
pull_request:
branches: ["main", "next"]
workflow_dispatch:
inputs:
description:
required: false
description: "Description of the run."
type: string
default: "Manual run"
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest-xl
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v7
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 #v4.1.2
with:
cosign-release: "v2.2.4"
# Set up BuildKit Docker container builder to be able to build
# multi-platform images and export cache
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
type=edge
# Custom rule to prevent pre-releases from getting latest tag
type=raw,value=latest,enable=${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-') }}
- name: Go Build Cache for Docker
uses: actions/cache@v5
with:
path: go-build-cache
key: ${{ runner.os }}-go-build-cache-${{ hashFiles('**/go.sum') }}
- name: Inject go-build-cache
uses: reproducible-containers/buildkit-cache-dance@5422eac04292c961a382e0f584ea0f03ad9da723 # v3.4.0
with:
cache-map: |
{
"go-build-cache/apk": "/var/cache/apk",
"go-build-cache/pkg": "/go/pkg/mod",
"go-build-cache/build": "/root/.cache/go-build"
}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
build-args: |
VERSION=${{ github.ref_name }}
secrets: |
oauth_client_id=${{ secrets.OAUTH_CLIENT_ID }}
oauth_client_secret=${{ secrets.OAUTH_CLIENT_SECRET }}
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
+50
View File
@@ -0,0 +1,50 @@
name: Documentation Check
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
docs-check:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Build UI
uses: ./.github/actions/build-ui
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Build docs generator
run: go build -o github-mcp-server ./cmd/github-mcp-server
- name: Generate documentation
run: ./github-mcp-server generate-docs
- name: Check for documentation changes
run: |
if ! git diff --exit-code README.md; then
echo "❌ Documentation is out of date!"
echo ""
echo "The generated documentation differs from what's committed."
echo "Please run the following command to update the documentation:"
echo ""
echo " go run ./cmd/github-mcp-server generate-docs"
echo ""
echo "Then commit the changes."
echo ""
echo "Changes detected:"
git diff README.md
exit 1
else
echo "✅ Documentation is up to date!"
fi
+44
View File
@@ -0,0 +1,44 @@
name: Build and Test Go Project
on: [push, pull_request]
permissions:
contents: read
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Force git to use LF
# This step is required on Windows to work around go mod tidy -diff issues caused by CRLF line endings.
# TODO: replace with a checkout option when https://github.com/actions/checkout/issues/226 is implemented
if: runner.os == 'Windows'
run: |
git config --global core.autocrlf false
git config --global core.eol lf
- name: Check out code
uses: actions/checkout@v7
- name: Build UI
uses: ./.github/actions/build-ui
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
- name: Tidy dependencies
run: go mod tidy -diff
- name: Run unit tests
shell: bash
run: script/test
- name: Build
run: go build -v ./cmd/github-mcp-server
+50
View File
@@ -0,0 +1,50 @@
name: GoReleaser Release
on:
push:
tags:
- "v*"
permissions:
contents: write
id-token: write
attestations: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v7
- name: Build UI
uses: ./.github/actions/build-ui
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
- name: Download dependencies
run: go mod download
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94
with:
distribution: goreleaser
# GoReleaser version
version: "~> v2"
# Arguments to pass to GoReleaser
args: release --clean
workdir: .
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }}
OAUTH_CLIENT_SECRET: ${{ secrets.OAUTH_CLIENT_SECRET }}
- name: Generate signed build provenance attestations for workflow artifacts
uses: actions/attest-build-provenance@v4
with:
subject-path: |
dist/*.tar.gz
dist/*.zip
dist/*.txt
+19
View File
@@ -0,0 +1,19 @@
name: Label issues for AI review
on:
issues:
types:
- reopened
- opened
jobs:
label_issues:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add AI review label to issue
run: gh issue edit "$NUMBER" --add-label "$LABELS"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.issue.number }}
LABELS: "request ai review"
+116
View File
@@ -0,0 +1,116 @@
# Automatically fix license files on PRs that need updates
# Tries to auto-commit the fix, or comments with instructions if push fails
name: License Check
on:
pull_request:
branches:
- main # Only run when PR targets main
paths:
- "**.go"
- go.mod
- go.sum
- ".github/licenses.tmpl"
- "script/licenses*"
- "third-party-licenses.*.md"
- "third-party/**"
permissions:
contents: write
pull-requests: write
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v7
# Check out the actual PR branch so we can push changes back if needed
- name: Check out PR branch
env:
GH_TOKEN: ${{ github.token }}
run: gh pr checkout ${{ github.event.pull_request.number }}
- name: Build UI
uses: ./.github/actions/build-ui
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
# actions/setup-go does not setup the installed toolchain to be preferred over the system install,
# which causes go-licenses to raise "Package ... does not have module info" errors.
# For more information, https://github.com/google/go-licenses/issues/244#issuecomment-1885098633
- name: Regenerate licenses
env:
CI: "true"
run: |
export GOROOT=$(go env GOROOT)
export PATH=${GOROOT}/bin:$PATH
./script/licenses
- name: Check for changes
id: changes
continue-on-error: true
run: script/licenses-check
- name: Commit and push fixes
if: steps.changes.outcome == 'failure'
continue-on-error: true
id: push
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add third-party-licenses.*.md third-party/
git commit -m "chore: regenerate license files" -m "Auto-generated by license-check workflow"
git push
- name: Check if already commented
if: steps.changes.outcome == 'failure' && steps.push.outcome == 'failure'
id: check_comment
uses: actions/github-script@v9
with:
script: |
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
const alreadyCommented = comments.some(comment =>
comment.user.login === 'github-actions[bot]' &&
comment.body.includes('## ⚠️ License files need updating')
);
core.setOutput('already_commented', alreadyCommented ? 'true' : 'false');
- name: Comment with instructions if cannot push
if: steps.changes.outcome == 'failure' && steps.push.outcome == 'failure' && steps.check_comment.outputs.already_commented == 'false'
uses: actions/github-script@v9
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## ⚠️ License files need updating
The license files are out of date. I tried to fix them automatically but don't have permission to push to this branch.
**Please run:**
\`\`\`bash
script/licenses
git add third-party-licenses.*.md third-party/
git commit -m "chore: regenerate license files"
git push
\`\`\`
Alternatively, enable "Allow edits by maintainers" in the PR settings so I can fix it automatically.`
});
- name: Fail check if changes needed
if: steps.changes.outcome == 'failure'
run: exit 1
+26
View File
@@ -0,0 +1,26 @@
name: golangci-lint
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Build UI
uses: ./.github/actions/build-ui
- uses: actions/setup-go@v6
with:
go-version: '1.25'
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
# sync with script/lint
version: v2.9
+140
View File
@@ -0,0 +1,140 @@
name: MCP Server Diff
on:
pull_request:
push:
branches: [main]
tags: ['v*']
permissions:
contents: read
jobs:
mcp-diff:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Build UI
uses: ./.github/actions/build-ui
- name: Stash UI artifacts for baseline checkout
# mcp-server-diff checks the baseline ref out into a separate working
# directory and runs install_command there. Without these prebuilt
# artifacts, pkg/github/ui_dist/ would be empty on the baseline side
# and UIAssetsAvailable() would return false, producing a false-positive
# diff that "adds" _meta.ui to MCP Apps tools on every PR.
run: |
mkdir -p "${RUNNER_TEMP}/ui_dist"
cp pkg/github/ui_dist/*.html "${RUNNER_TEMP}/ui_dist/"
- name: Generate diff configurations
id: configs
# The generator imports pkg/github so any new entry in
# AllowedFeatureFlags is automatically diffed without touching this
# workflow. See script/print-mcp-diff-configs/main.go.
run: |
{
echo 'configurations<<MCP_DIFF_EOF'
go run ./script/print-mcp-diff-configs
echo 'MCP_DIFF_EOF'
} >> "$GITHUB_OUTPUT"
- name: Run MCP Server Diff
# Pinned to the cross-spec-aware mcp-server-diff v3.0.0 (full SHA required —
# Actions rejects shortened SHAs): normalizes _meta plumbing, cache hints,
# initialize envelope, tool-annotation default hints; probes each server at its
# own newest spec via the stateless SEP-2575 server/discover path. Keeps the
# go-sdk v1.6.1 -> v1.7.0-pre.1 bump an honest, signal-only diff. github/copilot-mcp-core#1709.
uses: SamMorrowDrums/mcp-server-diff@40d992e0a220e5b63378758f9a40d6a8982898d2 # v3.0.0
with:
setup_go: "false"
install_command: |
go mod download
mkdir -p pkg/github/ui_dist
cp "${RUNNER_TEMP}"/ui_dist/*.html pkg/github/ui_dist/
start_command: go run ./cmd/github-mcp-server stdio
env_vars: |
GITHUB_PERSONAL_ACCESS_TOKEN=test-token
configurations: ${{ steps.configs.outputs.configurations }}
- name: Add interpretation note
if: always()
run: |
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "️ **Note:** Differences may be intentional improvements." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Common expected differences:" >> $GITHUB_STEP_SUMMARY
echo "- New tools/toolsets added" >> $GITHUB_STEP_SUMMARY
echo "- Tool descriptions updated" >> $GITHUB_STEP_SUMMARY
echo "- Capability changes (intentional improvements)" >> $GITHUB_STEP_SUMMARY
mcp-diff-http:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Build UI
uses: ./.github/actions/build-ui
- name: Stash UI artifacts for baseline checkout
# See the stdio job above for rationale: the action's baseline checkout
# has no UI artifacts unless we hand them over via RUNNER_TEMP.
run: |
mkdir -p "${RUNNER_TEMP}/ui_dist"
cp pkg/github/ui_dist/*.html "${RUNNER_TEMP}/ui_dist/"
- name: Generate diff configurations
id: configs
# See script/print-mcp-diff-configs/main.go. The http-headers variant
# points every config at a shared HTTP server started by the action
# and carries per-config settings via X-MCP-* headers, mirroring how
# the remote server is invoked in production (server-side defaults +
# per-user header overrides).
run: |
{
echo 'configurations<<MCP_DIFF_EOF'
go run ./script/print-mcp-diff-configs -transport http-headers
echo 'MCP_DIFF_EOF'
} >> "$GITHUB_OUTPUT"
- name: Run MCP Server Diff (streamable-http)
# Pinned to mcp-server-diff v3.0.0 — see rationale on the stdio job above.
uses: SamMorrowDrums/mcp-server-diff@40d992e0a220e5b63378758f9a40d6a8982898d2 # v3.0.0
with:
setup_go: "false"
install_command: |
go mod download
mkdir -p pkg/github/ui_dist
cp "${RUNNER_TEMP}"/ui_dist/*.html pkg/github/ui_dist/
http_start_command: go run ./cmd/github-mcp-server http --port 8082
http_startup_wait_ms: "5000"
configurations: ${{ steps.configs.outputs.configurations }}
- name: Add interpretation note
if: always()
run: |
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "️ **Note:** This job exercises the streamable-http transport against a shared server, with per-config settings supplied via X-MCP-* request headers." >> $GITHUB_STEP_SUMMARY
+28
View File
@@ -0,0 +1,28 @@
name: AI Moderator
on:
issues:
types: [opened]
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
spam-detection:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
models: read
contents: read
steps:
- uses: actions/checkout@v7
- uses: github/ai-moderator@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
spam-label: 'spam'
ai-label: 'ai-generated'
minimize-detected-comments: true
enable-spam-detection: true
enable-link-spam-detection: true
enable-ai-detection: true
+83
View File
@@ -0,0 +1,83 @@
name: Publish to MCP Registry
on:
push:
tags: ["v*"] # Triggers on version tags like v1.0.0
workflow_dispatch: # Allow manual triggering
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # Required for OIDC authentication
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: "stable"
- name: Fetch tags
run: |
if [[ "${{ github.ref_type }}" != "tag" ]]; then
git fetch --tags
else
echo "Skipping tag fetch - already on tag ${{ github.ref_name }}"
fi
- name: Wait for Docker image
run: |
if [[ "${{ github.ref_type }}" == "tag" ]]; then
TAG="${{ github.ref_name }}"
else
TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n1)
fi
IMAGE="ghcr.io/github/github-mcp-server:$TAG"
for i in {1..10}; do
if docker manifest inspect "$IMAGE" &>/dev/null; then
echo "✅ Docker image ready: $TAG"
break
fi
[ $i -eq 10 ] && { echo "❌ Timeout waiting for $TAG after 5 minutes"; exit 1; }
echo "⏳ Waiting for Docker image ($i/10)..."
sleep 30
done
- name: Install MCP Publisher
run: |
git clone --quiet https://github.com/modelcontextprotocol/registry publisher-repo
cd publisher-repo && make publisher > /dev/null && cd ..
cp publisher-repo/bin/mcp-publisher . && chmod +x mcp-publisher
- name: Update server.json version
run: |
if [[ "${{ github.ref_type }}" == "tag" ]]; then
TAG_VERSION=$(echo "${{ github.ref_name }}" | sed 's/^v//')
else
LATEST_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
[ -z "$LATEST_TAG" ] && { echo "No release tag found"; exit 1; }
TAG_VERSION=$(echo "$LATEST_TAG" | sed 's/^v//')
echo "Using latest tag: $LATEST_TAG"
fi
sed -i "s/\${VERSION}/$TAG_VERSION/g" server.json
echo "Version: $TAG_VERSION"
- name: Validate configuration
run: |
python3 -m json.tool server.json > /dev/null && echo "Configuration valid" || exit 1
- name: Display final server.json
run: |
echo "Final server.json contents:"
cat server.json
- name: Login to MCP Registry (OIDC)
run: ./mcp-publisher login github-oidc
- name: Publish to MCP Registry
run: ./mcp-publisher publish