v0.12.1
Hardening pass over the tool surface from a full-pass review: input validation on the write/bulk handlers, output-contract fixes, and test-suite robustness.
Fixed
npm_dist_tag_setpre-flights the packument and returns a 404 (with the published-version list) when the target version does not exist, instead of PUTting a tag at a nonexistent version. It was the only write handler that skipped the packument pre-flight.npm_token_revokevalidates the token key (rejects empty/malformed) before the DELETE, so passing the token value instead of its UUID key no longer silently targets the wrong resource.npm_team_grant/npm_team_revokevalidate thepackagefield before building the request -- previously the only package-accepting handlers with no validation guard in the call path.npm_downloads_bulkandnpm_comparevalidate every package name up front and return a clean 400 naming the offender, instead of throwing insideencPkgand surfacing a raw error at the MCP boundary.npm_owner_removematches usernames case-insensitively; a caller passingBobagainst a storedbobno longer gets a misleading 404.- The packument GET-mutate-PUT flows (
npm_deprecate,npm_undeprecate,npm_owner_add,npm_owner_remove) retry once on a 409_revconflict (CouchDB optimistic-concurrency), so a concurrent write no longer hard-fails a retryable conflict. npm_unpublish_versionskips the tarball DELETE when the tarball origin does not match the configured registry origin, instead of misrouting the DELETE to the wrong host under proxy registries (Verdaccio/Nexus in proxy mode).npm_check_auth/npm_publish_preflightreport a distinctfetch-failed2FA state when the profile fetch fails, instead of rendering "2FA is enabled (unknown)" -- which implied confirmed 2FA when the real cause was a token lacking read on/-/npm/v1/user.npm_provenancerejects an empty/whitespace version with a 400 before the registry call.npm_package_accesssurfaces both endpoint errors when/accessand/collaboratorsboth fail, instead of reporting only the collaborators error and hiding the real root cause.npm_healthstays well-defined for a partially-written packument (dist-tags.latestpresent but its version doc absent).build.mjsguards thepackage.jsonread with an actionable error instead of an unhandled exception.
Changed
npm_recent_changes: thetotalPackagesresponse field is renamed toregistryPackageCount. It holds the registry-wide doc count (~3M fromreplicate.npmjs.com), not the per-callchanges.length, and the old name read as if it were a per-call count. Consumers readingtotalPackagesmust update toregistryPackageCount.npm_recent_changes: theidempotentHintannotation is corrected tofalse-- it serves a live changes feed, so MCP clients must not cache or de-duplicate repeated calls.npm_access_set:access: "private"now maps to the registry wire value"restricted"rather than being passed through verbatim (the registry usespublic/restricted).npm_provenance: predicate-type detection tightened from substring to prefix match, and the description reworded to make clear the tool retrieves attestations -- it does not cryptographically verify signatures, certificate chains, or Rekor entries.npm_org_member_setnow requiresconfirm: true, matchingnpm_org_member_remove.npm_compare/npm_healthcarry the deprecation message string when a package is deprecated, instead of collapsing it to a boolean.npm_trusted_publisherstolerates a string-or-objectworkflow_ref/ci_config_ref_uri, surfacing the raw string instead of silently yieldingundefined.
Added
npm_tokenssurfaces each token'stypeandautomationflag, so callers can distinguish automation tokens (which bypass 2FA) from granular/legacy ones -- the distinction the tool description already promised.npm_check_auth/npm_publish_preflightfire their independent auth reads (whoami / profile / tokens) concurrently rather than serially.
Documentation
- Description fixes:
npm_deprecateempty-message wording, enumerated downloadperiodvalues, consistent org-name@-prefix wording,npm_dep_treedepth semantics (depth counts the root), and named staleness constants innpm_health. - ASCII-normalized the
missing _reverror strings (were a mix of em-dash and--).
Tests
mockFetchSequencethrows on over-run instead of silently replaying the last canned response, which had masked spurious extra-request regressions across the write suite. Tightened write/semver assertions, derived the total tool-count check from the per-module sums, and added annpm_token_revokemalformed-key negative test. 739 passing.- Internal:
Packumentdist-tags/maintainerstyped optional to match the defensive runtime guards.