@nekzus/mcp-server 1.16.2 → 1.18.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/README.md +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -50
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -699,13 +699,19 @@ export async function handleNpmDeps(args) {
|
|
|
699
699
|
version: depVersion,
|
|
700
700
|
}));
|
|
701
701
|
};
|
|
702
|
+
const actualVersion = rawData.version || version; // Use version from response if available
|
|
703
|
+
const finalPackageName = `${name}@${actualVersion}`;
|
|
704
|
+
// Fetch transitive dependencies from deps.dev to provide deep topological insights
|
|
705
|
+
const transitiveGraphRaw = await fetchTransitiveDependenciesFromDepsDev(name, actualVersion);
|
|
706
|
+
// Erase root package from the graph to avoid self-counting if returned
|
|
707
|
+
const transitiveGraph = transitiveGraphRaw.filter((dep) => dep.name !== name);
|
|
702
708
|
const depData = {
|
|
703
709
|
dependencies: mapDeps(rawData.dependencies),
|
|
704
710
|
devDependencies: mapDeps(rawData.devDependencies),
|
|
705
711
|
peerDependencies: mapDeps(rawData.peerDependencies),
|
|
712
|
+
transitiveCount: transitiveGraph.length,
|
|
713
|
+
transitiveGraph: transitiveGraph,
|
|
706
714
|
};
|
|
707
|
-
const actualVersion = rawData.version || version; // Use version from response if available
|
|
708
|
-
const finalPackageName = `${name}@${actualVersion}`;
|
|
709
715
|
// Store with the actual resolved package name if 'latest' was used
|
|
710
716
|
cacheSet(cacheKey, { depData, packageNameForCache: finalPackageName }, CACHE_TTL_MEDIUM);
|
|
711
717
|
return {
|
|
@@ -713,7 +719,7 @@ export async function handleNpmDeps(args) {
|
|
|
713
719
|
status: 'success',
|
|
714
720
|
error: null,
|
|
715
721
|
data: depData,
|
|
716
|
-
message: `Dependencies for ${finalPackageName}`,
|
|
722
|
+
message: `Dependencies for ${finalPackageName} (Direct: ${depData.dependencies.length}, Transitive: ${depData.transitiveCount})`,
|
|
717
723
|
};
|
|
718
724
|
}
|
|
719
725
|
catch (error) {
|
|
@@ -1009,23 +1015,32 @@ export async function handleNpmSize(args) {
|
|
|
1009
1015
|
};
|
|
1010
1016
|
}
|
|
1011
1017
|
}
|
|
1012
|
-
// Helper to
|
|
1013
|
-
async function
|
|
1018
|
+
// Helper to fetch full transitive dependency graph from deps.dev
|
|
1019
|
+
async function fetchTransitiveDependenciesFromDepsDev(pkgName, version) {
|
|
1014
1020
|
try {
|
|
1015
|
-
const
|
|
1021
|
+
const encodedName = encodeURIComponent(pkgName);
|
|
1022
|
+
const encodedVersion = encodeURIComponent(version);
|
|
1023
|
+
const url = `https://api.deps.dev/v3/systems/npm/packages/${encodedName}/versions/${encodedVersion}:dependencies`;
|
|
1024
|
+
const response = await fetch(url, {
|
|
1016
1025
|
headers: { Accept: 'application/json', 'User-Agent': 'NPM-Sentinel-MCP' },
|
|
1017
1026
|
});
|
|
1018
|
-
if (!response.ok)
|
|
1019
|
-
|
|
1027
|
+
if (!response.ok) {
|
|
1028
|
+
console.warn(`deps.dev API returned ${response.status} for ${pkgName}@${version}`);
|
|
1029
|
+
return [];
|
|
1030
|
+
}
|
|
1020
1031
|
const data = (await response.json());
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1032
|
+
if (!data.nodes || !Array.isArray(data.nodes))
|
|
1033
|
+
return [];
|
|
1034
|
+
return data.nodes
|
|
1035
|
+
.filter((node) => node.versionKey?.name)
|
|
1036
|
+
.map((node) => ({
|
|
1037
|
+
name: node.versionKey.name,
|
|
1038
|
+
version: node.versionKey.version,
|
|
1039
|
+
}));
|
|
1025
1040
|
}
|
|
1026
1041
|
catch (error) {
|
|
1027
|
-
console.error(`Error fetching dependencies for ${pkgName}:`, error);
|
|
1028
|
-
return
|
|
1042
|
+
console.error(`Error fetching transitive dependencies from deps.dev for ${pkgName}:`, error);
|
|
1043
|
+
return [];
|
|
1029
1044
|
}
|
|
1030
1045
|
}
|
|
1031
1046
|
// Helper to resolve 'latest' tag to actual version number
|
|
@@ -1107,31 +1122,19 @@ export async function handleNpmVulnerabilities(args) {
|
|
|
1107
1122
|
});
|
|
1108
1123
|
}
|
|
1109
1124
|
};
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
// If version is 'latest' or undefined, we settled it in addToQuery, but for fetching deps we need a concrete version
|
|
1124
|
-
// If we don't have one, we might need to resolve it again or let getPackageDependencies handle 'latest'
|
|
1125
|
-
// getPackageDependencies handles 'latest' by default.
|
|
1126
|
-
const { dependencies } = await getPackageDependencies(name, version || 'latest');
|
|
1127
|
-
// Process children
|
|
1128
|
-
const children = Object.entries(dependencies);
|
|
1129
|
-
await Promise.all(children.map(async ([depName, depVersion]) => {
|
|
1130
|
-
const cleanVersion = depVersion.replace(/[\^~]/g, '');
|
|
1131
|
-
if (/^\d+\.\d+\.\d+/.test(cleanVersion)) {
|
|
1132
|
-
await processPackage(depName, cleanVersion, currentDepth + 1);
|
|
1133
|
-
}
|
|
1134
|
-
}));
|
|
1125
|
+
const processPackage = async (name, version) => {
|
|
1126
|
+
const safeVersion = version || 'latest';
|
|
1127
|
+
// Always add the root package (depth 0 logic)
|
|
1128
|
+
addToQuery(name, safeVersion, false);
|
|
1129
|
+
// Try to get all transitive dependencies in a single call to deps.dev
|
|
1130
|
+
// They require a concrete version (or we pass exactly what we have)
|
|
1131
|
+
const allDeps = await fetchTransitiveDependenciesFromDepsDev(name, safeVersion);
|
|
1132
|
+
for (const dep of allDeps) {
|
|
1133
|
+
// Avoid adding the root package itself again, which is included in the graph
|
|
1134
|
+
if (dep.name === name)
|
|
1135
|
+
continue;
|
|
1136
|
+
addToQuery(dep.name, dep.version, true);
|
|
1137
|
+
}
|
|
1135
1138
|
};
|
|
1136
1139
|
const validationErrors = [];
|
|
1137
1140
|
const validPackagesToProcess = packagesToProcess.filter((pkgInput) => {
|
|
@@ -1203,14 +1206,12 @@ export async function handleNpmVulnerabilities(args) {
|
|
|
1203
1206
|
version = resolved;
|
|
1204
1207
|
}
|
|
1205
1208
|
}
|
|
1206
|
-
// Start
|
|
1207
|
-
await processPackage(name, version
|
|
1209
|
+
// Start fetching dependencies with deps.dev
|
|
1210
|
+
await processPackage(name, version);
|
|
1208
1211
|
// Ecosystem Check: Scan associated packages that share the same version
|
|
1209
1212
|
if (ECOSYSTEM_MAP[name]) {
|
|
1210
1213
|
for (const associatedPkg of ECOSYSTEM_MAP[name]) {
|
|
1211
|
-
|
|
1212
|
-
// so they are checked fully.
|
|
1213
|
-
await processPackage(associatedPkg, version, 0);
|
|
1214
|
+
await processPackage(associatedPkg, version);
|
|
1214
1215
|
}
|
|
1215
1216
|
}
|
|
1216
1217
|
}));
|
|
@@ -2197,7 +2198,7 @@ export async function handleNpmPackageReadme(args) {
|
|
|
2197
2198
|
}
|
|
2198
2199
|
const processedResults = await Promise.all(packagesToProcess.map(async (pkgInput) => {
|
|
2199
2200
|
let name = '';
|
|
2200
|
-
let versionTag
|
|
2201
|
+
let versionTag; // Explicitly undefined if not specified
|
|
2201
2202
|
if (typeof pkgInput === 'string') {
|
|
2202
2203
|
const atIdx = pkgInput.lastIndexOf('@');
|
|
2203
2204
|
if (atIdx > 0) {
|
|
@@ -2720,7 +2721,7 @@ export async function handleNpmRepoStats(args) {
|
|
|
2720
2721
|
cacheSet(cacheKey, resultNoRepo, CACHE_TTL_LONG);
|
|
2721
2722
|
return resultNoRepo;
|
|
2722
2723
|
}
|
|
2723
|
-
const githubMatch = repoUrl.match(/github\.com[
|
|
2724
|
+
const githubMatch = repoUrl.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
|
|
2724
2725
|
if (!githubMatch) {
|
|
2725
2726
|
const resultNotGitHub = {
|
|
2726
2727
|
packageInput: pkgInput,
|
|
@@ -3021,7 +3022,7 @@ export async function handleNpmChangelogAnalysis(args) {
|
|
|
3021
3022
|
}
|
|
3022
3023
|
const processedResults = await Promise.all(packagesToProcess.map(async (pkgInput) => {
|
|
3023
3024
|
let name = '';
|
|
3024
|
-
let versionQueried
|
|
3025
|
+
let versionQueried;
|
|
3025
3026
|
if (typeof pkgInput === 'string') {
|
|
3026
3027
|
const atIdx = pkgInput.lastIndexOf('@');
|
|
3027
3028
|
if (atIdx > 0) {
|
|
@@ -3118,7 +3119,7 @@ export async function handleNpmChangelogAnalysis(args) {
|
|
|
3118
3119
|
cacheSet(cacheKey, resultNoRepo, CACHE_TTL_MEDIUM);
|
|
3119
3120
|
return resultNoRepo;
|
|
3120
3121
|
}
|
|
3121
|
-
const githubMatch = repositoryUrl.match(/github\.com[
|
|
3122
|
+
const githubMatch = repositoryUrl.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
|
|
3122
3123
|
if (!githubMatch) {
|
|
3123
3124
|
const resultNotGitHub = {
|
|
3124
3125
|
packageInput: pkgInput,
|
|
@@ -3257,7 +3258,7 @@ export async function handleNpmAlternatives(args) {
|
|
|
3257
3258
|
}
|
|
3258
3259
|
const processedResults = await Promise.all(packagesToProcess.map(async (pkgInput) => {
|
|
3259
3260
|
let originalPackageName = '';
|
|
3260
|
-
let versionQueried
|
|
3261
|
+
let versionQueried;
|
|
3261
3262
|
if (typeof pkgInput === 'string') {
|
|
3262
3263
|
const atIdx = pkgInput.lastIndexOf('@');
|
|
3263
3264
|
if (atIdx > 0) {
|
|
@@ -3432,7 +3433,7 @@ export const configSchema = z.object({
|
|
|
3432
3433
|
NPM_REGISTRY_URL: z.string().optional().describe('URL of the NPM registry to use'),
|
|
3433
3434
|
});
|
|
3434
3435
|
// Create server function for Smithery CLI
|
|
3435
|
-
export default function createServer({ config
|
|
3436
|
+
export default function createServer({ config }) {
|
|
3436
3437
|
// Apply config overrides
|
|
3437
3438
|
if (config.NPM_REGISTRY_URL) {
|
|
3438
3439
|
NPM_REGISTRY_URL = config.NPM_REGISTRY_URL.replace(/\/$/, '');
|