@yawlabs/npmjs-mcp 0.11.11 → 0.11.13

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 +68 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31105,8 +31105,12 @@ async function request(baseUrl, path, options) {
31105
31105
  debug(`${method} ${url2} -> ${res.status} ${elapsed}ms`);
31106
31106
  return { ok: true, status: res.status };
31107
31107
  }
31108
- const data = await res.json();
31108
+ const text = await res.text();
31109
31109
  debug(`${method} ${url2} -> ${res.status} ${elapsed}ms`);
31110
+ if (text.length === 0) {
31111
+ return { ok: true, status: res.status };
31112
+ }
31113
+ const data = JSON.parse(text);
31110
31114
  return { ok: true, status: res.status, data };
31111
31115
  } catch (err) {
31112
31116
  const message = err instanceof Error ? err.message : String(err);
@@ -31469,9 +31473,13 @@ var analysisTools = [
31469
31473
  if (latest) auditMap[name] = [latest];
31470
31474
  }
31471
31475
  let auditData = {};
31476
+ let auditSucceeded = false;
31472
31477
  if (Object.keys(auditMap).length > 0) {
31473
31478
  const auditRes = await registryPost("/-/npm/v1/security/advisories/bulk", auditMap);
31474
- if (auditRes.ok && auditRes.data) auditData = auditRes.data;
31479
+ if (auditRes.ok && auditRes.data) {
31480
+ auditData = auditRes.data;
31481
+ auditSucceeded = true;
31482
+ }
31475
31483
  }
31476
31484
  const results = partials.map(({ name, pkgRes, dlRes }) => {
31477
31485
  if (!pkgRes.ok) {
@@ -31482,8 +31490,9 @@ var analysisTools = [
31482
31490
  const latest = pkg["dist-tags"]?.latest;
31483
31491
  const latestVersion = latest ? pkg.versions[latest] : void 0;
31484
31492
  const versionKeys = Object.keys(pkg.versions);
31493
+ const wasAudited = auditSucceeded && name in auditMap;
31485
31494
  const advisories = auditData[name];
31486
- const vulnerabilities = Array.isArray(advisories) ? advisories.length : 0;
31495
+ const vulnerabilities = wasAudited ? Array.isArray(advisories) ? advisories.length : 0 : null;
31487
31496
  return {
31488
31497
  name,
31489
31498
  description: pkg.description,
@@ -31498,7 +31507,8 @@ var analysisTools = [
31498
31507
  hasReadme: !!(pkg.readme && pkg.readme.length > 0),
31499
31508
  repository: pkg.repository,
31500
31509
  homepage: pkg.homepage,
31501
- vulnerabilities
31510
+ vulnerabilities,
31511
+ auditReliable: wasAudited
31502
31512
  };
31503
31513
  });
31504
31514
  return { ok: true, status: 200, data: { comparison: results } };
@@ -31586,8 +31596,11 @@ var analysisTools = [
31586
31596
  // Holistic single-string verdict layered priority-first: a deprecated
31587
31597
  // package supersedes everything (don't use it), a vulnerable package
31588
31598
  // supersedes maintenance signals (active development doesn't undo a
31589
- // CVE), then staleness, recency, and the catch-all.
31590
- assessment: isDeprecated ? "DEPRECATED" : vulnerabilityCount !== null && vulnerabilityCount > 0 ? "VULNERABLE" : isStale ? "STALE" : daysSinceLastPublish !== null && daysSinceLastPublish < 90 ? "ACTIVE" : "MAINTENANCE"
31599
+ // CVE), then AUDIT_UNKNOWN when we couldn't verify vuln status (a 5xx
31600
+ // on the audit endpoint or a packument with no `latest` to audit) --
31601
+ // better to flag the unknown than confidently report ACTIVE on
31602
+ // unverified data. Then staleness, recency, and the catch-all.
31603
+ assessment: isDeprecated ? "DEPRECATED" : vulnerabilityCount !== null && vulnerabilityCount > 0 ? "VULNERABLE" : !auditReliable ? "AUDIT_UNKNOWN" : isStale ? "STALE" : daysSinceLastPublish !== null && daysSinceLastPublish < 90 ? "ACTIVE" : "MAINTENANCE"
31591
31604
  }
31592
31605
  };
31593
31606
  }
@@ -31951,7 +31964,10 @@ var dependencyTools = [
31951
31964
  if (tree[resolvedKey]) return;
31952
31965
  const versionData = pkg.versions[resolvedVersion];
31953
31966
  if (!versionData) {
31954
- tree[resolvedKey] = { version: resolvedVersion, dependencies: {}, failed: true };
31967
+ if (!failedPackages.has(name)) {
31968
+ failedPackages.add(name);
31969
+ tree[resolvedKey] = { version: resolvedVersion, dependencies: {}, failed: true };
31970
+ }
31955
31971
  return;
31956
31972
  }
31957
31973
  const deps = versionData.dependencies ?? {};
@@ -32141,6 +32157,15 @@ function classifyHookTarget(target) {
32141
32157
  return { type: "package", name: target };
32142
32158
  }
32143
32159
  function validateHookTarget(target) {
32160
+ if (typeof target !== "string" || target.length === 0) {
32161
+ return "Hook target is empty.";
32162
+ }
32163
+ if (target === "~") {
32164
+ return "Hook target '~' is missing the username (use '~your-username').";
32165
+ }
32166
+ if (target === "@") {
32167
+ return "Hook target '@' is missing the scope (use '@scope' or '@scope/pkg').";
32168
+ }
32144
32169
  const { type, name } = classifyHookTarget(target);
32145
32170
  if (type === "owner") return validateUsername(name);
32146
32171
  if (type === "scope") return validateScope(name);
@@ -32663,6 +32688,8 @@ var packageTools = [
32663
32688
  version: external_exports.string().optional().describe("Semver version or dist-tag (default: 'latest')")
32664
32689
  }),
32665
32690
  handler: async (input) => {
32691
+ const nameErr = validatePackageName(input.name);
32692
+ if (nameErr) return { ok: false, status: 400, error: nameErr };
32666
32693
  const ver = input.version ?? "latest";
32667
32694
  let typesPackage;
32668
32695
  if (input.name.startsWith("@")) {
@@ -33242,6 +33269,13 @@ var workflowTools = [
33242
33269
  });
33243
33270
  canPublishHeadless = false;
33244
33271
  }
33272
+ } else if (twoFactorAuth === "disabled" && readWriteTokens.length === 0) {
33273
+ checks.push({
33274
+ check: "Token capability",
33275
+ status: "fail",
33276
+ detail: `2FA is disabled but no read-write tokens found out of ${totalTokens} total. Need a token with publish permissions.`
33277
+ });
33278
+ canPublishHeadless = false;
33245
33279
  }
33246
33280
  if (isScoped && scope) {
33247
33281
  checks.push({
@@ -33413,7 +33447,19 @@ var writeTools = [
33413
33447
  for (const v of affected) {
33414
33448
  packument.versions[v].deprecated = input.message;
33415
33449
  }
33416
- const putRes = await registryPutAuth(`/${encPkg(input.name)}`, packument);
33450
+ if (!packument._rev) {
33451
+ return {
33452
+ ok: false,
33453
+ status: 500,
33454
+ error: `Packument for ${input.name} missing _rev -- cannot deprecate. Try again; this is usually transient.`
33455
+ };
33456
+ }
33457
+ delete packument._revisions;
33458
+ delete packument._attachments;
33459
+ const putRes = await registryPutAuth(
33460
+ `/${encPkg(input.name)}/-rev/${encodeURIComponent(packument._rev)}`,
33461
+ packument
33462
+ );
33417
33463
  if (!putRes.ok) return translateError(putRes, { pkg: input.name, op: "deprecate (write)" });
33418
33464
  return {
33419
33465
  ok: true,
@@ -33463,7 +33509,19 @@ var writeTools = [
33463
33509
  for (const v of affected) {
33464
33510
  packument.versions[v].deprecated = "";
33465
33511
  }
33466
- const putRes = await registryPutAuth(`/${encPkg(input.name)}`, packument);
33512
+ if (!packument._rev) {
33513
+ return {
33514
+ ok: false,
33515
+ status: 500,
33516
+ error: `Packument for ${input.name} missing _rev -- cannot undeprecate. Try again; this is usually transient.`
33517
+ };
33518
+ }
33519
+ delete packument._revisions;
33520
+ delete packument._attachments;
33521
+ const putRes = await registryPutAuth(
33522
+ `/${encPkg(input.name)}/-rev/${encodeURIComponent(packument._rev)}`,
33523
+ packument
33524
+ );
33467
33525
  if (!putRes.ok) return translateError(putRes, { pkg: input.name, op: "undeprecate (write)" });
33468
33526
  return {
33469
33527
  ok: true,
@@ -34235,7 +34293,7 @@ var writeTools = [
34235
34293
  ];
34236
34294
 
34237
34295
  // src/index.ts
34238
- var version2 = true ? "0.11.11" : (await null).createRequire(import.meta.url)("../package.json").version;
34296
+ var version2 = true ? "0.11.13" : (await null).createRequire(import.meta.url)("../package.json").version;
34239
34297
  var subcommand = process.argv[2];
34240
34298
  if (subcommand === "version" || subcommand === "--version" || subcommand === "-v" || subcommand === "-V") {
34241
34299
  console.log(version2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/npmjs-mcp",
3
- "version": "0.11.11",
3
+ "version": "0.11.13",
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",