Skip to content

Sprint1 distribution - #1

Merged
a1410453 merged 5 commits into
mainfrom
sprint1-distribution
Sep 16, 2026
Merged

a1410453 merged 5 commits into
mainfrom
sprint1-distribution

Conversation

@a1410453

Copy link
Copy Markdown
Collaborator

No description provided.

package.json said 0.1.2 while server.json (twice), manifest.json and
package-lock.json all still said 0.1.0. The release workflow compared the
tag to package.json alone, so nothing ever looked at the other three — and
`npm install` in CI rewrote the lock in place, which is how it drifted in
the first place.

- scripts/release.mjs bumps all four together and opens a dated CHANGELOG
  section; --check verifies they agree.
- test/version.test.js fails the build on drift, and also asserts every
  declared version site still exists, so a renamed key cannot make the
  check silently vacuous.
- CI installs with `npm ci`.
- CHANGELOG now matches what actually shipped: the block sitting under
  "Unreleased" went out in 0.1.0 (f5f2e1a is an ancestor of the v0.1.0
  tag), and 0.1.1 was tagged but never published — it carried
  package.json 0.1.0, so the version gate added in that same commit
  rejected its own release. npm has 0.1.0 and 0.1.2 only.
The package had mcpName and a server.json but no publish step, so it was
invisible to every client and catalogue that discovers servers through the
registry rather than through npm search.

- server.json is validated (`mcp-publisher validate`) and published on each
  release tag, after npm, because the registry proves ownership by fetching
  the npm package and matching its mcpName.
- Fixed a rejection we had not hit yet: the registry caps a server
  description at 100 characters and ours was 135. A test now asserts the
  cap, along with the reverse-DNS name shape.
- `remotes` declares its Authorization header as a secret, with the token
  as a {api_token} variable so clients prompt for the key rather than the
  whole header. Verified the endpoint answers an unauthenticated connect
  with 401 invalid_token, which is what a registry install got before.
- npm publish --provenance (+ id-token: write). The unaffiliated
  2captcha-mcp package cannot produce a provenance badge; a README warning
  only reaches people who read the README.
- The workflow triggers on tags instead of every push and filtering inside.

docs/RELEASING.md covers the one-time DNS setup: com.2captcha is not an
io.github.* namespace, so OIDC login does not cover it and the TXT record
goes on the apex, not under a _mcp-registry selector.
manifest.json has described a desktop extension since the first release
and nothing ever built one, so the one-click install path in Claude
Desktop did not exist — the file documented something uninstallable.

`npm run bundle` stages server.js, tool_groups.js and the production
node_modules under server/ and packs them with @anthropic-ai/mcpb, pinned.
The bundle is self-contained and runs with the host's own node rather than
shelling out to `npx @2captcha/mcp` at runtime: that needs a network round
trip and an npx on PATH, and "spawn npx ENOENT" is already a
troubleshooting entry in our own README.

manifest.json's server block moves to the bundle layout to match, and a
test pins the two together so the entry point cannot drift from where the
bundle stages the file.
The README had the content and none of the packaging: no badges, no
install buttons, and JSON snippets for five clients. That is lost
conversion at the narrowest point of the funnel — the reader is already
on the page.

- npm version/downloads, CI, registry and license badges.
- Cursor and VS Code install deeplinks, and a button for the .mcpb bundle.
- An Install section covering 16 clients: adds Windsurf, Zed, Warp,
  Gemini CLI, Continue, LM Studio, Cline/Roo, Goose, n8n and a generic
  stdio/HTTP entry.
- README.ru.md, linked both ways. 2Captcha's RU/CIS audience and SEO are
  historically strong and the organic traffic compounds.

Every badge and image URL was fetched to confirm it resolves, and every
internal anchor in both files was checked against its heading — the
Cyrillic ones are easy to get silently wrong.
npm audit reported qs (GHSA-x5fp-wj9c-mxmx, GHSA-4mjr-xmp4-gh2g, via
express) and hono (GHSA-gqvv-2mrq-wpjv and two others). Both arrive
through @modelcontextprotocol/sdk and neither is reachable from this
bridge, which uses the SDK's stdio and Streamable-HTTP client only.

`npm audit fix` resolves both inside the existing semver ranges:
  qs    6.15.3 -> 6.16.0
  hono  4.13.3 -> 4.13.8

Lock-only, six lines; no direct dependency and no lockfileVersion change.
Verified with npm ci from the fixed lock (0 vulnerabilities), npm test
(22/22) and a full .mcpb rebuild.

This treats the symptom. The actual fix is E2 in the audit: bundle
server.js with esbuild so express and hono are tree-shaken out of the
published package entirely, rather than shipping patched copies of
dependencies we never call.
@a1410453
a1410453 merged commit f4c0b32 into main Sep 16, 2026
6 checks passed
@a1410453
a1410453 deleted the sprint1-distribution branch September 16, 2026 14:09
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