@yawlabs/npmjs-mcp 0.11.9 → 0.11.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +65 -39
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31233,7 +31233,7 @@ function parseSingleConstraint(r) {
31233
31233
  if (patch === null) {
31234
31234
  return { min: [major, minor, 0], max: [major, minor + 1, 0] };
31235
31235
  }
31236
- return null;
31236
+ return { min: [major, minor, patch], max: [major, minor, patch + 1] };
31237
31237
  }
31238
31238
  return null;
31239
31239
  }
@@ -31453,46 +31453,60 @@ var analysisTools = [
31453
31453
  packages: external_exports.array(external_exports.string()).min(2).max(5).describe("Package names to compare")
31454
31454
  }),
31455
31455
  handler: async (input) => {
31456
- const results = await Promise.all(
31456
+ const partials = await Promise.all(
31457
31457
  input.packages.map(async (name) => {
31458
31458
  const [pkgRes, dlRes] = await Promise.all([
31459
31459
  registryGet(`/${encPkg(name)}`),
31460
31460
  downloadsGet(`/downloads/point/last-week/${encPkg(name)}`)
31461
31461
  ]);
31462
- if (!pkgRes.ok) {
31463
- return { name, error: pkgRes.error };
31464
- }
31465
- const pkg = pkgRes.data;
31466
- const latest = pkg["dist-tags"]?.latest;
31467
- const latestVersion = latest ? pkg.versions[latest] : void 0;
31468
- const versionKeys = Object.keys(pkg.versions);
31469
- let vulnerabilities = 0;
31470
- if (latest) {
31471
- const auditRes = await registryPost("/-/npm/v1/security/advisories/bulk", {
31472
- [name]: [latest]
31473
- });
31474
- if (auditRes.ok && auditRes.data?.[name]) {
31475
- vulnerabilities = auditRes.data[name].length;
31476
- }
31477
- }
31478
- return {
31479
- name,
31480
- description: pkg.description,
31481
- latest,
31482
- license: pkg.license ?? latestVersion?.license,
31483
- maintainers: pkg.maintainers?.map((m) => m.name),
31484
- weeklyDownloads: dlRes.ok ? dlRes.data.downloads : null,
31485
- versionCount: versionKeys.length,
31486
- created: pkg.time.created,
31487
- lastPublish: latest ? pkg.time[latest] : void 0,
31488
- deprecated: latestVersion?.deprecated ?? false,
31489
- hasReadme: !!(pkg.readme && pkg.readme.length > 0),
31490
- repository: pkg.repository,
31491
- homepage: pkg.homepage,
31492
- vulnerabilities
31493
- };
31462
+ return { name, pkgRes, dlRes };
31494
31463
  })
31495
31464
  );
31465
+ const auditMap = {};
31466
+ for (const { name, pkgRes } of partials) {
31467
+ if (!pkgRes.ok) continue;
31468
+ const latest = pkgRes.data["dist-tags"]?.latest;
31469
+ if (latest) auditMap[name] = [latest];
31470
+ }
31471
+ let auditData = {};
31472
+ let auditSucceeded = false;
31473
+ if (Object.keys(auditMap).length > 0) {
31474
+ const auditRes = await registryPost("/-/npm/v1/security/advisories/bulk", auditMap);
31475
+ if (auditRes.ok && auditRes.data) {
31476
+ auditData = auditRes.data;
31477
+ auditSucceeded = true;
31478
+ }
31479
+ }
31480
+ const results = partials.map(({ name, pkgRes, dlRes }) => {
31481
+ if (!pkgRes.ok) {
31482
+ const translated = translateError(pkgRes, { pkg: name, op: "compare" });
31483
+ return { name, error: translated.error };
31484
+ }
31485
+ const pkg = pkgRes.data;
31486
+ const latest = pkg["dist-tags"]?.latest;
31487
+ const latestVersion = latest ? pkg.versions[latest] : void 0;
31488
+ const versionKeys = Object.keys(pkg.versions);
31489
+ const wasAudited = auditSucceeded && name in auditMap;
31490
+ const advisories = auditData[name];
31491
+ const vulnerabilities = wasAudited ? Array.isArray(advisories) ? advisories.length : 0 : null;
31492
+ return {
31493
+ name,
31494
+ description: pkg.description,
31495
+ latest,
31496
+ license: pkg.license ?? latestVersion?.license,
31497
+ maintainers: pkg.maintainers?.map((m) => m.name),
31498
+ weeklyDownloads: dlRes.ok ? dlRes.data.downloads : null,
31499
+ versionCount: versionKeys.length,
31500
+ created: pkg.time.created,
31501
+ lastPublish: latest ? pkg.time[latest] : void 0,
31502
+ deprecated: latestVersion?.deprecated ?? false,
31503
+ hasReadme: !!(pkg.readme && pkg.readme.length > 0),
31504
+ repository: pkg.repository,
31505
+ homepage: pkg.homepage,
31506
+ vulnerabilities,
31507
+ auditReliable: wasAudited
31508
+ };
31509
+ });
31496
31510
  return { ok: true, status: 200, data: { comparison: results } };
31497
31511
  }
31498
31512
  },
