Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,35 @@ updates:
schedule:
interval: "weekly"
groups:
production-dependencies:
runtime-dependencies:
dependency-type: "production"
toolchain:
dependency-type: "development"
patterns:
- "*"
exclude-patterns:
- "@eslint/js"
- "@types/*"
- "typescript"
- "vitest"
- "eslint*"
- "@vitest/coverage-v8"
- "eslint"
- "eslint-config-prettier"
- "prettier"
dev-dependencies:
patterns:
- "@types/*"
- "tsx"
- "typescript"
- "typescript-eslint"
- "vitest"
- "eslint*"
- "prettier"
ignore:
# Major bumps for coupled toolchain packages need manual coordination
- dependency-name: "typescript"
update-types: ["version-update:semver-major"]
- dependency-name: "typescript-eslint"
update-types: ["version-update:semver-major"]
- dependency-name: "eslint"
update-types: ["version-update:semver-major"]
- dependency-name: "@eslint/*"
update-types: ["version-update:semver-major"]
- dependency-name: "vitest"
update-types: ["version-update:semver-major"]
- dependency-name: "@vitest/*"
update-types: ["version-update:semver-major"]
commit-message:
prefix: "chore(deps)"
open-pull-requests-limit: 10
39 changes: 39 additions & 0 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Dependabot auto-merge

on:
pull_request_target:
types:
- opened
- reopened
- synchronize
- ready_for_review

permissions:
contents: write
pull-requests: write

jobs:
auto-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Fetch Dependabot metadata
id: meta
uses: dependabot/fetch-metadata@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Approve and enable auto-merge
if: |
steps.meta.outputs.update-type != 'version-update:semver-major' ||
steps.meta.outputs.package-ecosystem == 'github_actions'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_URL: ${{ github.event.pull_request.html_url }}
run: |
CURRENT_LOGIN="$(gh api user --jq .login)"
ALREADY_APPROVED="$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews" --jq '[.[] | select(.user.login == "'"$CURRENT_LOGIN"'" and .state == "APPROVED")] | length')"
if [ "$ALREADY_APPROVED" -eq 0 ]; then
gh pr review --approve "$PR_URL"
fi
gh pr merge --auto --squash "$PR_URL"
35 changes: 35 additions & 0 deletions .github/workflows/pr-title.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: PR Title

on:
pull_request_target:
types:
- opened
- edited
- reopened
- synchronize

permissions:
pull-requests: read

jobs:
conventional-pr-title:
if: ${{ github.event.pull_request.base.ref == 'main' }}
runs-on: ubuntu-latest
steps:
- name: Validate conventional PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
pattern='^(feat|fix|docs|chore|refactor|test|perf|build|ci|revert)(\([[:alnum:]_.-]+\))?!?: .+'

if [[ "$PR_TITLE" =~ $pattern ]]; then
echo "PR title is valid: $PR_TITLE"
exit 0
fi

echo "PR title must use Conventional Commits because squash merges become release-please input."
echo "Allowed prefixes: feat, fix, docs, chore, refactor, test, perf, build, ci, revert"
echo "Examples:"
echo " fix: harden push approval auth flow"
echo " feat(auth): add TOTP support"
exit 1
35 changes: 14 additions & 21 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@
# chore/docs: no version bump
#
# npm Publishing:
# Uses Trusted Publishing (OIDC) - no secrets needed!
# Uses Trusted Publishing (OIDC) - no NPM_TOKEN needed!
# Requires Node 24+ for npm 11.5.1+ OIDC support.
# Configure at: https://www.npmjs.com/package/@verygoodplugins/mcp-{name}/access
#
# RELEASE_PLEASE_TOKEN:
# Uses org-level PAT so the Release PR triggers CI workflows.
# PRs created by GITHUB_TOKEN don't trigger other workflows (GitHub security).

name: Release Please

Expand All @@ -39,12 +44,15 @@ jobs:
- uses: googleapis/release-please-action@v4
id: release
with:
release-type: node
manifest-file: ".release-please-manifest.json"
config-file: "release-please-config.json"
Comment on lines +47 to +48

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

release-please-action is configured to use manifest-file and config-file, but neither .release-please-manifest.json nor release-please-config.json exists in the repository. This will cause the workflow to fail at runtime; add these files (or revert to release-type: node config) before merging.

Suggested change
manifest-file: ".release-please-manifest.json"
config-file: "release-please-config.json"
release-type: node

Copilot uses AI. Check for mistakes.
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow now requires secrets.RELEASE_PLEASE_TOKEN. If this secret isn’t configured for the repo/org, releases will stop working. Consider falling back to GITHUB_TOKEN when the secret is absent, or document/enforce provisioning of RELEASE_PLEASE_TOKEN as part of the template sync.

Suggested change
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
token: ${{ secrets.RELEASE_PLEASE_TOKEN || github.token }}

Copilot uses AI. Check for mistakes.

npm-publish:
needs: release-please
if: ${{ needs.release-please.outputs.release_created }}
runs-on: ubuntu-latest
environment: npm
permissions:
contents: read
id-token: write
Expand All @@ -53,28 +61,13 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "24"
registry-url: "https://registry.npmjs.org"

