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']);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.
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);