From 9030359b3c8dfba4dc8eba646fd59d33aaeb83a4 Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 18 Oct 2026 15:06:42 +0000 Subject: [PATCH 1/5] feat(registry): add MCP Server Registry manifest, ownership labels, and publish step (#188) Add server.json for io.github.hyperpolymath/boj-server per owner ruling D146 (boj-server#188): - server.json: official MCP Registry 2025-12-11 schema manifest declaring the @hyperpolymath/boj-server npm stdio package and BoJ bridge/cartridge environment variables - package.json: add mcpName for npm ownership verification and include server.json in published files - Containerfile, container/Containerfile, .github/workflows/container-publish.yml: add io.modelcontextprotocol.server.name OCI label - .github/workflows/publish.yml: verify server.json version/name alignment on v* tags and publish via mcp-publisher with GitHub OIDC - mcp-bridge/tests/dispatch_test.js: add coherence test for server.json, package.json, and jsr.json Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .github/workflows/container-publish.yml | 1 + .github/workflows/publish.yml | 34 +++++++- Containerfile | 3 +- container/Containerfile | 1 + mcp-bridge/tests/dispatch_test.js | 36 +++++++++ package.json | 2 + server.json | 103 ++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 server.json diff --git a/.github/workflows/container-publish.yml b/.github/workflows/container-publish.yml index 6a35abe1..a0cfdcc7 100644 --- a/.github/workflows/container-publish.yml +++ b/.github/workflows/container-publish.yml @@ -76,6 +76,7 @@ jobs: --label "org.opencontainers.image.description=Bundle of Joy MCP Server — 112 cartridges (111 Zig FFI + 1 JS)" \ --label "org.opencontainers.image.licenses=MPL-2.0" \ --label "org.opencontainers.image.version=${{ steps.meta.outputs.version }}" \ + --label "io.modelcontextprotocol.server.name=io.github.hyperpolymath/boj-server" \ . - name: Push to GitHub Container Registry diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c0d0925d..99086f03 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,8 +4,8 @@ # This workflow is managed by gh actions-lock. # Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) # -# Publish workflow — publishes to npm and JSR on version tag push (v*). -# Requires NPM_TOKEN and JSR_TOKEN repository secrets. +# Publish workflow — publishes to npm, the official MCP Server Registry, and JSR on version tag push (v*). +# Requires NPM_TOKEN and JSR_TOKEN repository secrets; MCP Registry uses GitHub OIDC (zero secrets). name: Publish on: @@ -19,7 +19,7 @@ permissions: jobs: publish-npm: - name: Publish to npm + name: Publish to npm & MCP Registry runs-on: ubuntu-latest timeout-minutes: 15 permissions: @@ -34,20 +34,46 @@ jobs: node-version: '22' registry-url: 'https://registry.npmjs.org' - - name: Verify package version matches tag + - name: Verify package and server.json versions match tag run: | TAG_VERSION="${GITHUB_REF_NAME#v}" PKG_VERSION=$(node -p "require('./package.json').version") + MCP_NAME=$(node -p "require('./package.json').mcpName") + SRV_VERSION=$(node -p "require('./server.json').version") + SRV_NAME=$(node -p "require('./server.json').name") if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then echo "::error::Tag version ($TAG_VERSION) does not match package.json version ($PKG_VERSION)" exit 1 fi + if [ "$TAG_VERSION" != "$SRV_VERSION" ]; then + echo "::error::Tag version ($TAG_VERSION) does not match server.json version ($SRV_VERSION)" + exit 1 + fi + if [ "$MCP_NAME" != "$SRV_NAME" ]; then + echo "::error::package.json mcpName ($MCP_NAME) does not match server.json name ($SRV_NAME)" + exit 1 + fi - name: Publish to npm run: npm publish --provenance --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Install mcp-publisher + run: | + ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') + OS=$(uname -s | tr '[:upper:]' '[:lower:]') + curl -fsSL -o /tmp/mcp-publisher.tar.gz \ + "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_${OS}_${ARCH}.tar.gz" + tar -xzf /tmp/mcp-publisher.tar.gz -C /tmp mcp-publisher + chmod +x /tmp/mcp-publisher + + - name: Authenticate and publish to MCP Registry + run: | + /tmp/mcp-publisher login github-oidc + /tmp/mcp-publisher validate server.json + /tmp/mcp-publisher publish + publish-jsr: name: Publish to JSR runs-on: ubuntu-latest diff --git a/Containerfile b/Containerfile index 5c5689d4..119dae94 100644 --- a/Containerfile +++ b/Containerfile @@ -22,7 +22,8 @@ LABEL org.opencontainers.image.title="Bundle of Joy Server (MCP Bridge)" \ org.opencontainers.image.source="https://github.com/hyperpolymath/boj-server" \ org.opencontainers.image.vendor="hyperpolymath" \ org.opencontainers.image.licenses="MPL-2.0" \ - org.opencontainers.image.authors="Jonathan D.A. Jewell " + org.opencontainers.image.authors="Jonathan D.A. Jewell " \ + io.modelcontextprotocol.server.name="io.github.hyperpolymath/boj-server" WORKDIR /app diff --git a/container/Containerfile b/container/Containerfile index 0d8e32e5..5dad7749 100644 --- a/container/Containerfile +++ b/container/Containerfile @@ -94,6 +94,7 @@ LABEL org.opencontainers.image.title="Bundle of Joy Server" \ org.opencontainers.image.vendor="hyperpolymath" \ org.opencontainers.image.licenses="MPL-2.0" \ org.opencontainers.image.authors="Jonathan D.A. Jewell " \ + io.modelcontextprotocol.server.name="io.github.hyperpolymath/boj-server" \ dev.stapeln.compose="container/compose.toml" # Minimal runtime deps: OpenSSL (Elixir TLS), ncurses (Erlang), glibc (boj-invoke + .so) diff --git a/mcp-bridge/tests/dispatch_test.js b/mcp-bridge/tests/dispatch_test.js index 927ff960..2a5e40b5 100644 --- a/mcp-bridge/tests/dispatch_test.js +++ b/mcp-bridge/tests/dispatch_test.js @@ -383,3 +383,39 @@ test("otel enabled-mode produces well-formed span handles", async () => { delete process.env.OTEL_EXPORTER_OTLP_ENDPOINT; } }); + +// ----------------------------------------------------------------- +// 16. MCP Registry (server.json) and package.json coherence +// ----------------------------------------------------------------- +test("server.json and package.json satisfy MCP Registry constraints", () => { + const repoRoot = join(__dirname, "../.."); + const pkg = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")); + const jsr = JSON.parse(readFileSync(join(repoRoot, "jsr.json"), "utf8")); + const srv = JSON.parse(readFileSync(join(repoRoot, "server.json"), "utf8")); + + assert.equal( + srv.$schema, + "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + ); + assert.equal(srv.name, "io.github.hyperpolymath/boj-server"); + assert.equal(pkg.mcpName, srv.name, "package.json mcpName must match server.json name"); + assert.equal(srv.version, pkg.version, "server.json version must match package.json version"); + assert.equal(srv.version, jsr.version, "server.json version must match jsr.json version"); + assert.ok( + srv.description && srv.description.length >= 1 && srv.description.length <= 100, + `server.json description must be 1..100 chars (got ${srv.description?.length})`, + ); + assert.equal(srv.repository?.source, "github"); + assert.match( + srv.repository?.url ?? "", + /^https:\/\/github\.com\/[\w.-]+\/[\w.-]+$/, + "repository.url must match MCP Registry githubURLRegex (no .git suffix)", + ); + assert.ok(Array.isArray(srv.packages) && srv.packages.length >= 1); + const npmPkg = srv.packages.find((p) => p.registryType === "npm"); + assert.ok(npmPkg, "server.json must declare an npm package entry"); + assert.equal(npmPkg.identifier, pkg.name); + assert.equal(npmPkg.version, pkg.version); + assert.equal(npmPkg.transport?.type, "stdio"); +}); + diff --git a/package.json b/package.json index 51f651ae..ae823e26 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,13 @@ { "name": "@hyperpolymath/boj-server", "version": "0.5.0", + "mcpName": "io.github.hyperpolymath/boj-server", "description": "Bundle of Joy (BoJ) MCP Server — cartridge-based DevOps + multi-agent coordination toolkit with 125 domain cartridges (database, container, git, k8s, observability, secrets, IaC, multi-instance AI coord, and more). Formally verified (Idris2) core; MPL-2.0.", "license": "MPL-2.0", "author": "Jonathan D.A. Jewell ", "files": [ "mcp-bridge/", + "server.json", "README.md", "LICENSE", "NOTICE" diff --git a/server.json b/server.json new file mode 100644 index 00000000..105daa5e --- /dev/null +++ b/server.json @@ -0,0 +1,103 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json", + "name": "io.github.hyperpolymath/boj-server", + "title": "Bundle of Joy (BoJ) Server", + "description": "Cartridge-based MCP server for DevOps, cloud, database, k8s, and formally verified coordination.", + "repository": { + "url": "https://github.com/hyperpolymath/boj-server", + "source": "github" + }, + "websiteUrl": "https://github.com/hyperpolymath/boj-server", + "version": "0.5.0", + "packages": [ + { + "registryType": "npm", + "registryBaseUrl": "https://registry.npmjs.org", + "identifier": "@hyperpolymath/boj-server", + "version": "0.5.0", + "runtimeHint": "npx", + "transport": { + "type": "stdio" + }, + "environmentVariables": [ + { + "name": "BOJ_URL", + "description": "Base URL for the BoJ REST API backend (loads cartridges from boj-server-cartridges).", + "default": "http://localhost:7700", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "BOJ_TOOL_SCOPE", + "description": "Advertised cartridge tool-surface scope ('full', 'core', or CSV of domains like 'core,github,browser').", + "default": "full", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "BOJ_PROTOCOL", + "description": "Primary protocol for cartridge communication (rest, grpc, graphql).", + "default": "rest", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "BOJ_RATE_LIMIT", + "description": "Maximum number of tool calls permitted per minute.", + "default": "60", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "BOJ_LOG_LEVEL", + "description": "Logging verbosity (debug, info, warn, error, silent).", + "default": "info", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "COORD_BACKEND_URL", + "description": "URL for the local multi-agent coordination bus backend.", + "default": "http://127.0.0.1:7745", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "GITHUB_TOKEN", + "description": "Personal Access Token for GitHub API operations (required for boj_github_* cartridge tools).", + "format": "string", + "isRequired": false, + "isSecret": true + }, + { + "name": "GITLAB_TOKEN", + "description": "Private Token for GitLab API operations (required for boj_gitlab_* cartridge tools).", + "format": "string", + "isRequired": false, + "isSecret": true + }, + { + "name": "GITLAB_URL", + "description": "Base URL for the GitLab instance.", + "default": "https://gitlab.com", + "format": "string", + "isRequired": false, + "isSecret": false + }, + { + "name": "OTEL_EXPORTER_OTLP_ENDPOINT", + "description": "Optional OTLP/HTTP collector endpoint (e.g. http://localhost:4318) for tool-call trace export.", + "format": "string", + "isRequired": false, + "isSecret": false + } + ] + } + ] +} From b7e1e7507de3b08f5c0b3d45a396f5d4d5299861 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sun, 18 Oct 2026 15:16:44 +0000 Subject: [PATCH 2/5] fix(ci): validate MCP manifest before publishing to npm --- .github/workflows/publish.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 99086f03..650d1ff0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -54,11 +54,6 @@ jobs: exit 1 fi - - name: Publish to npm - run: npm publish --provenance --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Install mcp-publisher run: | ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') @@ -68,10 +63,17 @@ jobs: tar -xzf /tmp/mcp-publisher.tar.gz -C /tmp mcp-publisher chmod +x /tmp/mcp-publisher + - name: Validate MCP manifest + run: /tmp/mcp-publisher validate server.json + + - name: Publish to npm + run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Authenticate and publish to MCP Registry run: | /tmp/mcp-publisher login github-oidc - /tmp/mcp-publisher validate server.json /tmp/mcp-publisher publish publish-jsr: From a03f97a384e871d4179f0b25910262d991157b41 Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 18 Oct 2026 15:27:27 +0000 Subject: [PATCH 3/5] fix(ci): repin standards reusables for actions.lock setup and gate SonarQube - Repin `.github/workflows/secret-scanner.yml`, `governance.yml`, `scorecard.yml`, and `mirror.yml` to `hyperpolymath/standards@e16a231` (includes #1271 leaf tag refs in `actions.lock` so GitHub runner setup no longer fails with `invalid lockfile pin` on `actions/checkout`, #1260 UUID v8 conformance, and #1283 removal/narrowing of `secrets: inherit` / Hypatia WH008). - Add `if: github.actor != 'dependabot[bot]' && vars.SONAR_ENABLED == 'true'` and `timeout-minutes: 15` to `.github/workflows/build.yml` (matching `boj-server-cartridges` and resolving Hypatia's `missing_timeout_minutes` finding on `build.yml`). - Add `io.modelcontextprotocol.server.name` OCI label to `container/Containerfile.fly` and `container/Containerfile.mcp-bridge` for consistency across all four Containerfiles. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .github/workflows/build.yml | 5 +++++ .github/workflows/governance.yml | 7 ++++++- .github/workflows/mirror.yml | 11 +++++++++-- .github/workflows/scorecard.yml | 2 +- .github/workflows/secret-scanner.yml | 6 ++++-- container/Containerfile.fly | 3 ++- container/Containerfile.mcp-bridge | 3 ++- 7 files changed, 29 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9497511..67f9a960 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,7 +21,12 @@ permissions: jobs: sonarqube: name: SonarQube + # Opt-in via repository variable SONAR_ENABLED=true (matching + # boj-server-cartridges) so missing/unrotated SONAR_TOKEN does not produce + # a permanent false-red check on PRs and main. + if: github.actor != 'dependabot[bot]' && vars.SONAR_ENABLED == 'true' runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/checkout@v4.3.1 with: diff --git a/.github/workflows/governance.yml b/.github/workflows/governance.yml index fc730fdb..a964439c 100644 --- a/.github/workflows/governance.yml +++ b/.github/workflows/governance.yml @@ -35,4 +35,9 @@ permissions: jobs: governance: - uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@5a0891e9e58b785181a92e141505ca96ca987b42 + # Previous 5a0891e9 pin predates hyperpolymath/standards#1271 (f335165), + # which fixed actions.lock leaf tag refs so runner job setup succeeds, + # and hyperpolymath/standards#1260 (UUID v8 conformance). + uses: hyperpolymath/standards/.github/workflows/governance-reusable.yml@e16a23170fa378bf3b1444c3ee94100413ae3ff7 + secrets: + HYPATIA_SCAN_PAT: ${{ secrets.HYPATIA_SCAN_PAT }} diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index b7da63bc..7f2b3d93 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -24,5 +24,12 @@ concurrency: jobs: mirror: - uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@84355587cb2a1f86e6882de83514a32db2646e7a - secrets: inherit + uses: hyperpolymath/standards/.github/workflows/mirror-reusable.yml@e16a23170fa378bf3b1444c3ee94100413ae3ff7 + secrets: + GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }} + BITBUCKET_SSH_KEY: ${{ secrets.BITBUCKET_SSH_KEY }} + CODEBERG_SSH_KEY: ${{ secrets.CODEBERG_SSH_KEY }} + SOURCEHUT_SSH_KEY: ${{ secrets.SOURCEHUT_SSH_KEY }} + DISROOT_SSH_KEY: ${{ secrets.DISROOT_SSH_KEY }} + GITEA_SSH_KEY: ${{ secrets.GITEA_SSH_KEY }} + RADICLE_KEY: ${{ secrets.RADICLE_KEY }} diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 73f1cac4..9de8382a 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -43,4 +43,4 @@ jobs: contents: read security-events: write id-token: write - uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@84355587cb2a1f86e6882de83514a32db2646e7a + uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@e16a23170fa378bf3b1444c3ee94100413ae3ff7 diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index fffde78c..54d47e40 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -21,5 +21,7 @@ jobs: scan: permissions: contents: read - uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@84355587cb2a1f86e6882de83514a32db2646e7a - secrets: inherit + # Previous 84355587 pin predates hyperpolymath/standards#1271 (f335165), + # which fixed actions.lock leaf tag refs so runner job setup succeeds. + # Also drops `secrets: inherit` per hyperpolymath/standards#1283 (e16a231). + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@e16a23170fa378bf3b1444c3ee94100413ae3ff7 diff --git a/container/Containerfile.fly b/container/Containerfile.fly index da1c08b1..069be3e2 100644 --- a/container/Containerfile.fly +++ b/container/Containerfile.fly @@ -61,7 +61,8 @@ LABEL org.opencontainers.image.title="Bundle of Joy Server" \ org.opencontainers.image.source="https://github.com/hyperpolymath/boj-server" \ org.opencontainers.image.vendor="hyperpolymath" \ org.opencontainers.image.licenses="MPL-2.0" \ - org.opencontainers.image.authors="Jonathan D.A. Jewell " + org.opencontainers.image.authors="Jonathan D.A. Jewell " \ + io.modelcontextprotocol.server.name="io.github.hyperpolymath/boj-server" # wolfi is glibc-native: no gcompat; ncurses not ncurses-libs; add curl for healthcheck RUN apk add --no-cache ca-certificates openssl ncurses libstdc++ libssl3 curl diff --git a/container/Containerfile.mcp-bridge b/container/Containerfile.mcp-bridge index 0b69ac47..b02efa10 100644 --- a/container/Containerfile.mcp-bridge +++ b/container/Containerfile.mcp-bridge @@ -27,7 +27,8 @@ LABEL org.opencontainers.image.title="Bundle of Joy Server (MCP Bridge)" \ org.opencontainers.image.source="https://github.com/hyperpolymath/boj-server" \ org.opencontainers.image.vendor="hyperpolymath" \ org.opencontainers.image.licenses="MPL-2.0" \ - org.opencontainers.image.authors="Jonathan D.A. Jewell " + org.opencontainers.image.authors="Jonathan D.A. Jewell " \ + io.modelcontextprotocol.server.name="io.github.hyperpolymath/boj-server" WORKDIR /app From ba59fbcebf5cc6b4d78423f4ad7802cc9b67c6de Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 18 Oct 2026 16:16:40 +0000 Subject: [PATCH 4/5] chore(env): provision Bun in .mise.toml and MCP bridge Containerfiles Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .mise.toml | 1 + Containerfile | 2 ++ container/Containerfile.mcp-bridge | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.mise.toml b/.mise.toml index 0763c6cf..4a8451fb 100644 --- a/.mise.toml +++ b/.mise.toml @@ -2,4 +2,5 @@ zig = "0.16.0" elixir = "1.18.4-otp-25" idris2 = "0.8.0" +bun = "1.4.2" deno = "2.7.14" diff --git a/Containerfile b/Containerfile index 119dae94..4b8ded98 100644 --- a/Containerfile +++ b/Containerfile @@ -16,6 +16,8 @@ FROM cgr.dev/chainguard/node:latest +COPY --from=oven/bun:1.4.2 /usr/local/bin/bun /usr/local/bin/bun + LABEL org.opencontainers.image.title="Bundle of Joy Server (MCP Bridge)" \ org.opencontainers.image.description="MCP stdio transport for BoJ cartridge toolkit" \ org.opencontainers.image.url="https://github.com/hyperpolymath/boj-server" \ diff --git a/container/Containerfile.mcp-bridge b/container/Containerfile.mcp-bridge index b02efa10..0368fb1c 100644 --- a/container/Containerfile.mcp-bridge +++ b/container/Containerfile.mcp-bridge @@ -18,8 +18,8 @@ FROM cgr.dev/chainguard/wolfi-base:latest -# Install Deno runtime (replaces banned Node.js/npm) -RUN apk add --no-cache deno +# Install Bun and Deno runtimes (preference order: Bun > Deno per LANGUAGE-POLICY) +RUN apk add --no-cache bun deno LABEL org.opencontainers.image.title="Bundle of Joy Server (MCP Bridge)" \ org.opencontainers.image.description="MCP stdio transport for BoJ cartridge toolkit" \ From b2730842a8cac939bbcaf7b609fa6c36676f25ce Mon Sep 17 00:00:00 2001 From: hyperpolymath <6759885+hyperpolymath@users.noreply.github.com> Date: Sun, 18 Oct 2026 16:24:40 +0000 Subject: [PATCH 5/5] fix(ci): resolve Hypatia RE008 alert and CodeRabbit workflow review comments Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- .github/workflows/publish.yml | 11 +++++++++++ .github/workflows/scorecard.yml | 14 +++++++------- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67f9a960..9a2dde99 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: # Opt-in via repository variable SONAR_ENABLED=true (matching # boj-server-cartridges) so missing/unrotated SONAR_TOKEN does not produce # a permanent false-red check on PRs and main. - if: github.actor != 'dependabot[bot]' && vars.SONAR_ENABLED == 'true' + if: vars.SONAR_ENABLED == 'true' runs-on: ubuntu-latest timeout-minutes: 15 steps: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 650d1ff0..dd461eb5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,10 +37,13 @@ jobs: - name: Verify package and server.json versions match tag run: | TAG_VERSION="${GITHUB_REF_NAME#v}" + PKG_NAME=$(node -p "require('./package.json').name") PKG_VERSION=$(node -p "require('./package.json').version") MCP_NAME=$(node -p "require('./package.json').mcpName") SRV_VERSION=$(node -p "require('./server.json').version") SRV_NAME=$(node -p "require('./server.json').name") + SRV_PKG_ID=$(node -p "require('./server.json').packages?.[0]?.identifier ?? ''") + SRV_PKG_VERSION=$(node -p "require('./server.json').packages?.[0]?.version ?? ''") if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then echo "::error::Tag version ($TAG_VERSION) does not match package.json version ($PKG_VERSION)" exit 1 @@ -53,6 +56,14 @@ jobs: echo "::error::package.json mcpName ($MCP_NAME) does not match server.json name ($SRV_NAME)" exit 1 fi + if [ "$PKG_NAME" != "$SRV_PKG_ID" ]; then + echo "::error::package.json name ($PKG_NAME) does not match server.json packages[0].identifier ($SRV_PKG_ID)" + exit 1 + fi + if [ "$TAG_VERSION" != "$SRV_PKG_VERSION" ]; then + echo "::error::Tag version ($TAG_VERSION) does not match server.json packages[0].version ($SRV_PKG_VERSION)" + exit 1 + fi - name: Install mcp-publisher run: | diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 9de8382a..b602b749 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -33,13 +33,13 @@ permissions: jobs: analysis: permissions: - # `contents: read` is REQUIRED, not redundant. Declaring `permissions:` - # at job level sets every unlisted scope to `none`, and a called - # workflow can never hold more than the calling job grants it. The - # reusable declares top-level `permissions: contents: read` and its - # first step is actions/checkout, so omitting `contents` here handed - # it `contents: none` and the call died at startup with zero jobs. - # The green sibling (boj-server-cartridges) lists all three. + # `actions: read` and `contents: read` are REQUIRED, not redundant. + # Declaring `permissions:` at job level sets every unlisted scope to + # `none`, and a called workflow can never hold more than the calling job + # grants it. `scorecard-reusable.yml` requests `actions: read` (for + # Scorecard's Packaging check), `contents: read`, `security-events: write`, + # and `id-token: write` on its `scorecard` job. + actions: read contents: read security-events: write id-token: write