Skip to content

fix(release): Pin npm 11 and support a GitHub App token for the version PR (#95) - #96

Merged
deanzaka merged 4 commits into
mainfrom
fix/release-npm11-app-token-95
Oct 19, 2026
Merged

deanzaka merged 4 commits into
mainfrom
fix/release-npm11-app-token-95

Conversation

@johnxie

@johnxie johnxie commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Summary

The Release workflow fails on every push to main, so no release reaches npm or the MCP Registry without a manual publish. This PR fixes the two causes, removes a README section for a mode that the package does not have, and makes the npm install of @taskade/mcp-server smaller.

  1. npm 12 breaks changeset publish. The workflow installs npm@latest, which is now npm 12. npm 12 returns npm info --json as an array. @changesets/cli 2.29.4 reads pkgInfo.versions from that output (getUnpublishedPackages). For an array the value is undefined, so the list of published versions is empty. The CLI then tries to publish the current version again, and npm stops it with You cannot publish over the previously published versions: 0.1.2.
  2. GITHUB_TOKEN cannot open the version PR. This repository does not let GitHub Actions create pull requests. A push with a pending changeset fails with GitHub Actions is not permitted to create or approve pull requests.

I checked the npm claim locally with the same command that changeset publish runs:

Command Output shape .versions
npx npm@11.21.1 info @taskade/mcp-server --json object ["0.0.1","0.0.3","0.1.0","0.1.1","0.1.2"]
npx npm@12.2.1 info @taskade/mcp-server --json array of 1 object undefined

Changes

  • .github/workflows/release.yml
    • Pin npm@^11.5.1 in place of npm@latest. npm 11.5.1 is the minimum for trusted publishing (OIDC), so publishing stays tokenless.
    • Add an optional actions/create-github-app-token@v3 step. It runs only when the repository variable RELEASE_APP_ID exists. It reads the private key from the secret RELEASE_APP_PRIVATE_KEY and asks only for contents: write and pull-requests: write.
    • changesets/action gets steps.app-token.outputs.token || secrets.GITHUB_TOKEN. actions/checkout gets steps.app-token.outputs.token || github.token, so the git pushes also use the App token. github.token is the checkout default.
    • Add a Push release tags step after Publish. changeset publish creates a tag for each new version but does not push it. The step runs only with the App token, because a tag pushed with GITHUB_TOKEN does not start publish-mcp-registry.yml.
  • .github/workflows/publish-mcp-registry.yml: correct the trigger comment. The tag comes from the new Push release tags step, which runs only with the App token.
  • .github/workflows/force-release.yml: the same npm pin. This manual workflow runs changeset publish too, so npm 12 breaks it in the same way.
  • README.md and packages/server/README.md: remove the --http section. The published bin/cli.mjs runs over stdio only and ignores the flag. HTTP clients go to the hosted server at https://www.taskade.com/mcp, which the README already leads with.
  • packages/server/package.json: move @modelcontextprotocol/sdk, mcp-proxy, node-fetch and zod to devDependencies. The esbuild bundle contains the first three, and mcp-proxy is used only by the local HTTP dev script (start:server). yarn.lock does not change.
  • .changeset/bundle-only-deps.md: a patch changeset for @taskade/mcp-server.

The codegen package is not in this PR.

Behavior without the App (the current repository state)

Push to main Before After
Pending changeset Version PR step fails (Actions cannot create PRs) Same failure. No change until the App exists
No pending changeset, version already on npm changeset publish tries to publish again and fails changeset publish skips the published version and the job passes
No pending changeset, new version npm 12 path, tries to publish every package again Publishes only the new version with OIDC. No tag push (same as before)

Owner steps to enable the App

  1. Create a GitHub App owned by the taskade organization. Clear the Active box under Webhook. Give it the repository permissions Contents: Read and write and Pull requests: Read and write. Metadata: Read-only is automatic.
  2. Install the App on taskade/mcp only.
  3. On the App settings page, copy the App ID and generate a private key (.pem).
  4. In taskade/mcp > Settings > Secrets and variables > Actions, add the variable RELEASE_APP_ID with the App ID.
  5. In the same page, add the secret RELEASE_APP_PRIVATE_KEY with the full contents of the .pem file.
  6. Merge a PR that has a changeset. Make sure that the Release run opens a chore: release PR, and that CI runs on that PR.
  7. Merge the chore: release PR. Make sure that the next Release run publishes the new version to npm and that Publish to MCP Registry starts from the new tag.

If you add the variable, you must also add the secret. Without the secret, the token step fails and the release job stops.

Risk and rollback

  • Low risk. With no RELEASE_APP_ID variable, the token step is skipped and every token expression falls back to the same token as today. The only change on that path is the npm 11 pin.
  • The npm pin keeps OIDC trusted publishing and provenance. npm@^11.5.1 resolves to the latest npm 11 (11.21.1 today), which supports Node ^20.17.0 || >=22.9.0.
  • actions/create-github-app-token@v3 also accepts client-id, which is the newer input name. This PR uses app-id because actionlint 1.7.12 knows only app-id for v3.
  • Moving the dependencies changes only what npm installs for users of the package. The bundle is the same.
  • Rollback: revert this PR. To disable only the App path, delete the RELEASE_APP_ID variable.

Tests

  • actionlint 1.7.12 on all 4 workflows: 0 findings.
  • yarn install --frozen-lockfile --force: passes, yarn.lock unchanged.
  • yarn build, then git status: no tracked file changes (the CI clean-tree check).
  • yarn lint: passes. yarn test: 4 files, 19 tests passed.
  • Bundle check: every import in the built bin/cli.mjs is a Node built-in (node:*, module), with no dynamic import(). The only require() calls are buffer, node:process, node:stream/web and worker_threads.
  • Package smoke: npm pack of this branch, then npm install --prefix <empty dir> ./taskade-mcp-server-0.1.2.tgz adds 1 package (632 KB). The same install of the published 0.1.2 tarball adds 120 packages (34 MB). A stdio initialize plus tools/list against the installed bin/cli.mjs returns serverInfo.name = taskade and 62 tools.
  • --http check: the published 0.1.2 bin/cli.mjs has no process.argv read and no HTTP server code. Run with --http, it answers initialize over stdio.

Refs #74

Closes #95

…on PR (#95)

npm 12 returns `npm info --json` as an array. `@changesets/cli` then
finds no published versions and tries to publish the current version
again, and npm rejects it. Pin `npm@^11.5.1` in the release and force
release workflows. npm 11.5.1 is the minimum for trusted publishing.

Add an optional `actions/create-github-app-token` step. It runs only
when the repository variable `RELEASE_APP_ID` exists. Its token opens
the version PR, does the git pushes, and pushes the release tags after a
publish. Without the variable, the job uses GITHUB_TOKEN as before.

Refs #74
…have (#95)

The published `bin/cli.mjs` runs over stdio only and ignores `--http`.
Point HTTP clients to the hosted server at https://www.taskade.com/mcp.
…es (#95)

`bin/cli.mjs` bundles `@modelcontextprotocol/sdk`, `node-fetch` and
`zod`, and imports only Node built-in modules. `mcp-proxy` is used only
by the local HTTP dev script. An install of the package now adds 1
package instead of 120.
Copilot AI balanced review requested due to automatic review settings October 17, 2026 05:57
@changeset-bot

changeset-bot Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 407894e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@taskade/mcp-server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No blocking issues were identified in the scoped workflow, packaging, or documentation changes.

No open issues 🎉

What changed in this PR

Improves release automation for the MCP packages and reduces the server package’s installation footprint.

Changes:

  • Pins npm to version 11 in both release workflows.
  • Adds optional GitHub App authentication for version PRs and release-tag pushes.
  • Moves bundled dependencies to development dependencies and clarifies stdio-only local usage.
File Description
README.md Directs HTTP clients to the hosted server.
packages/​server/​README.md Clarifies local stdio-only support.
packages/​server/​package.json Removes runtime dependency installation requirements.
.github/​workflows/​release.yml Pins npm and adds optional App authentication and tag pushes.
.github/​workflows/​force-release.yml Pins npm for manual releases.
.changeset/​bundle-only-deps.md Records the server packaging patch release.

Review effort: Balanced

The tag that starts this workflow comes from the new Push release tags
step in release.yml. That step runs only with the release App token.
@johnxie
johnxie requested a balanced review from Copilot October 17, 2026 06:04
@johnxie

johnxie commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

@deanzaka for review.

Impact

  • Maintainers: a merged changeset becomes a reviewed chore: release PR again, and merging it publishes to npm with no manual step. Today every Release run on main is red.
  • With the release GitHub App installed, CI runs on the release PR and the MCP Registry entry updates from the release tag. Without the App, nothing changes except the npm 11 pin.
  • Users of npx @taskade/mcp-server: the install adds 1 package instead of 120, because the bundle already contains its dependencies.
  • README readers no longer try a --http flag that the package ignores. HTTP clients go to https://www.taskade.com/mcp.

Release flow

BEFORE
  merge PR with changeset
    -> Release: changesets/action with GITHUB_TOKEN
    -> "GitHub Actions is not permitted to create or approve pull requests"  (red)
  push with no changeset
    -> npm@latest = npm 12 -> `npm info --json` is an array
    -> changeset publish thinks 0.1.2 is unpublished -> "cannot publish over 0.1.2"  (red)
  => maintainer publishes to npm by hand, then runs "Publish to MCP Registry" by hand
AFTER (App configured: RELEASE_APP_ID + RELEASE_APP_PRIVATE_KEY)
  merge PR with changeset
    -> Release: App token -> changesets/action opens "chore: release" PR
    -> CI runs on the release PR (App events start workflows)
  merge "chore: release"
    -> Release: npm@^11.5.1 -> changeset publish via OIDC -> npm 0.1.3
    -> "Push release tags" (App token) -> tag @taskade/mcp-server@0.1.3
    -> "Publish to MCP Registry" starts from the tag

AFTER (no App, current repository state)
  merge PR with changeset   -> same red PR step as today
  push with no changeset    -> npm 11 skips published versions -> green

QA steps

Step Action Expected result
1 Run actionlint on .github/workflows/*.yml 0 findings
2 Run npx npm@11 info @taskade/mcp-server --json and npx npm@12 info @taskade/mcp-server --json npm 11 returns an object with versions. npm 12 returns an array, so .versions is undefined
3 Run yarn install --frozen-lockfile, yarn build, git status Install passes, yarn.lock and tracked files do not change
4 Run yarn lint and yarn test Lint passes, 19 tests pass
5 npm pack in packages/server, then npm install --prefix <empty dir> <tgz> "added 1 package"
6 Send initialize and tools/list over stdio to the installed bin/cli.mjs with a test TASKADE_API_KEY serverInfo.name is taskade, 62 tools
7 (regression) Merge this PR with no App configured npm --version prints 11.x. The two App steps show as skipped. The run still fails at the version PR step, as today, because main has pending changesets and no App
8 (owner) Create a GitHub App with Contents and Pull requests set to Read and write, install it on taskade/mcp, add variable RELEASE_APP_ID and secret RELEASE_APP_PRIVATE_KEY Next Release run on main opens chore: release, and CI runs on it
9 (owner) Merge chore: release npm shows the new version, the tag exists, Publish to MCP Registry runs from the tag
10 (rollback) Delete the RELEASE_APP_ID variable, or revert this PR Without the variable, the job uses GITHUB_TOKEN again. A revert restores the old workflows

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

No blocking issues were identified; the optional App path preserves existing authentication behavior until configured.

No open issues 🎉

Review effort: Balanced

@deanzaka
deanzaka merged commit de335b7 into main Oct 19, 2026
6 checks passed
@taskade-mcp-release taskade-mcp-release Bot mentioned this pull request Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(release): Release workflow fails on npm 12 and cannot open the version PR

3 participants