Skip to content

fix(mcp): Stop npm from dropping the bin entry on publish - #15

Merged
korya merged 2 commits into
masterfrom
korya-chore-release-prep-mcp
Aug 1, 2026
Merged

fix(mcp): Stop npm from dropping the bin entry on publish#15
korya merged 2 commits into
masterfrom
korya-chore-release-prep-mcp

Conversation

@korya

@korya korya commented Aug 1, 2026

Copy link
Copy Markdown
Member

Problem

npx @frontsail-ai/qr-mcp would have installed fine and then done nothing — npm drops the bin entry when publishing this package.

npm rejects a bin path written as "./dist/index.mjs", and instead of failing it silently strips the entry: npm warn publish "bin[qr-mcp]" script name dist/index.mjs was invalid and removed. It is a warning, not an error, and it only appears on npm publish — installing the packed tarball links the bin correctly either way, which is exactly why PR #14's end-to-end install check went green on a package that could not have shipped. Separately, the package still carried the tentative name from PR #14.

Solution

Rename to the owned scope, stop the build from rewriting the manifest, and add a release checklist that catches this class of problem.

The ./ prefix was not hand-written, which is why fixing package.json alone would not have held. vp pack with pack.exports: true rewrites exports and bin on every build, generating precisely the rejected form — so any correction would be undone by the next build, including the build the publish flow itself runs. Dropping exports: true and declaring the entry explicitly stops the build touching package.json at all:

Field Required form Why
exports["."] ./dist/index.mjs the spec requires the ./ prefix on subpath values
bin["qr-mcp"] dist/index.mjs npm strips the entry if it has one

Two adjacent fields with opposite rules, one of them failing silently, is what makes this worth a regression test rather than a one-line fix. tests/manifest.test.ts pins both forms, the file list, public access, and the invariants that core stays a devDependency (so it gets bundled) and node-canvas never becomes a dependency.

Verified publish shape

npm publish --dry-run --access publiczero warnings, three files:

2.5kB   README.md
32.2kB  dist/index.mjs
1.5kB   package.json
→ @frontsail-ai/qr-mcp@0.1.0, 9.9 kB packed

The packed tarball was then installed into a clean directory: node_modules/.bin/qr-mcp links to dist/index.mjs, and the binary answers a raw JSON-RPC initialize with {"name":"qr-code-generator","version":"0.1.0"}.

Dogfooding turned up two real schema problems

Everything before this was SDK-client integration tests. Pointing an actual agent session at the built server surfaced two things those tests could not, because both are about what a reader of the schema concludes:

  1. corner_square_type: "extra-rounded" is what the web UI labels plain "Rounded". dot_type has both rounded and extra-rounded, so an agent reasonably guesses rounded exists for corners too and gets a validation error.
  2. The two linear gradient names are rotated relative to what they render. linear-bl-tr ("Bottom-left to top-right") emits x1=0 y1=0 → x2=280 y2=280, which in SVG coordinates is top-left to bottom-right; linear-tl-br renders top-right to bottom-left. Independently confirmed by rendering with distinct start/end colours and sampling each quadrant.

The gradient bug lives in packages/core and predates this package — the MCP server faithfully exposes core's values, and the web app has always rendered them this way. Correcting the rotations would change the site's output and re-render every existing share link, so it is documented, not fixed. Both facts now appear in the tool descriptions, which is the in-scope half: an agent that reads them stops guessing. A follow-up PR should decide whether to correct the rotations and accept the share-link churn.

No visual changeapps/web is untouched.

Other Changes

  • RELEASING section in the package README: bump the version in both places (package.json and SERVER_VERSION, which is what the MCP handshake reports), run the tests, read the dry-run for warnings, publish with --access public (scoped packages default to restricted), tag, and smoke-test the published npx.
  • README gains the verified client config under the new name plus the Claude Code one-liner: claude mcp add qr -- npx -y @frontsail-ai/qr-mcp.
  • Removed a _comment_test key from the package's scripts — npm scripts are a task namespace, and it was showing up as a runnable task in vp run.
  • Test count 146 → 154 (37 core + 70 mcp + 47 e2e); nothing was removed.
  • The private @frontsail/qr-core keeps its name. It is bundled into the published artifact and never published itself, so its scope is invisible externally; renaming it would churn apps/web for no outside benefit.
  • The blueprint's body keeps the old name as written — only its Outcome section records the resolution, so the plan stays a record of what was planned rather than a retcon.

Related:

🤖 Generated with Claude Code

korya and others added 2 commits August 1, 2026 00:01
The npm scope question is settled: the owned org is frontsail-ai, with the hyphen, and
@frontsail-ai/qr-mcp is verified free. PR #14 shipped the package as @frontsail/qr-mcp, which was
always marked tentative pending exactly this.

The `qr-mcp` bin name is unchanged, so the npx invocation users type is the only thing that shifts.
The private @frontsail/qr-core keeps its name: it is bundled into the published artifact and never
published itself, so its scope is invisible outside the repo and renaming it would churn apps/web
for no external benefit.

The blueprint's body keeps the old name as written; only its Outcome section records the
resolution, so the plan stays a record of what was planned rather than a retcon.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8brJnertGtttZrNke8L1C
`npx @frontsail-ai/qr-mcp` would have done nothing. npm rejects a `bin` path written as
"./dist/index.mjs" and, rather than failing, strips the entry and publishes the package without it:
"bin[qr-mcp] script name dist/index.mjs was invalid and removed". It surfaces only as a warning, and
only on `npm publish` — installing the packed tarball links the bin correctly either way, which is
why PR #14's end-to-end check did not catch it.

The `./` prefix was not hand-written. `vp pack` with `pack.exports: true` rewrites package.json's
`exports` and `bin` on every build, and the `bin` value it generates is the rejected form — so
correcting package.json alone would have been undone by the next build, including the build that
the publish flow runs. Dropping `exports: true` and declaring the entry explicitly stops the build
touching the manifest at all. `exports` keeps its "./" prefix, which that field requires; only `bin`
takes the bare path. The two fields having opposite rules is what makes this easy to get wrong.

tests/manifest.test.ts pins both forms, plus the file list, public access, and the invariant that
core stays a devDependency and node-canvas never becomes a dependency.

Also clarifies two tool descriptions that a dogfooding agent flagged as guess-inducing: that
`extra-rounded` is the value the UI labels "Rounded", and that the two linear gradient names are
rotated relative to what they render (verified: `linear-bl-tr` emits a top-left to bottom-right
gradient). The underlying rotation bug lives in packages/core and predates this package; fixing it
would change the web app's output and re-render existing share links, so it is left alone and
documented instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8brJnertGtttZrNke8L1C
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
qr-code-generator Ready Ready Preview Aug 1, 2026 4:02am

@korya
korya marked this pull request as ready for review August 1, 2026 13:59
@korya
korya merged commit 6121aee into master Aug 1, 2026
3 checks passed
@korya
korya deleted the korya-chore-release-prep-mcp branch August 1, 2026 14:00
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.

1 participant