/* End-to-end sanity check for MCP catalog sorting. - Calls MCPRegistryService.searchServers() - Prints the top entries and verifies githubStars descending, then installCount, then name. */ import { MCPRegistryService } from '../src/main/services/mcp-registry-service'; type Server = { id: string; name: string; description?: string; author?: string; version?: string; url?: string; packageRegistry?: string; packageName?: string; repository?: { type: string; url: string }; tags?: string[]; license?: string; createdAt?: string; updatedAt?: string; installCount?: number; rating?: number; githubStars?: number; }; function asNum(n: unknown): number { const v = Number(n ?? 0); return Number.isFinite(v) ? v : 0; } function keyOf(s: Server): string { return s.packageName || s.repository?.url || s.id || s.name; } function dedupe(list: Server[]): Server[] { const m = new Map(); for (const s of list) { const k = keyOf(s); if (!m.has(k)) m.set(k, s); } return Array.from(m.values()); } function verifyOrder(servers: Server[]): { ok: boolean; reason?: string; index?: number; } { for (let i = 1; i < servers.length; i++) { const prev = servers[i - 1]; const cur = servers[i]; const ps = asNum(prev.githubStars); const cs = asNum(cur.githubStars); if (ps < cs) return { ok: false, reason: `stars increased from ${ps} to ${cs}`, index: i, }; if (ps === cs) { const pi = asNum(prev.installCount); const ci = asNum(cur.installCount); if (pi < ci) return { ok: false, reason: `installs increased at equal stars (${ps}): ${pi} -> ${ci}`, index: i, }; if (pi === ci) { if (prev.name.localeCompare(cur.name) > 0) { return { ok: false, reason: `name order incorrect at equal stars/installs`, index: i, }; } } } } return { ok: true }; } async function main() { const registry = MCPRegistryService.getInstance(); console.log('[mcp-sort-check] Performing registry search (limit=50, offsets 0..150)'); const pages: Server[][] = []; let total = 0; let hasMore = false; for (const offset of [0, 50, 100, 150]) { const res = await registry.searchServers({ limit: 50, offset }); total = res.total ?? total; hasMore = res.hasMore ?? hasMore; pages.push(((res.servers || []) as Server[])); } const raw = pages.flat(); const list = dedupe(raw); console.log(`[mcp-sort-check] Received ${raw.length} servers across 4 pages; after dedupe: ${list.length} (total=${total}, hasMore=${hasMore})`); console.log('[mcp-sort-check] Top 20 (raw merged, deduped):'); list.slice(0, 20).forEach((s, i) => { console.log( `${String(i + 1).padStart(2, ' ')}. ${s.name} | stars=${asNum(s.githubStars)} installs=${asNum(s.installCount)}` ); }); const mergedSorted = [...list].sort((a, b) => { const aStars = asNum(a.githubStars) const bStars = asNum(b.githubStars) if (aStars !== bStars) return bStars - aStars const aInst = asNum(a.installCount) const bInst = asNum(b.installCount) if (aInst !== bInst) return bInst - aInst return a.name.localeCompare(b.name) }) console.log('[mcp-sort-check] Top 20 (after resort):'); mergedSorted.slice(0, 20).forEach((s, i) => { console.log( `${String(i + 1).padStart(2, ' ')}. ${s.name} | stars=${asNum(s.githubStars)} installs=${asNum(s.installCount)}` ); }) const check = verifyOrder(mergedSorted); if (!check.ok) { const i = check.index ?? 0; const prev = list[i - 1]; const cur = list[i]; console.log('[mcp-sort-check] ORDER VIOLATION ->', check.reason); console.log(' Prev:', { name: prev?.name, stars: asNum(prev?.githubStars), installs: asNum(prev?.installCount), }); console.log(' Curr:', { name: cur?.name, stars: asNum(cur?.githubStars), installs: asNum(cur?.installCount), }); process.exit(1); } else { console.log( '[mcp-sort-check] Order OK: stars desc, then installs desc, then name asc' ); } } main() .then(() => { console.log('[mcp-sort-check] complete'); process.exit(0); }) .catch((err) => { console.error('[mcp-sort-check] Failed:', err); process.exit(2); });