@nekzus/mcp-server 1.19.0-alpha.1 → 1.19.0-alpha.3

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 CHANGED
@@ -1014,6 +1014,40 @@ async function fetchTransitiveDependenciesFromDepsDev(pkgName, version) {
1014
1014
  return [];
1015
1015
  }
1016
1016
  }
1017
+ export async function fetchRepoStatsFromDepsDev(owner, repo, ignoreCache = false) {
1018
+ const projectKey = encodeURIComponent(`github.com/${owner}/${repo}`);
1019
+ const cacheKey = generateCacheKey('depsDevProject', owner, repo);
1020
+ const cached = ignoreCache ? undefined : cacheGet(cacheKey);
1021
+ if (cached)
1022
+ return cached;
1023
+ try {
1024
+ const response = await fetchWithRetry(`https://api.deps.dev/v3alpha/projects/${projectKey}`, {}, { maxRetries: 1 });
1025
+ if (!response.ok)
1026
+ return null;
1027
+ const data = (await response.json());
1028
+ const result = {
1029
+ starsCount: data.starsCount ?? 0,
1030
+ forksCount: data.forksCount ?? 0,
1031
+ openIssuesCount: data.openIssuesCount ?? 0,
1032
+ license: data.license ?? 'unknown',
1033
+ description: data.description ?? '',
1034
+ homepage: data.homepage ?? '',
1035
+ scorecard: data.scorecard ? {
1036
+ overallScore: data.scorecard.overallScore,
1037
+ checks: (data.scorecard.checks || []).map((c) => ({
1038
+ name: c.name,
1039
+ score: c.score,
1040
+ reason: c.reason,
1041
+ })),
1042
+ } : undefined,
1043
+ };
1044
+ cacheSet(cacheKey, result, CACHE_TTL_VERY_LONG);
1045
+ return result;
1046
+ }
1047
+ catch {
1048
+ return null;
1049
+ }
1050
+ }
1017
1051
  // Helper to resolve 'latest' tag to actual version number