- run: npm ci
# Use npm install for cross-version lockfile compatibility
- run: npm install
- run: npm run build
- run: npm test

# Trusted Publishing: No NPM_TOKEN needed!
- run: npm publish --access public --provenance

announce:
needs: [release-please, npm-publish]
if: ${{ needs.release-please.outputs.release_created }}
runs-on: ubuntu-latest
steps:
- name: Post to Slack
if: ${{ vars.SLACK_WEBHOOK_URL }}
uses: slackapi/slack-github-action@v1
with:
webhook-url: ${{ vars.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload: |
{
"text": "🚀 ${{ github.repository }} ${{ needs.release-please.outputs.tag_name }} released!\n\nhttps://github.com/${{ github.repository }}/releases/tag/${{ needs.release-please.outputs.tag_name }}"
}
- run: npm publish --provenance --access public
6 changes: 3 additions & 3 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ jobs:
- uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: typescript

- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4

audit:
name: Dependency Audit
Expand Down
4 changes: 2 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}

26 changes: 26 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// ESLint flat config for VGP MCP servers
// Requires: eslint ^9.0.0, typescript-eslint ^8.0.0
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['src/**/*.ts'],
rules: {
// MCP stdio servers must not write to stdout outside the protocol.
'no-console': ['error', { allow: ['error', 'warn'] }],
// Allow unused vars prefixed with underscore
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
// Allow explicit any in some cases (MCP tools often need flexibility)
'@typescript-eslint/no-explicit-any': 'warn',
},
},
{
ignores: ['dist/', 'node_modules/', '**/*.js', '**/*.mjs', '**/*.cjs'],
}
);
Comment on lines +1 to +26

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repo already has an eslint.config.js flat config. Adding a second flat config (eslint.config.mjs) with different rule/plugin settings is likely to cause confusion about which config is authoritative (ESLint will prefer eslint.config.js by default). Consider removing this file or replacing the existing config in a single location.

Suggested change
// ESLint flat config for VGP MCP servers
// Requires: eslint ^9.0.0, typescript-eslint ^8.0.0
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['src/**/*.ts'],
rules: {
// MCP stdio servers must not write to stdout outside the protocol.
'no-console': ['error', { allow: ['error', 'warn'] }],
// Allow unused vars prefixed with underscore
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
],
// Allow explicit any in some cases (MCP tools often need flexibility)
'@typescript-eslint/no-explicit-any': 'warn',
},
},
{
ignores: ['dist/', 'node_modules/', '**/*.js', '**/*.mjs', '**/*.cjs'],
}
);
// Delegate to the repository's authoritative ESLint flat config.
import config from './eslint.config.js';
export default config;

Copilot uses AI. Check for mistakes.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@
"mysql2": "^3.6.5"
},
"devDependencies": {
"@eslint/js": "^9.39.2",
"@types/node": "^18.0.0",
"@eslint/js": "^9.18.0",
"@types/node": "^22.10.5",
"@typescript-eslint/eslint-plugin": "^8.50.1",
"@typescript-eslint/parser": "^8.50.1",
"eslint": "^9.39.0",
"eslint-config-prettier": "^10.1.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-unused-imports": "^4.3.0",
"globals": "^16.0.0",
"prettier": "^3.7.4",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.50.1"
"prettier": "^3.4.2",
"tsx": "^4.19.2",
"typescript": "^5.7.3",
"typescript-eslint": "^8.20.0"
Comment on lines +59 to +70

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package.json updates multiple devDependency versions, but package-lock.json is not updated accordingly. Because CI/security workflows use npm ci, the install will fail due to lockfile/package.json mismatch; regenerate and commit an updated package-lock.json for these version changes.

Copilot uses AI. Check for mistakes.

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typescript-eslint is pinned to ^8.20.0 while @typescript-eslint/eslint-plugin/@typescript-eslint/parser are ^8.50.1. These packages are typically version-coupled; mixing versions can cause ESLint config/runtime incompatibilities. Align the typescript-eslint and @typescript-eslint/* package versions to the same release line.

Suggested change
"typescript-eslint": "^8.20.0"
"typescript-eslint": "^8.50.1"

Copilot uses AI. Check for mistakes.
}
}
13 changes: 13 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
globals: true,
environment: 'node',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: ['node_modules/', 'dist/', 'tests/', '*.config.*'],
},
},
});
Comment on lines +1 to +13

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A vitest.config.ts is added, but the repo doesn’t declare vitest (or @vitest/coverage-v8) in dependencies and npm test does not invoke Vitest. Either add the required devDependencies and scripts (e.g., test/test:coverage) or remove the unused config to avoid confusion.

Suggested change
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: ['node_modules/', 'dist/', 'tests/', '*.config.*'],
},
},
});
// Vitest configuration was removed because the repository does not declare
// the required Vitest dependencies or invoke Vitest from its test scripts.
// Leaving a live `vitest.config.ts` in place would be misleading.
export {};

Copilot uses AI. Check for mistakes.
Loading