@yawlabs/npmjs-mcp 0.3.0 → 0.4.0
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.
- package/dist/index.js +281 -94
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21087,6 +21087,78 @@ function downloadsGet(path) {
|
|
|
21087
21087
|
function replicateGet(path) {
|
|
21088
21088
|
return request(REPLICATE_URL, path);
|
|
21089
21089
|
}
|
|
21090
|
+
function parseSemver(v) {
|
|
21091
|
+
const m = v.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
21092
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
21093
|
+
}
|
|
21094
|
+
function cmpSemver(a, b) {
|
|
21095
|
+
for (let i = 0; i < 3; i++) {
|
|
21096
|
+
if (a[i] < b[i]) return -1;
|
|
21097
|
+
if (a[i] > b[i]) return 1;
|
|
21098
|
+
}
|
|
21099
|
+
return 0;
|
|
21100
|
+
}
|
|
21101
|
+
function maxSatisfying(versions, range) {
|
|
21102
|
+
const r = range.trim().replace(/^v/, "");
|
|
21103
|
+
if (versions.includes(r)) return r;
|
|
21104
|
+
let minInclusive = null;
|
|
21105
|
+
let maxExclusive = null;
|
|
21106
|
+
if (r.startsWith("^")) {
|
|
21107
|
+
const base = parseSemver(r.slice(1));
|
|
21108
|
+
if (!base) return null;
|
|
21109
|
+
minInclusive = base;
|
|
21110
|
+
if (base[0] > 0) maxExclusive = [base[0] + 1, 0, 0];
|
|
21111
|
+
else if (base[1] > 0) maxExclusive = [0, base[1] + 1, 0];
|
|
21112
|
+
else maxExclusive = [0, 0, base[2] + 1];
|
|
21113
|
+
} else if (r.startsWith("~")) {
|
|
21114
|
+
const base = parseSemver(r.slice(1));
|
|
21115
|
+
if (!base) return null;
|
|
21116
|
+
minInclusive = base;
|
|
21117
|
+
maxExclusive = [base[0], base[1] + 1, 0];
|
|
21118
|
+
} else if (r.startsWith(">=")) {
|
|
21119
|
+
const base = parseSemver(r.slice(2));
|
|
21120
|
+
if (!base) return null;
|
|
21121
|
+
minInclusive = base;
|
|
21122
|
+
} else if (r.startsWith("<=")) {
|
|
21123
|
+
const base = parseSemver(r.slice(2));
|
|
21124
|
+
if (!base) return null;
|
|
21125
|
+
maxExclusive = [base[0], base[1], base[2] + 1];
|
|
21126
|
+
} else {
|
|
21127
|
+
const xm = r.match(/^(\d+)(?:\.(\d+|x)(?:\.(\d+|x))?)?$/);
|
|
21128
|
+
if (xm) {
|
|
21129
|
+
const major = Number(xm[1]);
|
|
21130
|
+
const minor = xm[2] !== void 0 && xm[2] !== "x" ? Number(xm[2]) : null;
|
|
21131
|
+
if (minor === null) {
|
|
21132
|
+
minInclusive = [major, 0, 0];
|
|
21133
|
+
maxExclusive = [major + 1, 0, 0];
|
|
21134
|
+
} else {
|
|
21135
|
+
const patch = xm[3] !== void 0 && xm[3] !== "x" ? Number(xm[3]) : null;
|
|
21136
|
+
if (patch === null) {
|
|
21137
|
+
minInclusive = [major, minor, 0];
|
|
21138
|
+
maxExclusive = [major, minor + 1, 0];
|
|
21139
|
+
} else {
|
|
21140
|
+
return null;
|
|
21141
|
+
}
|
|
21142
|
+
}
|
|
21143
|
+
} else {
|
|
21144
|
+
return null;
|
|
21145
|
+
}
|
|
21146
|
+
}
|
|
21147
|
+
let best = null;
|
|
21148
|
+
let bestParsed = null;
|
|
21149
|
+
for (const v of versions) {
|
|
21150
|
+
if (v.includes("-") && !r.includes("-")) continue;
|
|
21151
|
+
const parsed = parseSemver(v);
|
|
21152
|
+
if (!parsed) continue;
|
|
21153
|
+
if (minInclusive && cmpSemver(parsed, minInclusive) < 0) continue;
|
|
21154
|
+
if (maxExclusive && cmpSemver(parsed, maxExclusive) >= 0) continue;
|
|
21155
|
+
if (!bestParsed || cmpSemver(parsed, bestParsed) > 0) {
|
|
21156
|
+
best = v;
|
|
21157
|
+
bestParsed = parsed;
|
|
21158
|
+
}
|
|
21159
|
+
}
|
|
21160
|
+
return best;
|
|
21161
|
+
}
|
|
21090
21162
|
|
|
21091
21163
|
// src/tools/access.ts
|
|
21092
21164
|
var accessTools = [
|
|
@@ -21184,12 +21256,9 @@ var analysisTools = [
|
|
|
21184
21256
|
handler: async (input) => {
|
|
21185
21257
|
const results = await Promise.all(
|
|
21186
21258
|
input.packages.map(async (name) => {
|
|
21187
|
-
const [pkgRes, dlRes
|
|
21259
|
+
const [pkgRes, dlRes] = await Promise.all([
|
|
21188
21260
|
registryGet(`/${encPkg(name)}`),
|
|
21189
|
-
downloadsGet(`/downloads/point/last-week/${encPkg(name)}`)
|
|
21190
|
-
registryPost("/-/npm/v1/security/advisories/bulk", {
|
|
21191
|
-
[name]: ["latest"]
|
|
21192
|
-
})
|
|
21261
|
+
downloadsGet(`/downloads/point/last-week/${encPkg(name)}`)
|
|
21193
21262
|
]);
|
|
21194
21263
|
if (!pkgRes.ok) {
|
|
21195
21264
|
return { name, error: pkgRes.error };
|
|
@@ -21198,6 +21267,15 @@ var analysisTools = [
|
|
|
21198
21267
|
const latest = pkg["dist-tags"]?.latest;
|
|
21199
21268
|
const latestVersion = latest ? pkg.versions[latest] : void 0;
|
|
21200
21269
|
const versionKeys = Object.keys(pkg.versions);
|
|
21270
|
+
let vulnerabilities = 0;
|
|
21271
|
+
if (latest) {
|
|
21272
|
+
const auditRes = await registryPost("/-/npm/v1/security/advisories/bulk", {
|
|
21273
|
+
[name]: [latest]
|
|
21274
|
+
});
|
|
21275
|
+
if (auditRes.ok && auditRes.data?.[name]) {
|
|
21276
|
+
vulnerabilities = auditRes.data[name].length;
|
|
21277
|
+
}
|
|
21278
|
+
}
|
|
21201
21279
|
return {
|
|
21202
21280
|
name,
|
|
21203
21281
|
description: pkg.description,
|
|
@@ -21212,7 +21290,7 @@ var analysisTools = [
|
|
|
21212
21290
|
hasReadme: !!(pkg.readme && pkg.readme.length > 0),
|
|
21213
21291
|
repository: pkg.repository,
|
|
21214
21292
|
homepage: pkg.homepage,
|
|
21215
|
-
vulnerabilities
|
|
21293
|
+
vulnerabilities
|
|
21216
21294
|
};
|
|
21217
21295
|
})
|
|
21218
21296
|
);
|
|
@@ -21243,6 +21321,16 @@ var analysisTools = [
|
|
|
21243
21321
|
const latest = pkg["dist-tags"]?.latest;
|
|
21244
21322
|
const latestVersion = latest ? pkg.versions[latest] : void 0;
|
|
21245
21323
|
const versionKeys = Object.keys(pkg.versions);
|
|
21324
|
+
let vulnerabilityCount = null;
|
|
21325
|
+
if (latest) {
|
|
21326
|
+
const auditRes = await registryPost("/-/npm/v1/security/advisories/bulk", {
|
|
21327
|
+
[input.name]: [latest]
|
|
21328
|
+
});
|
|
21329
|
+
if (auditRes.ok) {
|
|
21330
|
+
const advisories = auditRes.data?.[input.name];
|
|
21331
|
+
vulnerabilityCount = Array.isArray(advisories) ? advisories.length : 0;
|
|
21332
|
+
}
|
|
21333
|
+
}
|
|
21246
21334
|
const publishDates = versionKeys.map((v) => pkg.time[v]).filter(Boolean).map((d) => new Date(d).getTime()).sort((a, b) => b - a);
|
|
21247
21335
|
const now = Date.now();
|
|
21248
21336
|
const daysSinceLastPublish = publishDates.length > 0 ? Math.floor((now - publishDates[0]) / 864e5) : null;
|
|
@@ -21274,6 +21362,7 @@ var analysisTools = [
|
|
|
21274
21362
|
versionCount: versionKeys.length,
|
|
21275
21363
|
daysSinceLastPublish,
|
|
21276
21364
|
avgDaysBetweenReleases,
|
|
21365
|
+
vulnerabilityCount,
|
|
21277
21366
|
hasLicense,
|
|
21278
21367
|
hasReadme,
|
|
21279
21368
|
hasRepo,
|
|
@@ -21454,7 +21543,6 @@ var authTools = [
|
|
|
21454
21543
|
data: {
|
|
21455
21544
|
total: data.total,
|
|
21456
21545
|
tokens: data.objects.map((t) => ({
|
|
21457
|
-
token: t.token,
|
|
21458
21546
|
key: t.key,
|
|
21459
21547
|
readonly: t.readonly,
|
|
21460
21548
|
cidrWhitelist: t.cidr_whitelist,
|
|
@@ -21464,6 +21552,38 @@ var authTools = [
|
|
|
21464
21552
|
}
|
|
21465
21553
|
};
|
|
21466
21554
|
}
|
|
21555
|
+
},
|
|
21556
|
+
{
|
|
21557
|
+
name: "npm_user_packages",
|
|
21558
|
+
description: "List all packages published by a specific npm user. Shows package names and the user's access level for each. Requires authentication.",
|
|
21559
|
+
annotations: {
|
|
21560
|
+
title: "List user packages",
|
|
21561
|
+
readOnlyHint: true,
|
|
21562
|
+
destructiveHint: false,
|
|
21563
|
+
idempotentHint: true,
|
|
21564
|
+
openWorldHint: true
|
|
21565
|
+
},
|
|
21566
|
+
inputSchema: external_exports.object({
|
|
21567
|
+
username: external_exports.string().describe("npm username")
|
|
21568
|
+
}),
|
|
21569
|
+
handler: async (input) => {
|
|
21570
|
+
const authErr = requireAuth();
|
|
21571
|
+
if (authErr) return authErr;
|
|
21572
|
+
const res = await registryGetAuth(
|
|
21573
|
+
`/-/user/org.couchdb.user:${encodeURIComponent(input.username)}/package`
|
|
21574
|
+
);
|
|
21575
|
+
if (!res.ok) return res;
|
|
21576
|
+
const packages = Object.entries(res.data).map(([name, access]) => ({ name, access }));
|
|
21577
|
+
return {
|
|
21578
|
+
ok: true,
|
|
21579
|
+
status: 200,
|
|
21580
|
+
data: {
|
|
21581
|
+
username: input.username,
|
|
21582
|
+
packageCount: packages.length,
|
|
21583
|
+
packages
|
|
21584
|
+
}
|
|
21585
|
+
};
|
|
21586
|
+
}
|
|
21467
21587
|
}
|
|
21468
21588
|
];
|
|
21469
21589
|
|
|
@@ -21541,8 +21661,8 @@ var dependencyTools = [
|
|
|
21541
21661
|
else queue.push(run);
|
|
21542
21662
|
});
|
|
21543
21663
|
}
|
|
21544
|
-
async function resolve(name,
|
|
21545
|
-
const hintKey = `${name}@${
|
|
21664
|
+
async function resolve(name, versionHint2, currentDepth) {
|
|
21665
|
+
const hintKey = `${name}@${versionHint2}`;
|
|
21546
21666
|
if (resolved.has(hintKey) || currentDepth > maxDepth) return;
|
|
21547
21667
|
resolved.add(hintKey);
|
|
21548
21668
|
let pkg = packumentCache.get(name);
|
|
@@ -21550,19 +21670,21 @@ var dependencyTools = [
|
|
|
21550
21670
|
const res = await runLimited(() => registryGetAbbreviated(`/${encPkg(name)}`));
|
|
21551
21671
|
if (!res.ok) {
|
|
21552
21672
|
warnings.push(`Failed to fetch ${name}: ${res.error}`);
|
|
21553
|
-
tree[hintKey] = { version:
|
|
21673
|
+
tree[hintKey] = { version: versionHint2, dependencies: {} };
|
|
21554
21674
|
return;
|
|
21555
21675
|
}
|
|
21556
21676
|
pkg = res.data;
|
|
21557
21677
|
packumentCache.set(name, pkg);
|
|
21558
21678
|
}
|
|
21559
21679
|
let resolvedVersion;
|
|
21560
|
-
if (pkg.versions[
|
|
21561
|
-
resolvedVersion =
|
|
21562
|
-
} else if (pkg["dist-tags"][
|
|
21563
|
-
resolvedVersion = pkg["dist-tags"][
|
|
21680
|
+
if (pkg.versions[versionHint2]) {
|
|
21681
|
+
resolvedVersion = versionHint2;
|
|
21682
|
+
} else if (pkg["dist-tags"][versionHint2]) {
|
|
21683
|
+
resolvedVersion = pkg["dist-tags"][versionHint2];
|
|
21564
21684
|
} else {
|
|
21565
|
-
|
|
21685
|
+
const available = Object.keys(pkg.versions);
|
|
21686
|
+
const matched = maxSatisfying(available, versionHint2);
|
|
21687
|
+
resolvedVersion = matched ?? pkg["dist-tags"]?.latest ?? versionHint2;
|
|
21566
21688
|
}
|
|
21567
21689
|
const resolvedKey = `${name}@${resolvedVersion}`;
|
|
21568
21690
|
if (tree[resolvedKey]) return;
|
|
@@ -21578,12 +21700,14 @@ var dependencyTools = [
|
|
|
21578
21700
|
await Promise.all(tasks);
|
|
21579
21701
|
}
|
|
21580
21702
|
}
|
|
21581
|
-
|
|
21703
|
+
const versionHint = input.version ?? "latest";
|
|
21704
|
+
await resolve(input.name, versionHint, 1);
|
|
21705
|
+
const rootKey = Object.keys(tree).find((k) => k.startsWith(`${input.name}@`)) ?? `${input.name}@${versionHint}`;
|
|
21582
21706
|
return {
|
|
21583
21707
|
ok: true,
|
|
21584
21708
|
status: 200,
|
|
21585
21709
|
data: {
|
|
21586
|
-
root:
|
|
21710
|
+
root: rootKey,
|
|
21587
21711
|
depth: maxDepth,
|
|
21588
21712
|
totalPackages: Object.keys(tree).length,
|
|
21589
21713
|
tree,
|
|
@@ -21614,7 +21738,7 @@ var dependencyTools = [
|
|
|
21614
21738
|
const res = await registryGet(`/${encPkg(input.name)}/${ver}`);
|
|
21615
21739
|
if (!res.ok) return res;
|
|
21616
21740
|
const pkg = res.data;
|
|
21617
|
-
const
|
|
21741
|
+
const depEntries = Object.entries(pkg.dependencies ?? {});
|
|
21618
21742
|
const MAX_CONCURRENT = 10;
|
|
21619
21743
|
let active = 0;
|
|
21620
21744
|
const queue = [];
|
|
@@ -21632,21 +21756,25 @@ var dependencyTools = [
|
|
|
21632
21756
|
});
|
|
21633
21757
|
}
|
|
21634
21758
|
const depLicenses = await Promise.all(
|
|
21635
|
-
|
|
21636
|
-
const
|
|
21759
|
+
depEntries.map(async ([depName, depRange]) => {
|
|
21760
|
+
const abbrevRes = await runLimited(() => registryGetAbbreviated(`/${encPkg(depName)}`));
|
|
21761
|
+
if (!abbrevRes.ok) return { name: depName, version: depRange, license: "FETCH_ERROR" };
|
|
21762
|
+
const abbrev = abbrevRes.data;
|
|
21763
|
+
const available = Object.keys(abbrev.versions);
|
|
21764
|
+
const resolved = maxSatisfying(available, depRange) ?? abbrev["dist-tags"]?.latest;
|
|
21765
|
+
if (!resolved) return { name: depName, version: depRange, license: "UNKNOWN" };
|
|
21766
|
+
const verRes = await runLimited(() => registryGet(`/${encPkg(depName)}/${resolved}`));
|
|
21637
21767
|
return {
|
|
21638
21768
|
name: depName,
|
|
21639
|
-
|
|
21769
|
+
version: resolved,
|
|
21770
|
+
license: verRes.ok ? verRes.data?.license ?? "UNKNOWN" : "FETCH_ERROR"
|
|
21640
21771
|
};
|
|
21641
21772
|
})
|
|
21642
21773
|
);
|
|
21643
21774
|
const allowedSet = new Set(
|
|
21644
21775
|
input.allowed ?? ["MIT", "ISC", "BSD-2-Clause", "BSD-3-Clause", "Apache-2.0", "0BSD", "Unlicense"]
|
|
21645
21776
|
);
|
|
21646
|
-
const results = [
|
|
21647
|
-
{ name: pkg.name, version: pkg.version, license: pkg.license ?? "UNKNOWN" },
|
|
21648
|
-
...depLicenses.map((d) => ({ name: d.name, version: "latest", license: d.license }))
|
|
21649
|
-
];
|
|
21777
|
+
const results = [{ name: pkg.name, version: pkg.version, license: pkg.license ?? "UNKNOWN" }, ...depLicenses];
|
|
21650
21778
|
const flagged = results.filter((r) => !allowedSet.has(r.license));
|
|
21651
21779
|
return {
|
|
21652
21780
|
ok: true,
|
|
@@ -21744,57 +21872,6 @@ var downloadTools = [
|
|
|
21744
21872
|
}
|
|
21745
21873
|
];
|
|
21746
21874
|
|
|
21747
|
-
// src/tools/hooks.ts
|
|
21748
|
-
var hookTools = [
|
|
21749
|
-
{
|
|
21750
|
-
name: "npm_hooks",
|
|
21751
|
-
description: "List all npm webhooks configured for the authenticated user. Shows hook type (package, scope, or owner), endpoint URL, delivery status, and last response code.",
|
|
21752
|
-
annotations: {
|
|
21753
|
-
title: "List npm hooks",
|
|
21754
|
-
readOnlyHint: true,
|
|
21755
|
-
destructiveHint: false,
|
|
21756
|
-
idempotentHint: true,
|
|
21757
|
-
openWorldHint: true
|
|
21758
|
-
},
|
|
21759
|
-
inputSchema: external_exports.object({
|
|
21760
|
-
package: external_exports.string().optional().describe("Filter hooks by package name"),
|
|
21761
|
-
limit: external_exports.number().min(1).max(100).optional().describe("Max results (default: 25)"),
|
|
21762
|
-
offset: external_exports.number().min(0).optional().describe("Pagination offset")
|
|
21763
|
-
}),
|
|
21764
|
-
handler: async (input) => {
|
|
21765
|
-
const authErr = requireAuth();
|
|
21766
|
-
if (authErr) return authErr;
|
|
21767
|
-
const params = new URLSearchParams();
|
|
21768
|
-
if (input.package) params.set("package", input.package);
|
|
21769
|
-
if (input.limit !== void 0) params.set("limit", String(input.limit));
|
|
21770
|
-
if (input.offset !== void 0) params.set("offset", String(input.offset));
|
|
21771
|
-
const qs = params.toString();
|
|
21772
|
-
const path = `/-/npm/v1/hooks${qs ? `?${qs}` : ""}`;
|
|
21773
|
-
const res = await registryGetAuth(path);
|
|
21774
|
-
if (!res.ok) return res;
|
|
21775
|
-
const data = res.data;
|
|
21776
|
-
return {
|
|
21777
|
-
ok: true,
|
|
21778
|
-
status: 200,
|
|
21779
|
-
data: {
|
|
21780
|
-
total: data.total,
|
|
21781
|
-
hooks: data.objects.map((h) => ({
|
|
21782
|
-
id: h.id,
|
|
21783
|
-
type: h.type,
|
|
21784
|
-
name: h.name,
|
|
21785
|
-
endpoint: h.endpoint,
|
|
21786
|
-
status: h.status,
|
|
21787
|
-
lastDelivery: h.last_delivery,
|
|
21788
|
-
lastResponseCode: h.response_code,
|
|
21789
|
-
created: h.created,
|
|
21790
|
-
updated: h.updated
|
|
21791
|
-
}))
|
|
21792
|
-
}
|
|
21793
|
-
};
|
|
21794
|
-
}
|
|
21795
|
-
}
|
|
21796
|
-
];
|
|
21797
|
-
|
|
21798
21875
|
// src/tools/orgs.ts
|
|
21799
21876
|
var orgTools = [
|
|
21800
21877
|
{
|
|
@@ -22019,7 +22096,7 @@ var packageTools = [
|
|
|
22019
22096
|
},
|
|
22020
22097
|
{
|
|
22021
22098
|
name: "npm_versions",
|
|
22022
|
-
description: "List
|
|
22099
|
+
description: "List published versions of a package with their publish dates, ordered newest first. Returns up to `limit` versions (default 50). Set limit=0 to return all.",
|
|
22023
22100
|
annotations: {
|
|
22024
22101
|
title: "List versions",
|
|
22025
22102
|
readOnlyHint: true,
|
|
@@ -22028,25 +22105,29 @@ var packageTools = [
|
|
|
22028
22105
|
openWorldHint: true
|
|
22029
22106
|
},
|
|
22030
22107
|
inputSchema: external_exports.object({
|
|
22031
|
-
name: external_exports.string().describe("Package name")
|
|
22108
|
+
name: external_exports.string().describe("Package name"),
|
|
22109
|
+
limit: external_exports.number().min(0).optional().describe("Max versions to return, newest first (default 50, 0 = all)")
|
|
22032
22110
|
}),
|
|
22033
22111
|
handler: async (input) => {
|
|
22034
22112
|
const res = await registryGet(`/${encPkg(input.name)}`);
|
|
22035
22113
|
if (!res.ok) return res;
|
|
22036
22114
|
const pkg = res.data;
|
|
22037
|
-
const
|
|
22115
|
+
const limit = input.limit ?? 50;
|
|
22116
|
+
const allVersions = Object.keys(pkg.versions).map((v) => ({
|
|
22038
22117
|
version: v,
|
|
22039
22118
|
date: pkg.time[v],
|
|
22040
22119
|
deprecated: pkg.versions[v].deprecated,
|
|
22041
22120
|
npmUser: pkg.versions[v]._npmUser?.name
|
|
22042
22121
|
})).sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
22122
|
+
const versions = limit > 0 ? allVersions.slice(0, limit) : allVersions;
|
|
22043
22123
|
return {
|
|
22044
22124
|
ok: true,
|
|
22045
22125
|
status: 200,
|
|
22046
22126
|
data: {
|
|
22047
22127
|
name: pkg.name,
|
|
22048
22128
|
distTags: pkg["dist-tags"],
|
|
22049
|
-
total:
|
|
22129
|
+
total: allVersions.length,
|
|
22130
|
+
showing: versions.length,
|
|
22050
22131
|
versions
|
|
22051
22132
|
}
|
|
22052
22133
|
};
|
|
@@ -22091,6 +22172,61 @@ var packageTools = [
|
|
|
22091
22172
|
handler: async (input) => {
|
|
22092
22173
|
return registryGet(`/-/package/${encPkg(input.name)}/dist-tags`);
|
|
22093
22174
|
}
|
|
22175
|
+
},
|
|
22176
|
+
{
|
|
22177
|
+
name: "npm_types",
|
|
22178
|
+
description: "Check TypeScript type support for a package \u2014 whether it ships built-in types (types/typings field) or has a DefinitelyTyped companion (@types/* package).",
|
|
22179
|
+
annotations: {
|
|
22180
|
+
title: "Check TypeScript types",
|
|
22181
|
+
readOnlyHint: true,
|
|
22182
|
+
destructiveHint: false,
|
|
22183
|
+
idempotentHint: true,
|
|
22184
|
+
openWorldHint: true
|
|
22185
|
+
},
|
|
22186
|
+
inputSchema: external_exports.object({
|
|
22187
|
+
name: external_exports.string().describe("Package name (e.g. 'express' or '@anthropic-ai/sdk')"),
|
|
22188
|
+
version: external_exports.string().optional().describe("Semver version or dist-tag (default: 'latest')")
|
|
22189
|
+
}),
|
|
22190
|
+
handler: async (input) => {
|
|
22191
|
+
const ver = input.version ?? "latest";
|
|
22192
|
+
let typesPackage;
|
|
22193
|
+
if (input.name.startsWith("@")) {
|
|
22194
|
+
const withoutAt = input.name.slice(1);
|
|
22195
|
+
typesPackage = `@types/${withoutAt.replace("/", "__")}`;
|
|
22196
|
+
} else {
|
|
22197
|
+
typesPackage = `@types/${input.name}`;
|
|
22198
|
+
}
|
|
22199
|
+
const [versionRes, typesRes] = await Promise.all([
|
|
22200
|
+
registryGet(`/${encPkg(input.name)}/${ver}`),
|
|
22201
|
+
registryGet(`/${encPkg(typesPackage)}`)
|
|
22202
|
+
]);
|
|
22203
|
+
if (!versionRes.ok) return versionRes;
|
|
22204
|
+
const v = versionRes.data;
|
|
22205
|
+
const hasBuiltinTypes = !!(v.types || v.typings);
|
|
22206
|
+
const typesEntry = hasBuiltinTypes ? v.types ?? v.typings : void 0;
|
|
22207
|
+
const hasTypesPackage = typesRes.ok;
|
|
22208
|
+
const typesPackageLatest = hasTypesPackage ? typesRes.data?.["dist-tags"]?.latest : void 0;
|
|
22209
|
+
let recommendation;
|
|
22210
|
+
if (hasBuiltinTypes) {
|
|
22211
|
+
recommendation = "Built-in types included \u2014 no additional install needed.";
|
|
22212
|
+
} else if (hasTypesPackage) {
|
|
22213
|
+
recommendation = `Install types separately: npm install -D ${typesPackage}`;
|
|
22214
|
+
} else {
|
|
22215
|
+
recommendation = "No TypeScript types available (built-in or @types).";
|
|
22216
|
+
}
|
|
22217
|
+
return {
|
|
22218
|
+
ok: true,
|
|
22219
|
+
status: 200,
|
|
22220
|
+
data: {
|
|
22221
|
+
name: v.name,
|
|
22222
|
+
version: v.version,
|
|
22223
|
+
builtinTypes: hasBuiltinTypes,
|
|
22224
|
+
typesEntry,
|
|
22225
|
+
typesPackage: hasTypesPackage ? { name: typesPackage, latest: typesPackageLatest } : null,
|
|
22226
|
+
recommendation
|
|
22227
|
+
}
|
|
22228
|
+
};
|
|
22229
|
+
}
|
|
22094
22230
|
}
|
|
22095
22231
|
];
|
|
22096
22232
|
|
|
@@ -22157,7 +22293,7 @@ var registryTools = [
|
|
|
22157
22293
|
},
|
|
22158
22294
|
{
|
|
22159
22295
|
name: "npm_recent_changes",
|
|
22160
|
-
description: "Get the most recent package publishes/updates from the npm registry via the CouchDB changes feed.",
|
|
22296
|
+
description: "Get the most recent package publishes/updates from the npm registry via the CouchDB changes feed. Note: uses replicate.npmjs.com which may have intermittent availability.",
|
|
22161
22297
|
annotations: {
|
|
22162
22298
|
title: "Recent registry changes",
|
|
22163
22299
|
readOnlyHint: true,
|
|
@@ -22170,21 +22306,20 @@ var registryTools = [
|
|
|
22170
22306
|
}),
|
|
22171
22307
|
handler: async (input) => {
|
|
22172
22308
|
const limit = input.limit ?? 25;
|
|
22173
|
-
const dbRes = await
|
|
22174
|
-
|
|
22175
|
-
|
|
22176
|
-
|
|
22309
|
+
const [dbRes, changesRes] = await Promise.all([
|
|
22310
|
+
replicateGet("/"),
|
|
22311
|
+
replicateGet(`/_changes?limit=${limit}&descending=true`)
|
|
22312
|
+
]);
|
|
22177
22313
|
if (!changesRes.ok) return changesRes;
|
|
22178
22314
|
const changes = changesRes.data.results.map((r) => ({
|
|
22179
22315
|
package: r.id,
|
|
22180
|
-
seq: r.seq,
|
|
22181
22316
|
rev: r.changes[0]?.rev
|
|
22182
22317
|
}));
|
|
22183
22318
|
return {
|
|
22184
22319
|
ok: true,
|
|
22185
22320
|
status: 200,
|
|
22186
22321
|
data: {
|
|
22187
|
-
totalPackages: dbRes.data.doc_count,
|
|
22322
|
+
totalPackages: dbRes.ok ? dbRes.data.doc_count : null,
|
|
22188
22323
|
changes
|
|
22189
22324
|
}
|
|
22190
22325
|
};
|
|
@@ -22230,9 +22365,7 @@ var searchTools = [
|
|
|
22230
22365
|
publisher: obj.package.publisher,
|
|
22231
22366
|
keywords: obj.package.keywords,
|
|
22232
22367
|
links: obj.package.links,
|
|
22233
|
-
score: obj.score.detail
|
|
22234
|
-
downloads: obj.downloads,
|
|
22235
|
-
dependents: obj.dependents
|
|
22368
|
+
score: obj.score.detail
|
|
22236
22369
|
}));
|
|
22237
22370
|
return { ok: true, status: 200, data: { total: res.data.total, results } };
|
|
22238
22371
|
}
|
|
@@ -22243,7 +22376,7 @@ var searchTools = [
|
|
|
22243
22376
|
var securityTools = [
|
|
22244
22377
|
{
|
|
22245
22378
|
name: "npm_audit",
|
|
22246
|
-
description: "
|
|
22379
|
+
description: "Quick vulnerability check for specific packages and versions using the bulk advisory API. Returns matching advisories with severity, CVEs, and patched versions. For richer detail (CVSS scores, CWEs, fix recommendations), use npm_audit_deep instead.",
|
|
22247
22380
|
annotations: {
|
|
22248
22381
|
title: "Audit packages",
|
|
22249
22382
|
readOnlyHint: true,
|
|
@@ -22260,7 +22393,7 @@ var securityTools = [
|
|
|
22260
22393
|
},
|
|
22261
22394
|
{
|
|
22262
22395
|
name: "npm_audit_deep",
|
|
22263
|
-
description: "
|
|
22396
|
+
description: "Full security audit on a dependency set \u2014 returns detailed advisories with CVSS scores, CWEs, affected version ranges, fix recommendations, and full vulnerability metadata. Uses the npm audit v1 endpoint which provides richer detail than the bulk advisory API (npm_audit). Requires you to provide the dependency map (use npm_dependencies to get it first).",
|
|
22264
22397
|
annotations: {
|
|
22265
22398
|
title: "Deep security audit",
|
|
22266
22399
|
readOnlyHint: true,
|
|
@@ -22302,6 +22435,60 @@ var securityTools = [
|
|
|
22302
22435
|
}
|
|
22303
22436
|
];
|
|
22304
22437
|
|
|
22438
|
+
// src/tools/trust.ts
|
|
22439
|
+
var trustTools = [
|
|
22440
|
+
{
|
|
22441
|
+
name: "npm_trusted_publishers",
|
|
22442
|
+
description: "List trusted publishing configurations for a package. Shows OIDC trust relationships with CI/CD providers (GitHub Actions, GitLab CI, CircleCI) that allow tokenless publishing. Requires authentication with write access to the package.",
|
|
22443
|
+
annotations: {
|
|
22444
|
+
title: "List trusted publishers",
|
|
22445
|
+
readOnlyHint: true,
|
|
22446
|
+
destructiveHint: false,
|
|
22447
|
+
idempotentHint: true,
|
|
22448
|
+
openWorldHint: true
|
|
22449
|
+
},
|
|
22450
|
+
inputSchema: external_exports.object({
|
|
22451
|
+
name: external_exports.string().describe("Package name (e.g. 'express' or '@yawlabs/npmjs-mcp')")
|
|
22452
|
+
}),
|
|
22453
|
+
handler: async (input) => {
|
|
22454
|
+
const authErr = requireAuth();
|
|
22455
|
+
if (authErr) return authErr;
|
|
22456
|
+
const res = await registryGetAuth(`/-/package/${encPkg(input.name)}/trust`);
|
|
22457
|
+
if (!res.ok) return res;
|
|
22458
|
+
const configs = (res.data ?? []).map((c) => {
|
|
22459
|
+
const result = {
|
|
22460
|
+
id: c.id,
|
|
22461
|
+
provider: c.type
|
|
22462
|
+
};
|
|
22463
|
+
if (c.type === "github") {
|
|
22464
|
+
result.repository = c.claims?.repository;
|
|
22465
|
+
const workflowRef = c.claims?.workflow_ref;
|
|
22466
|
+
result.workflowFile = workflowRef?.file;
|
|
22467
|
+
result.environment = c.claims?.environment;
|
|
22468
|
+
} else if (c.type === "gitlab") {
|
|
22469
|
+
result.project = c.claims?.project_path;
|
|
22470
|
+
const configRef = c.claims?.ci_config_ref_uri;
|
|
22471
|
+
result.configFile = configRef?.file;
|
|
22472
|
+
result.environment = c.claims?.environment;
|
|
22473
|
+
} else if (c.type === "circleci") {
|
|
22474
|
+
result.project = c.claims?.project_id;
|
|
22475
|
+
result.context = c.claims?.context_ids;
|
|
22476
|
+
}
|
|
22477
|
+
return result;
|
|
22478
|
+
});
|
|
22479
|
+
return {
|
|
22480
|
+
ok: true,
|
|
22481
|
+
status: 200,
|
|
22482
|
+
data: {
|
|
22483
|
+
package: input.name,
|
|
22484
|
+
trustedPublisherCount: configs.length,
|
|
22485
|
+
trustedPublishers: configs
|
|
22486
|
+
}
|
|
22487
|
+
};
|
|
22488
|
+
}
|
|
22489
|
+
}
|
|
22490
|
+
];
|
|
22491
|
+
|
|
22305
22492
|
// src/tools/workflows.ts
|
|
22306
22493
|
var workflowTools = [
|
|
22307
22494
|
{
|
|
@@ -22576,7 +22763,7 @@ var workflowTools = [
|
|
|
22576
22763
|
];
|
|
22577
22764
|
|
|
22578
22765
|
// src/index.ts
|
|
22579
|
-
var version2 = true ? "0.
|
|
22766
|
+
var version2 = true ? "0.4.0" : (await null).createRequire(import.meta.url)("../package.json").version;
|
|
22580
22767
|
var subcommand = process.argv[2];
|
|
22581
22768
|
if (subcommand === "version" || subcommand === "--version") {
|
|
22582
22769
|
console.log(version2);
|
|
@@ -22594,7 +22781,7 @@ var allTools = [
|
|
|
22594
22781
|
...orgTools,
|
|
22595
22782
|
...accessTools,
|
|
22596
22783
|
...provenanceTools,
|
|
22597
|
-
...
|
|
22784
|
+
...trustTools,
|
|
22598
22785
|
...workflowTools
|
|
22599
22786
|
];
|
|
22600
22787
|
var server = new McpServer({
|
package/package.json
CHANGED