name: Vercel MCP-Deploy
on:
push:
branches:
- release/3
paths:
- '.github/workflows/mcp-vercel.yml'
- 'packages/samples/react/**'
- 'packages/tools/mcp/**'
- 'packages/components/**'
pull_request:
paths:
- '.github/workflows/mcp-vercel.yml'
- 'packages/components/**'
- 'packages/samples/react/**'
- 'packages/tools/mcp/**'
workflow_dispatch:
concurrency:
group: 'mcp-vercel-${{ github.ref }}'
cancel-in-progress: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
env:
PNPM_CACHE_FOLDER: .pnpm
VERCEL_ORG_ID: ${{ secrets.VERCEL_MCP_TEAM_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_MCP_PROJECT_ID }}
VERCEL_TOKEN: ${{ secrets.VERCEL_MCP_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- name: Setup pnpm workspace
uses: ./.github/actions/pnpm-setup
- name: Build MCP dependencies
run: |
echo "π§± Building MCP workspace dependencies..."
pnpm --filter @public-ui/mcp run build:deps
- name: Build MCP package
run: |
echo "π¨ Building MCP package..."
pnpm --filter @public-ui/mcp build
- name: Verify MCP build artifacts
working-directory: packages/tools/mcp
run: |
echo "π Checking built artifacts..."
echo "Dist directory contents:"
ls -la dist/ || echo "No dist directory found!"
echo ""
echo "Checking for required files:"
test -f dist/data.mjs && echo "β
dist/data.mjs exists" || echo "β dist/data.mjs missing"
test -f dist/search.mjs && echo "β
dist/search.mjs exists" || echo "β dist/search.mjs missing"
test -f dist/mcp.mjs && echo "β
dist/mcp.mjs exists" || echo "β dist/mcp.mjs missing"
test -f shared/sample-index.json && echo "β
shared/sample-index.json exists" || echo "β shared/sample-index.json missing"
echo ""
echo "Sample index stats:"
jq '.entries | length' shared/sample-index.json || echo "Could not read sample-index.json"
echo ""
echo "API directory:"
ls -la api/ || echo "No API directory found!"
- name: Strip workspace-only dependencies for Vercel
working-directory: packages/tools/mcp
run: |
echo "π§Ή Preparing package.json for Vercel..."
node <<'NODE'
const fs = require('fs');
const path = require('path');
const pkgPath = path.resolve('package.json');
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
if (pkg.dependencies && pkg.dependencies['@public-ui/components']) {
console.log('Removing @public-ui/components dependency before deployment');
delete pkg.dependencies['@public-ui/components'];
fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
} else {
console.log('No @public-ui/components dependency found; nothing to strip.');
}
NODE
pnpm exec prettier --write package.json
- name: Deploy to Vercel (production)
id: deploy_prod
if: github.ref == 'refs/heads/release/3' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
working-directory: packages/tools/mcp
run: |
set -eo pipefail
echo "π Deploying pre-built package to Vercel..."
DEPLOY_URL=$(pnpm dlx vercel@latest deploy --prod --yes --token "$VERCEL_TOKEN" | tail -n1)
echo "url=${DEPLOY_URL}" >> "$GITHUB_OUTPUT"
echo "Production deployment available at ${DEPLOY_URL}"
- name: Deploy to Vercel (preview)
id: deploy_preview
if: github.event_name == 'pull_request'
working-directory: packages/tools/mcp
run: |
set -eo pipefail
echo "π Deploying pre-built package to Vercel..."
DEPLOY_URL=$(pnpm dlx vercel@latest deploy --yes --token "$VERCEL_TOKEN" | tail -n1)
echo "url=${DEPLOY_URL}" >> "$GITHUB_OUTPUT"
echo "Preview deployment available at ${DEPLOY_URL}"
- name: Share preview URL in PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
env:
PREVIEW_URL: ${{ steps.deploy_preview.outputs.url }}
with:
script: |
const marker = '<!-- mcp-vercel-preview -->';
const url = process.env.PREVIEW_URL;
if (!url) {
core.setFailed('Missing Vercel preview URL');
return;
}
const body = `${marker}\nπ MCP preview deployed to Vercel: ${url}`;
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number,
});
const existing = comments.find((comment) => comment.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number,
body,
});
}