@@ -31521,6 +31535,7 @@ var analysisTools = [
31521
31535
  const latestVersion = latest ? pkg.versions[latest] : void 0;
31522
31536
  const versionKeys = Object.keys(pkg.versions);
31523
31537
  let vulnerabilityCount = null;
31538
+ let auditReliable = true;
31524
31539
  if (latest) {
31525
31540
  const auditRes = await registryPost("/-/npm/v1/security/advisories/bulk", {
31526
31541
  [input.name]: [latest]
@@ -31528,7 +31543,11 @@ var analysisTools = [
31528
31543
  if (auditRes.ok) {
31529
31544
  const advisories = auditRes.data?.[input.name];
31530
31545
  vulnerabilityCount = Array.isArray(advisories) ? advisories.length : 0;
31546
+ } else {
31547
+ auditReliable = false;
31531
31548
  }
31549
+ } else {
31550
+ auditReliable = false;
31532
31551
  }
31533
31552
  const publishDates = versionKeys.map((v) => pkg.time[v]).filter(Boolean).map((d) => new Date(d).getTime()).sort((a, b) => b - a);
31534
31553
  const now = Date.now();
@@ -31562,6 +31581,7 @@ var analysisTools = [
31562
31581
  daysSinceLastPublish,
31563
31582
  avgDaysBetweenReleases,
31564
31583
  vulnerabilityCount,
31584
+ auditReliable,
31565
31585
  hasLicense,
31566
31586
  hasReadme,
31567
31587
  hasRepo,
@@ -31572,8 +31592,11 @@ var analysisTools = [
31572
31592
  // Holistic single-string verdict layered priority-first: a deprecated
31573
31593
  // package supersedes everything (don't use it), a vulnerable package
31574
31594
  // supersedes maintenance signals (active development doesn't undo a
31575
- // CVE), then staleness, recency, and the catch-all.
31576
- assessment: isDeprecated ? "DEPRECATED" : vulnerabilityCount !== null && vulnerabilityCount > 0 ? "VULNERABLE" : isStale ? "STALE" : daysSinceLastPublish !== null && daysSinceLastPublish < 90 ? "ACTIVE" : "MAINTENANCE"
31595
+ // CVE), then AUDIT_UNKNOWN when we couldn't verify vuln status (a 5xx
31596
+ // on the audit endpoint or a packument with no `latest` to audit) --
31597
+ // better to flag the unknown than confidently report ACTIVE on
31598
+ // unverified data. Then staleness, recency, and the catch-all.
31599
+ assessment: isDeprecated ? "DEPRECATED" : vulnerabilityCount !== null && vulnerabilityCount > 0 ? "VULNERABLE" : !auditReliable ? "AUDIT_UNKNOWN" : isStale ? "STALE" : daysSinceLastPublish !== null && daysSinceLastPublish < 90 ? "ACTIVE" : "MAINTENANCE"
31577
31600
  }
31578
31601
  };
31579
31602
  }
@@ -31937,7 +31960,10 @@ var dependencyTools = [
31937
31960
  if (tree[resolvedKey]) return;
31938
31961
  const versionData = pkg.versions[resolvedVersion];
31939
31962
  if (!versionData) {
31940
- tree[resolvedKey] = { version: resolvedVersion, dependencies: {} };
31963
+ if (!failedPackages.has(name)) {
31964
+ failedPackages.add(name);
31965
+ tree[resolvedKey] = { version: resolvedVersion, dependencies: {}, failed: true };
31966
+ }
31941
31967
  return;
31942
31968
  }
31943
31969
  const deps = versionData.dependencies ?? {};
@@ -33475,7 +33501,7 @@ var writeTools = [
33475
33501
  // via the packument (step 3 succeeded), so we report success with a warning.
33476
33502
  {
33477
33503
  name: "npm_unpublish_version",
33478
- description: "Unpublish a specific version of a package. IRREVERSIBLE: once unpublished, the version cannot be re-published and will be blocked for 72 hours. Only works within 72 hours of the original publish for most packages. Requires explicit confirm: true to prevent accidents. Follows the npm CLI flow (mutate packument + delete tarball). For full-package unpublish use npm_unpublish_package.",
33504
+ description: "Unpublish a specific version of a package. IRREVERSIBLE: once unpublished, the version cannot be re-published and will be blocked for 72 hours. Only works within 72 hours of the original publish for most packages. Requires explicit confirm: true to prevent accidents. Follows the npm CLI flow (mutate packument + delete tarball). For full-package unpublish use npm_unpublish_package. Dist-tag handling: any dist-tag that pointed at the unpublished version is removed. Only `latest` is auto-reassigned (to the highest remaining stable version). Other tags like `next`/`beta` are left unset \u2014 reassign them explicitly with npm_dist_tag_set if needed.",
33479
33505
  annotations: {
33480
33506
  title: "Unpublish version",
33481
33507
  readOnlyHint: false,
@@ -34221,7 +34247,7 @@ var writeTools = [
34221
34247
  ];
34222
34248
 
34223
34249
  // src/index.ts
34224
- var version2 = true ? "0.11.9" : (await null).createRequire(import.meta.url)("../package.json").version;
34250
+ var version2 = true ? "0.11.12" : (await null).createRequire(import.meta.url)("../package.json").version;
34225
34251
  var subcommand = process.argv[2];
34226
34252
  if (subcommand === "version" || subcommand === "--version" || subcommand === "-v" || subcommand === "-V") {
34227
34253
  console.log(version2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/npmjs-mcp",
3
- "version": "0.11.9",
3
+ "version": "0.11.12",
4
4
  "mcpName": "io.github.YawLabs/npmjs-mcp",
5
5
  "description": "npm registry MCP server — package intelligence, security audits, and dependency analysis for AI assistants",
6
6
  "license": "MIT",