diff --git a/.gitea/workflows/mcp-build-test.yml b/.gitea/workflows/mcp-build-test.yml new file mode 100644 index 0000000..cb631c7 --- /dev/null +++ b/.gitea/workflows/mcp-build-test.yml @@ -0,0 +1,61 @@ +# MCP Server Build & Validation +# Copyright (C) 2026 Moko Consulting +# 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 diff --git a/.gitea/workflows/mcp-sdk-check.yml b/.gitea/workflows/mcp-sdk-check.yml new file mode 100644 index 0000000..b926cd3 --- /dev/null +++ b/.gitea/workflows/mcp-sdk-check.yml @@ -0,0 +1,105 @@ +# MCP SDK Version Check +# Copyright (C) 2026 Moko Consulting +# 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 }} diff --git a/.gitea/workflows/mcp-tool-inventory.yml b/.gitea/workflows/mcp-tool-inventory.yml new file mode 100644 index 0000000..f935b0c --- /dev/null +++ b/.gitea/workflows/mcp-tool-inventory.yml @@ -0,0 +1,57 @@ +# MCP Tool Inventory +# Copyright (C) 2026 Moko Consulting +# 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