Skip to content

Commit 1ea87ca

Browse files
committed
fix(scaffold): add mcp-server type templates and branch workflow generation
Scaffold was generating cursor-plugin workflows unconditionally for all repo types. An mcp-server scaffold produced: an empty validate.yml jobs block, a release.yml that required .cursor-plugin/plugin.json, and a pages.yml that invoked build_site.py. Add six new templates for the mcp-server type path: - validate.mcp.yml.j2: required-files check (README, CHANGELOG, AGENTS, CLAUDE, mcp-tools.json, site.json, LICENSE) - release.mcp.yml.j2: simplified tag-from-package.json release workflow - pages.mcp.yml.j2: static docs/ artifact deploy (no build_site.py) - publish.yml.j2: npm publish on release event - package.json.j2: parametrized Node package manifest - docs/index.mcp.html.j2: placeholder GitHub Pages landing page Branch create-tool.py workflow generation on args.type so mcp-server repos get the four mcp-server workflows and cursor-plugin repos continue to get validate, release, pages unchanged. Also generate package.json and docs/index.html for mcp-server type repos. Verified: freshly scaffolded mcp-server passes YAML validation for all seven workflow files and is mutually consistent with zero hand-fixing. Cursor-plugin output is byte-for-byte unchanged. Signed-off-by: fOuttaMyPaint <154358121+TMHSDigital@users.noreply.github.com>
1 parent b3614c9 commit 1ea87ca

7 files changed

Lines changed: 221 additions & 4 deletions

File tree

scaffold/create-tool.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,16 @@ def main():
178178
if args.type == "cursor-plugin":
179179
write_file(output_dir, ".cursor-plugin/plugin.json", render_template(env, "plugin.json.j2", ctx))
180180

181-
# GitHub workflows
182-
write_file(output_dir, ".github/workflows/validate.yml", render_template(env, "validate.yml.j2", ctx))
183-
write_file(output_dir, ".github/workflows/release.yml", render_template(env, "release.yml.j2", ctx))
184-
write_file(output_dir, ".github/workflows/pages.yml", render_template(env, "pages.yml.j2", ctx))
181+
# GitHub workflows — branched by type
182+
if args.type == "mcp-server":
183+
write_file(output_dir, ".github/workflows/validate.yml", render_template(env, "validate.mcp.yml.j2", ctx))
184+
write_file(output_dir, ".github/workflows/release.yml", render_template(env, "release.mcp.yml.j2", ctx))
185+
write_file(output_dir, ".github/workflows/pages.yml", render_template(env, "pages.mcp.yml.j2", ctx))
186+
write_file(output_dir, ".github/workflows/publish.yml", render_template(env, "publish.yml.j2", ctx))
187+
else:
188+
write_file(output_dir, ".github/workflows/validate.yml", render_template(env, "validate.yml.j2", ctx))
189+
write_file(output_dir, ".github/workflows/release.yml", render_template(env, "release.yml.j2", ctx))
190+
write_file(output_dir, ".github/workflows/pages.yml", render_template(env, "pages.yml.j2", ctx))
185191
write_file(output_dir, ".github/workflows/stale.yml", render_template(env, "stale.yml.j2", ctx))
186192
write_file(output_dir, ".github/workflows/drift-check.yml", render_template(env, "drift-check.yml.j2", ctx))
187193
write_file(output_dir, ".github/workflows/label-sync.yml", render_template(env, "label-sync.yml.j2", ctx))
@@ -213,6 +219,11 @@ def main():
213219
(output_dir / "assets" / ".gitkeep").touch()
214220
print(" created assets/.gitkeep")
215221

