API
Core functions
Section titled “Core functions”import { stats, calc, createCache } from '@mcptoolshop/registry-stats';stats()
Section titled “stats()”Query a single registry:
const npm = await stats('npm', 'express');const pypi = await stats('pypi', 'requests');const nuget = await stats('nuget', 'Newtonsoft.Json');const vscode = await stats('vscode', 'esbenp.prettier-vscode');const docker = await stats('docker', 'library/node');stats.all()
Section titled “stats.all()”Query all registries at once. Uses Promise.allSettled — never throws:
const all = await stats.all('express');stats.bulk()
Section titled “stats.bulk()”Fetch multiple packages from one registry, concurrency-limited:
const bulk = await stats.bulk('npm', ['express', 'koa', 'fastify']);stats.range()
Section titled “stats.range()”Daily download counts (npm + PyPI only):
const daily = await stats.range('npm', 'express', '2025-01-01', '2025-06-30');stats.compare()
Section titled “stats.compare()”Compare across registries:
const cmp = await stats.compare('express');await stats.compare('express', ['npm', 'pypi']);stats.mine()
Section titled “stats.mine()”Discover all npm packages by a maintainer, then fetch stats for each:
const results = await stats.mine('mikefrilot', { onProgress(done, total, pkg) { console.log(`${done}/${total}: ${pkg}`); },});// Returns PackageStats[] sorted by monthly downloads (descending)Uses the npm search API for discovery and the smart bulk API for stats (single HTTP call for unscoped packages, throttled sequential for scoped).
Calculations
Section titled “Calculations”calc.total(daily); // sum of all downloadscalc.avg(daily); // daily averagecalc.groupTotals(calc.monthly(daily)); // { '2025-01': 134982, ... }calc.trend(daily); // { direction: 'up', changePercent: 8.3 }calc.movingAvg(daily, 7); // 7-day moving averagecalc.popularity(daily); // 0-100 log-scale scorecalc.toCSV(daily); // CSV stringcalc.toChartData(daily, 'express'); // Chart.js-compatibleCaching
Section titled “Caching”const cache = createCache();await stats('npm', 'express', { cache }); // fetchesawait stats('npm', 'express', { cache }); // cache hit (5 min TTL)The StatsCache interface is pluggable — bring your own Redis or file backend.
AI Inference
Section titled “AI Inference”Zero-dependency, pure-math inference — no ML runtime, no external APIs.
import { forecast, detectAnomalies, segmentTrends, detectSeasonality, computeMomentum, generateRecommendations, computeHealthScore, generateActionableAdvice, computeYearlyProgress, inferPortfolio,} from '@mcptoolshop/registry-stats';
// 7-day forecast with 80% confidence intervalsconst predictions = forecast(dailySeries, 7);
// Anomaly detection (adaptive rolling z-score, 14-day window)const anomalies = detectAnomalies(dailySeries);
// Piecewise trend segmentationconst segments = segmentTrends(dailySeries);
// Composite momentum score (-100 to +100)const momentum = computeMomentum(dailySeries);
// Package health score (0-100 with A-F grade)const health = computeHealthScore('my-pkg', 'npm', dailySeries, momentum);// → { score: 72, grade: 'B', components: { activity, consistency, growth, stability } }
// Actionable advice with severity/urgency// Takes: (packageInferences[], healthScores[], opts)const advice = generateActionableAdvice(packages, healthScores, { gini: 0.6, npmPct: 85 });// → [{ type, severity, urgency, title, detail, action, packages }]
// Full portfolio analysis (the main entry point)const result = inferPortfolio(leaderboard, { gini: 0.6, npmPct: 85 });// → { packages, forecastTotal7, riskScore, portfolioMomentum, recommendations, healthScores, actionableAdvice }REST server
Section titled “REST server”import { createHandler, serve } from '@mcptoolshop/registry-stats';
// Quick startserve({ port: 3000 });
// Bring your own serverimport { createServer } from 'node:http';const handler = createHandler();createServer(handler).listen(3000);Endpoints
Section titled “Endpoints”| Method | Path | Description |
|---|---|---|
GET | / | Health check (lists available endpoints) |
GET | /stats/:package | All registries for a package |
GET | /stats/:registry/:package | Single registry |
GET | /compare/:package?registries=npm,pypi | Cross-registry comparison |
GET | /range/:registry/:package?start=...&end=...&format=json|csv|chart | Time series data |
All endpoints return JSON by default. The /range endpoint supports format=csv (returns CSV with Content-Disposition header) and format=chart (returns Chart.js-compatible JSON). CORS is enabled for all origins.