1018
1052
  async function resolveLatestVersion(packageName) {
1019
1053
  try {
@@ -1619,7 +1653,7 @@ export async function getLocalPackageMetrics(name, ignoreCache = false) {
1619
1653
  catch (dlError) {
1620
1654
  console.debug(`Could not fetch downloads for ${name}: ${dlError}`);
1621
1655
  }
1622
- // 3. Fetch GitHub stats (optional, graceful degradation)
1656
+ // 3. Fetch GitHub stats via deps.dev (optional, graceful degradation)
1623
1657
  let github = {
1624
1658
  starsCount: 0,
1625
1659
  forksCount: 0,
@@ -1627,6 +1661,7 @@ export async function getLocalPackageMetrics(name, ignoreCache = false) {
1627
1661
  openIssuesCount: 0,
1628
1662
  hasGitHubData: false,
1629
1663
  };
1664
+ let scorecard;
1630
1665
  const repoUrl = versionData.repository?.url || packageInfo.repository?.url;
1631
1666
  if (repoUrl?.includes('github.com')) {
1632
1667
  const githubMatch = repoUrl.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
@@ -1634,20 +1669,20 @@ export async function getLocalPackageMetrics(name, ignoreCache = false) {
1634
1669
  const [, owner, repo] = githubMatch;
1635
1670
  const cleanRepo = repo.replace(/\.git$/, '');
1636
1671
  try {
1637
- const ghResponse = await fetchWithRetry(`https://api.github.com/repos/${owner}/${cleanRepo}`, {}, { maxRetries: 0 });
1638
- if (ghResponse.ok) {
1639
- const ghData = await ghResponse.json();
1672
+ const depsDevData = await fetchRepoStatsFromDepsDev(owner, cleanRepo, ignoreCache);
1673
+ if (depsDevData) {
1640
1674
  github = {
1641
- starsCount: ghData.stargazers_count || 0,
1642
- forksCount: ghData.forks_count || 0,
1643
- subscribersCount: ghData.subscribers_count || 0,
1644
- openIssuesCount: ghData.open_issues_count || 0,
1675
+ starsCount: depsDevData.starsCount,
1676
+ forksCount: depsDevData.forksCount,
1677
+ subscribersCount: 0,
1678
+ openIssuesCount: depsDevData.openIssuesCount,
1645
1679
  hasGitHubData: true,
1646
1680
  };
1681
+ scorecard = depsDevData.scorecard;
1647
1682
  }
1648
1683
  }
1649
1684
  catch (ghError) {
1650
- console.debug(`Could not fetch GitHub data for ${owner}/${cleanRepo}: ${ghError}`);
1685
+ console.debug(`Could not fetch deps.dev project data for ${owner}/${cleanRepo}: ${ghError}`);
1651
1686
  }
1652
1687
  }
1653
1688
  }
@@ -1694,6 +1729,7 @@ export async function getLocalPackageMetrics(name, ignoreCache = false) {
1694
1729
  maintenance,
1695
1730
  },
1696
1731
  },
1732
+ scorecard,
1697
1733
  };
1698
1734
  cacheSet(cacheKey, result, CACHE_TTL_LONG);
1699
1735
  return result;
@@ -2108,6 +2144,7 @@ export async function handleNpmScore(args) {
2108
2144
  },
2109
2145
  }
2110
2146
  : null,
2147
+ scorecard: metrics.scorecard,
2111
2148
  };
2112
2149
  cacheSet(cacheKey, scoreData, CACHE_TTL_LONG);
2113
2150
  return {
@@ -2723,43 +2760,38 @@ export async function handleNpmRepoStats(args) {
2723
2760
  return resultNotGitHub;
2724
2761
  }
2725
2762
  const [, owner, repo] = githubMatch;
2726
- const githubRepoApiUrl = `https://api.github.com/repos/${owner}/${repo.replace(/\.git$/, '')}`;
2727
- const githubResponse = await fetchWithRetry(githubRepoApiUrl, {
2728
- headers: {
2729
- Accept: 'application/vnd.github.v3+json',
2730
- },
2731
- });
2732
- if (!githubResponse.ok) {
2763
+ const cleanRepo = repo.replace(/\.git$/, '');
2764
+ const depsDevData = await fetchRepoStatsFromDepsDev(owner, cleanRepo, args.ignoreCache);
2765
+ if (!depsDevData) {
2733
2766
  const errorData = {
2734
2767
  packageInput: pkgInput,
2735
2768
  packageName: name,
2736
2769
  status: 'error',
2737
- error: `Failed to fetch GitHub repo stats for ${owner}/${repo}: ${githubResponse.status} ${githubResponse.statusText}`,
2738
- data: { githubRepoUrl: githubRepoApiUrl },
2739
- message: `Could not retrieve GitHub repository statistics from ${githubRepoApiUrl}.`,
2770
+ error: `Failed to fetch project stats for github.com/${owner}/${cleanRepo} from deps.dev`,
2771
+ data: { repositoryUrl: repoUrl },
2772
+ message: `Could not retrieve repository statistics from deps.dev.`,
2740
2773
  };
2741
- // Do not cache GitHub API call failures for now
2742
2774
  return errorData;
2743
2775
  }
2744
- const githubData = (await githubResponse.json());
2745
2776
  const successResult = {
2746
2777
  packageInput: pkgInput,
2747
2778
  packageName: name,
2748
2779
  status: 'success',
2749
2780
  error: null,
2750
2781
  data: {
2751
- githubRepoUrl: `https://github.com/${owner}/${repo.replace(/\.git$/, '')}`,
2752
- stars: githubData.stargazers_count,
2753
- forks: githubData.forks_count,
2754
- openIssues: githubData.open_issues_count,
2755
- watchers: githubData.watchers_count,
2756
- createdAt: githubData.created_at,
2757
- updatedAt: githubData.updated_at,
2758
- defaultBranch: githubData.default_branch,
2759
- hasWiki: githubData.has_wiki,
2760
- topics: githubData.topics || [],
2782
+ githubRepoUrl: `https://github.com/${owner}/${cleanRepo}`,
2783
+ stars: depsDevData.starsCount,
2784
+ forks: depsDevData.forksCount,
2785
+ openIssues: depsDevData.openIssuesCount,
2786
+ watchers: 0,
2787
+ createdAt: null,
2788
+ updatedAt: null,
2789
+ defaultBranch: null,
2790
+ hasWiki: null,
2791
+ topics: [],
2792
+ scorecard: depsDevData.scorecard,
2761
2793
  },
2762
- message: 'GitHub repository statistics fetched successfully.',
2794
+ message: 'Repository statistics fetched successfully from deps.dev.',
2763
2795
  };
2764
2796
  cacheSet(cacheKey, successResult, CACHE_TTL_LONG);
2765
2797
  return successResult;
@@ -3137,20 +3169,24 @@ export async function handleNpmChangelogAnalysis(args) {
3137
3169
  let changelogContent = null;
3138
3170
  let changelogSourceUrl = null;
3139
3171
  let hasChangelogFile = false;
3140
- for (const file of changelogFiles) {
3141
- try {
3142
- const rawChangelogUrl = `https://raw.githubusercontent.com/${owner}/${repoNameForUrl}/master/${file}`;
3143
- const response = await fetchWithRetry(rawChangelogUrl);
3144
- if (response.ok) {
3145
- changelogContent = await response.text();
3146
- changelogSourceUrl = rawChangelogUrl;
3147
- hasChangelogFile = true;
3148
- break;
3172
+ for (const branch of ['main', 'master']) {
3173
+ for (const file of changelogFiles) {
3174
+ try {
3175
+ const rawChangelogUrl = `https://raw.githubusercontent.com/${owner}/${repoNameForUrl}/${branch}/${file}`;
3176
+ const response = await fetchWithRetry(rawChangelogUrl, {}, { maxRetries: 0 });
3177
+ if (response.ok) {
3178
+ changelogContent = await response.text();
3179
+ changelogSourceUrl = rawChangelogUrl;
3180
+ hasChangelogFile = true;
3181
+ break;
3182
+ }
3183
+ }
3184
+ catch {
3185
+ // Sigue intentando
3149
3186
  }
3150
3187
  }
3151
- catch (error) {
3152
- console.debug(`Error fetching changelog file ${file} for ${name}: ${error}`);
3153
- }
3188
+ if (hasChangelogFile)
3189
+ break;
3154
3190
  }
3155
3191
  let githubReleases = [];
3156
3192
  try {
@@ -3158,19 +3194,34 @@ export async function handleNpmChangelogAnalysis(args) {
3158
3194
  headers: {
3159
3195
  Accept: 'application/vnd.github.v3+json',
3160
3196
  },
3161
- });
3197
+ }, { maxRetries: 0 });
3162
3198
  if (githubApiResponse.ok) {
3163
3199
  const releasesData = (await githubApiResponse.json());
3164
3200
  githubReleases = releasesData.map((r) => ({
3165
3201
  tag_name: r.tag_name || null,
3166
3202
  name: r.name || null,
3167
3203
  published_at: r.published_at || null,
3204
+ source: 'github-api',
3168
3205
  }));
3169
3206
  }
3170
3207
  }
3171
3208
  catch (error) {
3172
3209
  console.debug(`Error fetching GitHub releases for ${name}: ${error}`);
3173
3210
  }
3211
+ // Fallback to NPM Registry time/publish history if GitHub releases couldn't be fetched
3212
+ const publishTime = npmData.time;
3213
+ if (githubReleases.length === 0 && publishTime) {
3214
+ const timeKeys = Object.keys(publishTime).filter((k) => k !== 'modified' && k !== 'created');
3215
+ const sortedVersions = timeKeys.sort((a, b) => {
3216
+ return new Date(publishTime[b]).getTime() - new Date(publishTime[a]).getTime();
3217
+ });
3218
+ githubReleases = sortedVersions.slice(0, 5).map((v) => ({
3219
+ tag_name: `v${v}`,
3220
+ name: `Release ${v} (NPM Publish)`,
3221
+ published_at: publishTime[v],
3222
+ source: 'npm-registry',
3223
+ }));
3224
+ }
3174
3225
  const versions = Object.keys(npmData.versions || {});
3175
3226
  const npmVersionHistory = {
3176
3227
  totalVersions: versions.length,
@@ -3184,7 +3235,7 @@ export async function handleNpmChangelogAnalysis(args) {
3184
3235
  ? `No changelog file or GitHub releases found for ${name}.`
3185
3236
  : `Changelog analysis for ${name}.`;
3186
3237
  const resultToCache = {
3187
- packageInput: pkgInput, // This might differ on subsequent cache hits, so store the original reference for this specific cache entry
3238
+ packageInput: pkgInput,
3188
3239
  packageName: name,
3189
3240
  versionQueried: versionQueried,
3190
3241
  status: status,