222+
# MCP server specific files
223+
if args.type == "mcp-server":
224+
write_file(output_dir, "package.json", render_template(env, "package.json.j2", ctx))
225+
write_file(output_dir, "docs/index.html", render_template(env, "docs/index.mcp.html.j2", ctx))
226+
216227
# Skills
217228
for skill in skill_names:
218229
skill_content = f"""---
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>{{ name }}</title>
7+
<style>
8+
body { font-family: system-ui, sans-serif; background: #0d1117; color: #e6edf3; margin: 0; padding: 2rem; }
9+
h1 { color: #7c3aed; }
10+
a { color: #a78bfa; }
11+
</style>
12+
</head>
13+
<body>
14+
<h1>{{ name }}</h1>
15+
<p>{{ description }}</p>
16+
<p>Full documentation will be available here once the server implementation is complete.</p>
17+
<p><a href="https://github.com/{{ repo_owner }}/{{ slug }}">View on GitHub</a></p>
18+
</body>
19+
</html>

scaffold/templates/package.json.j2

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "@{{ repo_owner | lower }}/{{ slug }}",
3+
"version": "0.1.0",
4+
"description": "{{ description }}",
5+
"type": "module",
6+
"main": "dist/index.js",
7+
"bin": {"{{ slug }}": "dist/index.js"},
8+
"files": ["dist", "README.md", "LICENSE"],
9+
"scripts": {
10+
"build": "echo 'No build target yet'",
11+
"test": "echo 'No tests yet' && exit 0",
12+
"prepublishOnly": "npm run build"
13+
},
14+
"author": "{{ author_name }}",
15+
"license": "{{ license_spdx }}",
16+
"repository": {"type": "git", "url": "git+https://github.com/{{ repo_owner }}/{{ slug }}.git"},
17+
"homepage": "https://github.com/{{ repo_owner }}/{{ slug }}#readme",
18+
"bugs": {"url": "https://github.com/{{ repo_owner }}/{{ slug }}/issues"},
19+
"keywords": ["mcp", "model-context-protocol", "developer-tools"],
20+
"engines": {"node": ">=20.0.0"}
21+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Deploy GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "docs/**"
8+
- "assets/**"
9+
workflow_dispatch:
10+
11+
permissions:
12+
pages: write
13+
id-token: write
14+
15+
concurrency:
16+
group: pages
17+
cancel-in-progress: true
18+
19+
jobs:
20+
deploy:
21+
{% raw %}
22+
environment:
23+
name: github-pages
24+
url: ${{ steps.deployment.outputs.page_url }}
25+
{% endraw %}
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v6
29+
30+
- uses: actions/configure-pages@v6
31+
32+
- uses: actions/upload-pages-artifact@v5
33+
with:
34+
path: docs
35+
36+
- uses: actions/deploy-pages@v5
37+
id: deployment

scaffold/templates/publish.yml.j2

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Publish to npm
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
permissions:
8+
contents: read
9+
id-token: write
10+
11+
jobs:
12+
publish:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v6
16+
- uses: actions/setup-node@v6
17+
with:
18+
node-version: 22
19+
registry-url: https://registry.npmjs.org
20+
cache: npm
21+
- run: npm install -g npm@latest
22+
- run: npm ci
23+
- run: npm run build
24+
- run: npm test
25+
{% raw %}
26+
- run: npm publish --provenance --access public
27+
env:
28+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
29+
{% endraw %}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch: {}
7+
8+
permissions:
9+
contents: write
10+
11+
concurrency:
12+
group: release
13+
cancel-in-progress: false
14+
15+
jobs:
16+
tag-and-release:
17+
name: Tag and release
18+
runs-on: ubuntu-latest
19+
{% raw %}
20+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
21+
steps:
22+
23+
- uses: actions/checkout@v6
24+
with:
25+
fetch-depth: 0
26+
token: ${{ secrets.GITHUB_TOKEN }}
27+
28+
- name: Read version from package.json
29+
id: ver
30+
run: |
31+
version=$(python3 -c "import json; print(json.load(open('package.json'))['version'])")
32+
echo "version=$version" >> "$GITHUB_OUTPUT"
33+
echo "Version from package.json: $version"
34+
35+
- name: Check if tag already exists
36+
id: check
37+
run: |
38+
version="${{ steps.ver.outputs.version }}"
39+
if git rev-parse "v$version" >/dev/null 2>&1; then
40+
echo "skip=true" >> "$GITHUB_OUTPUT"
41+
echo "Tag v$version already exists, skipping release"
42+
else
43+
echo "skip=false" >> "$GITHUB_OUTPUT"
44+
echo "Tag v$version does not exist, proceeding"
45+
fi
46+
47+
- name: Create and push tags
48+
if: steps.check.outputs.skip == 'false'
49+
run: |
50+
version="${{ steps.ver.outputs.version }}"
51+
IFS='.' read -r major minor _patch <<< "$version"
52+
53+
git config user.name "github-actions[bot]"
54+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
55+
56+
git tag "v$version"
57+
git tag -f "v$major"
58+
git tag -f "v$major.$minor"
59+
60+
git push origin "v$version"
61+
git push origin "v$major" --force
62+
git push origin "v$major.$minor" --force
63+
64+
- name: Create GitHub Release
65+
if: steps.check.outputs.skip == 'false'
66+
env:
67+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
68+
run: |
69+
gh release create "v${{ steps.ver.outputs.version }}" \
70+
--title "v${{ steps.ver.outputs.version }}" \
71+
--generate-notes
72+
{% endraw %}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Validate
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
required-files:
14+
name: Check required files
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v6
18+
- name: Verify required files exist
19+
run: |
20+
missing=0
21+
for f in README.md CHANGELOG.md AGENTS.md CLAUDE.md mcp-tools.json site.json LICENSE; do
22+
if [ ! -f "$f" ]; then
23+
echo "Missing: $f"
24+
missing=1
25+
fi
26+
done
27+
if [ $missing -eq 1 ]; then exit 1; fi
28+
echo "All required files present"

0 commit comments

Comments
 (0)