# MCP Index Management Workflow Template
# This workflow manages code index artifacts for your repository
# Generated by mcp-index-kit
name: MCP Index Management
on:
push:
branches: [{{DEFAULT_BRANCH}}]
pull_request:
types: [opened, synchronize, reopened]
schedule:
- cron: '0 0 * * 0' # Weekly rebuild
workflow_dispatch:
inputs:
rebuild:
description: 'Force rebuild index'
type: boolean
default: false
env:
MCP_INDEX_ENABLED: ${{ vars.MCP_INDEX_ENABLED || 'true' }}
MCP_INDEX_VERSION: '{{MCP_VERSION}}'
jobs:
check-enabled:
runs-on: ubuntu-latest
outputs:
enabled: ${{ steps.check.outputs.enabled }}
steps:
- id: check
run: |
if [ "${{ env.MCP_INDEX_ENABLED }}" = "false" ]; then
echo "MCP indexing is disabled"
echo "enabled=false" >> $GITHUB_OUTPUT
else
echo "enabled=true" >> $GITHUB_OUTPUT
fi
download-existing-index:
needs: check-enabled
if: needs.check-enabled.outputs.enabled == 'true' && github.event_name != 'schedule'
runs-on: ubuntu-latest
outputs:
index-found: ${{ steps.download.outputs.found }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Try to download latest index artifact
id: download
run: |
echo "Checking for existing index artifacts..."
# Try to download the most recent index artifact
ARTIFACT_NAME="mcp-index-${{ github.event.pull_request.head.sha || github.sha }}"
# Use GitHub API to check for artifacts
ARTIFACTS=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/${{ github.repository }}/actions/artifacts \
--jq '.artifacts[] | select(.name | startswith("mcp-index-")) | .name' \
| head -1)
if [ -n "$ARTIFACTS" ]; then
echo "Found existing artifact: $ARTIFACTS"
gh run download --name "$ARTIFACTS" --dir .mcp-index-download || true
if [ -d ".mcp-index-download" ]; then
cd .mcp-index-download
tar -xzf mcp-index-archive.tar.gz -C ../.mcp-index/
cd ..
echo "found=true" >> $GITHUB_OUTPUT
else
echo "found=false" >> $GITHUB_OUTPUT
fi
else
echo "No existing artifacts found"
echo "found=false" >> $GITHUB_OUTPUT
fi
env:
GH_TOKEN: ${{ github.token }}
build-index:
needs: [check-enabled, download-existing-index]
if: |
needs.check-enabled.outputs.enabled == 'true' &&
(needs.download-existing-index.outputs.index-found != 'true' ||
github.event_name == 'schedule' ||
github.event.inputs.rebuild == 'true')
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Cache MCP indexer
id: cache-indexer
uses: actions/cache@v3
with:
path: ~/.mcp/indexer
key: mcp-indexer-${{ env.MCP_INDEX_VERSION }}
- name: Download MCP Indexer
if: steps.cache-indexer.outputs.cache-hit != 'true'
run: |
mkdir -p ~/.mcp/indexer
curl -L https://github.com/yourusername/Code-Index-MCP/releases/download/v${{ env.MCP_INDEX_VERSION }}/mcp-portable-indexer.pyz \
-o ~/.mcp/indexer/mcp-indexer.pyz
chmod +x ~/.mcp/indexer/mcp-indexer.pyz
- name: Build Index
run: |
# Create index directory
mkdir -p .mcp-index
# Check if config exists
if [ -f ".mcp-index.json" ]; then
CONFIG_FLAG="--config .mcp-index.json"
else
CONFIG_FLAG=""
fi
# Check if ignore file exists
if [ -f ".mcp-index-ignore" ]; then
IGNORE_FLAG="--ignore-file .mcp-index-ignore"
else
IGNORE_FLAG=""
fi
# Run the indexer
python ~/.mcp/indexer/mcp-indexer.pyz build \
$CONFIG_FLAG \
$IGNORE_FLAG \
--output .mcp-index/code_index.db \
--stats
- name: Create index metadata
run: |
cat > .mcp-index/.index_metadata.json <<EOF
{
"version": "${{ env.MCP_INDEX_VERSION }}",
"created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"commit": "${{ github.sha }}",
"branch": "${{ github.ref_name }}",
"repository": "${{ github.repository }}",
"workflow_run": "${{ github.run_id }}",
"indexed_files": $(find . -type f | wc -l),
"index_size_bytes": $(stat -c%s .mcp-index/code_index.db 2>/dev/null || echo 0)
}
EOF
- name: Compress index for artifact
run: |
cd .mcp-index
tar -czf ../mcp-index-archive.tar.gz .
cd ..
# Calculate checksum
sha256sum mcp-index-archive.tar.gz > mcp-index-archive.tar.gz.sha256
- name: Upload index artifact
uses: actions/upload-artifact@v4
with:
name: mcp-index-${{ github.sha }}
path: |
mcp-index-archive.tar.gz
mcp-index-archive.tar.gz.sha256
retention-days: ${{ github.event_name == 'push' && 30 || 7 }}
- name: Upload index for PRs
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: mcp-index-pr-${{ github.event.pull_request.number }}
path: |
mcp-index-archive.tar.gz
mcp-index-archive.tar.gz.sha256
retention-days: 7
validate-index:
needs: build-index
if: needs.check-enabled.outputs.enabled == 'true'
runs-on: ubuntu-latest
steps:
- name: Download index artifact
uses: actions/download-artifact@v4
with:
name: mcp-index-${{ github.sha }}
- name: Verify checksum
run: |
sha256sum -c mcp-index-archive.tar.gz.sha256
- name: Extract and validate
run: |
mkdir -p validation
tar -xzf mcp-index-archive.tar.gz -C validation/
# Basic validation
if [ ! -f "validation/code_index.db" ]; then
echo "Error: code_index.db not found in artifact"
exit 1
fi
if [ ! -f "validation/.index_metadata.json" ]; then
echo "Error: .index_metadata.json not found in artifact"
exit 1
fi
# Check file size
INDEX_SIZE=$(stat -c%s validation/code_index.db)
if [ $INDEX_SIZE -lt 1024 ]; then
echo "Warning: Index seems too small ($INDEX_SIZE bytes)"
fi
echo "Index validation passed"
cleanup-old-artifacts:
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
steps:
- name: Cleanup old artifacts
uses: actions/github-script@v6
with:
script: |
const artifacts = await github.rest.actions.listArtifactsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - 30);
let deletedCount = 0;
for (const artifact of artifacts.data.artifacts) {
if (artifact.name.startsWith('mcp-index-') &&
new Date(artifact.created_at) < cutoffDate) {
await github.rest.actions.deleteArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id
});
deletedCount++;
console.log(`Deleted old artifact: ${artifact.name}`);
}
}
console.log(`Total artifacts deleted: ${deletedCount}`);
update-pr-comment:
needs: [build-index, validate-index]
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Download metadata
uses: actions/download-artifact@v4
with:
name: mcp-index-${{ github.sha }}
- name: Extract metadata
id: metadata
run: |
tar -xzf mcp-index-archive.tar.gz .index_metadata.json
# Read metadata
INDEXED_FILES=$(jq -r '.indexed_files' .index_metadata.json)
INDEX_SIZE=$(jq -r '.index_size_bytes' .index_metadata.json)
INDEX_SIZE_MB=$(echo "scale=2; $INDEX_SIZE / 1048576" | bc)
echo "indexed_files=$INDEXED_FILES" >> $GITHUB_OUTPUT
echo "index_size_mb=$INDEX_SIZE_MB" >> $GITHUB_OUTPUT
- name: Update PR comment
uses: actions/github-script@v6
with:
script: |
const comment = `## 📚 MCP Index Build Complete
✅ Successfully built code index for this PR
**Index Statistics:**
- 📁 Indexed files: ${{ steps.metadata.outputs.indexed_files }}
- 💾 Index size: ${{ steps.metadata.outputs.index_size_mb }} MB
- 🏷️ Artifact: \`mcp-index-pr-${{ github.event.pull_request.number }}\`
The index will be available for 7 days and can be downloaded for local development.
`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('MCP Index Build Complete')
);
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: comment
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}