Template
ci(mcp): add MCP-specific workflows — build validation, SDK check, tool inventory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# MCP Server Build & Validation
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Builds the MCP server, validates TypeScript compilation, and checks
|
||||
# that tools are properly registered with valid Zod schemas.
|
||||
|
||||
name: MCP Build & Validate
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, dev/**]
|
||||
paths: ['src/**', 'package.json', 'tsconfig.json']
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths: ['src/**', 'package.json', 'tsconfig.json']
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20, 22]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: TypeScript compile
|
||||
run: npx tsc --noEmit
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Verify dist output exists
|
||||
run: |
|
||||
test -f dist/index.js || (echo "ERROR: dist/index.js not found" && exit 1)
|
||||
test -f dist/client.js || (echo "ERROR: dist/client.js not found" && exit 1)
|
||||
test -f dist/config.js || (echo "ERROR: dist/config.js not found" && exit 1)
|
||||
test -f dist/types.js || (echo "ERROR: dist/types.js not found" && exit 1)
|
||||
echo "✓ All required dist files present"
|
||||
|
||||
- name: Verify shebang in index.js
|
||||
run: |
|
||||
head -1 dist/index.js | grep -q "#!/usr/bin/env node" || echo "WARNING: Missing shebang in dist/index.js"
|
||||
|
||||
- name: Count registered tools
|
||||
run: |
|
||||
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || true)
|
||||
echo "Registered tools: ${TOOL_COUNT}"
|
||||
if [ "${TOOL_COUNT}" -eq 0 ]; then
|
||||
echo "ERROR: No tools registered in src/index.ts"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,105 @@
|
||||
# MCP SDK Version Check
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Weekly check for MCP SDK updates. Creates an issue when a new version
|
||||
# of @modelcontextprotocol/sdk is available.
|
||||
|
||||
name: MCP SDK Version Check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 9 * * 1' # Every Monday at 9am UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-sdk:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Check for SDK updates
|
||||
id: sdk-check
|
||||
run: |
|
||||
CURRENT=$(node -p "require('./package.json').dependencies['@modelcontextprotocol/sdk']" | sed 's/[\^~]//')
|
||||
LATEST=$(npm view @modelcontextprotocol/sdk version 2>/dev/null || echo "unknown")
|
||||
|
||||
echo "current=${CURRENT}" >> $GITHUB_OUTPUT
|
||||
echo "latest=${LATEST}" >> $GITHUB_OUTPUT
|
||||
|
||||
if [ "${CURRENT}" != "${LATEST}" ] && [ "${LATEST}" != "unknown" ]; then
|
||||
echo "update_available=true" >> $GITHUB_OUTPUT
|
||||
echo "MCP SDK update available: ${CURRENT} → ${LATEST}"
|
||||
else
|
||||
echo "update_available=false" >> $GITHUB_OUTPUT
|
||||
echo "MCP SDK is up to date: ${CURRENT}"
|
||||
fi
|
||||
|
||||
- name: Check for Zod updates
|
||||
id: zod-check
|
||||
run: |
|
||||
CURRENT=$(node -p "require('./package.json').dependencies['zod']" | sed 's/[\^~]//')
|
||||
LATEST=$(npm view zod version 2>/dev/null || echo "unknown")
|
||||
|
||||
echo "current=${CURRENT}" >> $GITHUB_OUTPUT
|
||||
echo "latest=${LATEST}" >> $GITHUB_OUTPUT
|
||||
|
||||
if [ "${CURRENT}" != "${LATEST}" ] && [ "${LATEST}" != "unknown" ]; then
|
||||
echo "update_available=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "update_available=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Create update issue
|
||||
if: steps.sdk-check.outputs.update_available == 'true'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const title = `chore(deps): update @modelcontextprotocol/sdk ${process.env.CURRENT} → ${process.env.LATEST}`;
|
||||
const body = [
|
||||
'## MCP SDK Update Available',
|
||||
'',
|
||||
`| Package | Current | Latest |`,
|
||||
`|---------|---------|--------|`,
|
||||
`| @modelcontextprotocol/sdk | ${process.env.CURRENT} | ${process.env.LATEST} |`,
|
||||
`| zod | ${process.env.ZOD_CURRENT} | ${process.env.ZOD_LATEST} |`,
|
||||
'',
|
||||
'### Steps',
|
||||
'1. Update package.json',
|
||||
'2. Run `npm install`',
|
||||
'3. Run `npm run build` to verify compilation',
|
||||
'4. Test all tools against target API',
|
||||
'',
|
||||
'### Changelog',
|
||||
`https://github.com/modelcontextprotocol/typescript-sdk/releases`,
|
||||
].join('\n');
|
||||
|
||||
// Check for existing open issue
|
||||
const existing = await github.rest.issues.listForRepo({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
state: 'open',
|
||||
labels: 'api-change',
|
||||
});
|
||||
|
||||
const alreadyExists = existing.data.some(i => i.title.includes('@modelcontextprotocol/sdk'));
|
||||
if (!alreadyExists) {
|
||||
await github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title,
|
||||
body,
|
||||
labels: ['api-change', 'chore'],
|
||||
});
|
||||
}
|
||||
env:
|
||||
CURRENT: ${{ steps.sdk-check.outputs.current }}
|
||||
LATEST: ${{ steps.sdk-check.outputs.latest }}
|
||||
ZOD_CURRENT: ${{ steps.zod-check.outputs.current }}
|
||||
ZOD_LATEST: ${{ steps.zod-check.outputs.latest }}
|
||||
@@ -0,0 +1,57 @@
|
||||
# MCP Tool Inventory
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Generates a tool inventory report on each push to main.
|
||||
# Extracts tool names, descriptions, and parameter counts from src/index.ts.
|
||||
|
||||
name: MCP Tool Inventory
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths: ['src/index.ts']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
inventory:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Generate tool inventory
|
||||
run: |
|
||||
echo "# MCP Tool Inventory" > TOOLS.md
|
||||
echo "" >> TOOLS.md
|
||||
echo "Auto-generated from \`src/index.ts\` on $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> TOOLS.md
|
||||
echo "" >> TOOLS.md
|
||||
|
||||
# Count tools
|
||||
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || true)
|
||||
echo "**Total tools: ${TOOL_COUNT}**" >> TOOLS.md
|
||||
echo "" >> TOOLS.md
|
||||
|
||||
# Extract tool names and descriptions
|
||||
echo "| Tool | Description |" >> TOOLS.md
|
||||
echo "|------|-------------|" >> TOOLS.md
|
||||
|
||||
grep -A1 "server\.tool(" src/index.ts | grep -E "^\s*'" | while read -r line; do
|
||||
TOOL_NAME=$(echo "$line" | sed "s/.*'\([^']*\)'.*/\1/")
|
||||
# Get next line for description
|
||||
DESC=$(grep -A2 "'${TOOL_NAME}'" src/index.ts | grep -E "^\s*'" | tail -1 | sed "s/.*'\([^']*\)'.*/\1/" || echo "")
|
||||
echo "| \`${TOOL_NAME}\` | ${DESC} |" >> TOOLS.md
|
||||
done
|
||||
|
||||
echo "" >> TOOLS.md
|
||||
echo "---" >> TOOLS.md
|
||||
echo "*Generated by MCP Tool Inventory workflow*" >> TOOLS.md
|
||||
|
||||
cat TOOLS.md
|
||||
|
||||
- name: Upload inventory artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: tool-inventory
|
||||
path: TOOLS.md
|
||||
retention-days: 90
|
||||
Reference in New Issue
Block a user