reasonix 0.32.0 → 0.33.1
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/cli/chat-Q5ZCVIOO.js +39 -0
- package/dist/cli/chunk-2AWTGJ2C.js +110 -0
- package/dist/cli/chunk-2AWTGJ2C.js.map +1 -0
- package/dist/cli/chunk-3Q3C4W66.js +30 -0
- package/dist/cli/chunk-3Q3C4W66.js.map +1 -0
- package/dist/cli/chunk-4DCHFFEY.js +149 -0
- package/dist/cli/chunk-4DCHFFEY.js.map +1 -0
- package/dist/cli/chunk-5X7LZJDE.js +36 -0
- package/dist/cli/chunk-5X7LZJDE.js.map +1 -0
- package/dist/cli/chunk-63KAV5DX.js +106 -0
- package/dist/cli/chunk-63KAV5DX.js.map +1 -0
- package/dist/cli/chunk-6TMHAK5D.js +576 -0
- package/dist/cli/chunk-6TMHAK5D.js.map +1 -0
- package/dist/cli/chunk-APPB3ZPQ.js +43 -0
- package/dist/cli/chunk-APPB3ZPQ.js.map +1 -0
- package/dist/cli/chunk-BQNUJJN7.js +42 -0
- package/dist/cli/chunk-BQNUJJN7.js.map +1 -0
- package/dist/cli/chunk-CPOV2O73.js +39 -0
- package/dist/cli/chunk-CPOV2O73.js.map +1 -0
- package/dist/cli/chunk-D5DKXIP5.js +368 -0
- package/dist/cli/chunk-D5DKXIP5.js.map +1 -0
- package/dist/cli/chunk-DFP4YSVM.js +247 -0
- package/dist/cli/chunk-DFP4YSVM.js.map +1 -0
- package/dist/cli/chunk-DULSP7JH.js +410 -0
- package/dist/cli/chunk-DULSP7JH.js.map +1 -0
- package/dist/cli/chunk-FM57FNPJ.js +46 -0
- package/dist/cli/chunk-FM57FNPJ.js.map +1 -0
- package/dist/cli/chunk-FWGEHRB7.js +54 -0
- package/dist/cli/chunk-FWGEHRB7.js.map +1 -0
- package/dist/cli/chunk-FXGQ5NHE.js +513 -0
- package/dist/cli/chunk-FXGQ5NHE.js.map +1 -0
- package/dist/cli/chunk-G3XNWSFN.js +53 -0
- package/dist/cli/chunk-G3XNWSFN.js.map +1 -0
- package/dist/cli/chunk-I6YIAK6C.js +757 -0
- package/dist/cli/chunk-I6YIAK6C.js.map +1 -0
- package/dist/cli/chunk-J5VLP23S.js +94 -0
- package/dist/cli/chunk-J5VLP23S.js.map +1 -0
- package/dist/cli/chunk-KMWKGPFZ.js +303 -0
- package/dist/cli/chunk-KMWKGPFZ.js.map +1 -0
- package/dist/cli/chunk-MDHVWCJ4.js +14965 -0
- package/dist/cli/chunk-MDHVWCJ4.js.map +1 -0
- package/dist/cli/chunk-MHDNZXJJ.js +48 -0
- package/dist/cli/chunk-MHDNZXJJ.js.map +1 -0
- package/dist/cli/chunk-ORM6PK57.js +140 -0
- package/dist/cli/chunk-ORM6PK57.js.map +1 -0
- package/dist/cli/chunk-Q6YFXW7H.js +4986 -0
- package/dist/cli/chunk-Q6YFXW7H.js.map +1 -0
- package/dist/cli/chunk-QGE6AF76.js +1467 -0
- package/dist/cli/chunk-QGE6AF76.js.map +1 -0
- package/dist/cli/chunk-RFX7TYVV.js +28 -0
- package/dist/cli/chunk-RFX7TYVV.js.map +1 -0
- package/dist/cli/chunk-RZILUXUC.js +940 -0
- package/dist/cli/chunk-RZILUXUC.js.map +1 -0
- package/dist/cli/chunk-SDE5U32Z.js +535 -0
- package/dist/cli/chunk-SDE5U32Z.js.map +1 -0
- package/dist/cli/chunk-SOZE7V7V.js +340 -0
- package/dist/cli/chunk-SOZE7V7V.js.map +1 -0
- package/dist/cli/chunk-U3V2ZQ5J.js +479 -0
- package/dist/cli/chunk-U3V2ZQ5J.js.map +1 -0
- package/dist/cli/chunk-W4LDFAZ6.js +1544 -0
- package/dist/cli/chunk-W4LDFAZ6.js.map +1 -0
- package/dist/cli/chunk-WBDE4IRI.js +208 -0
- package/dist/cli/chunk-WBDE4IRI.js.map +1 -0
- package/dist/cli/chunk-XHQIK7B6.js +189 -0
- package/dist/cli/chunk-XHQIK7B6.js.map +1 -0
- package/dist/cli/chunk-XJLZ4HKU.js +307 -0
- package/dist/cli/chunk-XJLZ4HKU.js.map +1 -0
- package/dist/cli/chunk-ZPTSJGX5.js +88 -0
- package/dist/cli/chunk-ZPTSJGX5.js.map +1 -0
- package/dist/cli/chunk-ZTLZO42A.js +231 -0
- package/dist/cli/chunk-ZTLZO42A.js.map +1 -0
- package/dist/cli/code-DLR77NPZ.js +151 -0
- package/dist/cli/code-DLR77NPZ.js.map +1 -0
- package/dist/cli/commands-JWT2MWVH.js +352 -0
- package/dist/cli/commands-JWT2MWVH.js.map +1 -0
- package/dist/cli/commit-RPZBOZS2.js +288 -0
- package/dist/cli/commit-RPZBOZS2.js.map +1 -0
- package/dist/cli/diff-NTEHCSDW.js +145 -0
- package/dist/cli/diff-NTEHCSDW.js.map +1 -0
- package/dist/cli/doctor-3TGB2NZN.js +19 -0
- package/dist/cli/doctor-3TGB2NZN.js.map +1 -0
- package/dist/cli/events-P27CX7LN.js +338 -0
- package/dist/cli/events-P27CX7LN.js.map +1 -0
- package/dist/cli/index.js +80 -33693
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-ARTNQ24O.js +266 -0
- package/dist/cli/mcp-ARTNQ24O.js.map +1 -0
- package/dist/cli/mcp-browse-HLO2ENDL.js +163 -0
- package/dist/cli/mcp-browse-HLO2ENDL.js.map +1 -0
- package/dist/cli/mcp-inspect-T2HBR22P.js +103 -0
- package/dist/cli/mcp-inspect-T2HBR22P.js.map +1 -0
- package/dist/cli/{prompt-XHICFAYN.js → prompt-V47QKSAR.js} +3 -2
- package/dist/cli/prompt-V47QKSAR.js.map +1 -0
- package/dist/cli/prune-sessions-ERL6B4G5.js +42 -0
- package/dist/cli/prune-sessions-ERL6B4G5.js.map +1 -0
- package/dist/cli/replay-Q43DSMG6.js +273 -0
- package/dist/cli/replay-Q43DSMG6.js.map +1 -0
- package/dist/cli/run-JMEOTQCG.js +215 -0
- package/dist/cli/run-JMEOTQCG.js.map +1 -0
- package/dist/cli/server-SYC3OVOP.js +2967 -0
- package/dist/cli/server-SYC3OVOP.js.map +1 -0
- package/dist/cli/sessions-MOJAALJI.js +102 -0
- package/dist/cli/sessions-MOJAALJI.js.map +1 -0
- package/dist/cli/setup-CCJZAWTY.js +404 -0
- package/dist/cli/setup-CCJZAWTY.js.map +1 -0
- package/dist/cli/stats-5RJCATCE.js +12 -0
- package/dist/cli/stats-5RJCATCE.js.map +1 -0
- package/dist/cli/update-4TJWRUIN.js +90 -0
- package/dist/cli/update-4TJWRUIN.js.map +1 -0
- package/dist/cli/version-3MYFE4G6.js +29 -0
- package/dist/cli/version-3MYFE4G6.js.map +1 -0
- package/dist/index.d.ts +13 -2
- package/dist/index.js +493 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-VWFJNLIK.js +0 -1031
- package/dist/cli/chunk-VWFJNLIK.js.map +0 -1
- /package/dist/cli/{prompt-XHICFAYN.js.map → chat-Q5ZCVIOO.js.map} +0 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MCP_CATALOG
|
|
4
|
+
} from "./chunk-FM57FNPJ.js";
|
|
5
|
+
|
|
6
|
+
// src/mcp/registry-fetch.ts
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
import { dirname, join } from "path";
|
|
10
|
+
var OFFICIAL_REGISTRY_URL = "https://registry.modelcontextprotocol.io/v0/servers";
|
|
11
|
+
var SMITHERY_REGISTRY_URL = "https://registry.smithery.ai/servers";
|
|
12
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
13
|
+
var FETCH_TIMEOUT_MS = 1e4;
|
|
14
|
+
var CACHE_SCHEMA_VERSION = 2;
|
|
15
|
+
function defaultCachePath() {
|
|
16
|
+
return join(homedir(), ".reasonix", "mcp-registry-cache.json");
|
|
17
|
+
}
|
|
18
|
+
function readCache(path) {
|
|
19
|
+
try {
|
|
20
|
+
const raw = readFileSync(path, "utf8");
|
|
21
|
+
const parsed = JSON.parse(raw);
|
|
22
|
+
if (parsed.schemaVersion !== CACHE_SCHEMA_VERSION || typeof parsed.fetchedAt !== "number" || !Array.isArray(parsed.entries) || typeof parsed.pagination?.pagesLoaded !== "number") {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return parsed;
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function writeCache(path, file) {
|
|
31
|
+
try {
|
|
32
|
+
const dir = dirname(path);
|
|
33
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
34
|
+
writeFileSync(path, JSON.stringify(file, null, 2));
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function timeoutFetch(url, fetcher) {
|
|
39
|
+
const ctrl = new AbortController();
|
|
40
|
+
const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
|
|
41
|
+
try {
|
|
42
|
+
return await fetcher(url, { signal: ctrl.signal });
|
|
43
|
+
} finally {
|
|
44
|
+
clearTimeout(timer);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function normalizeOfficialPackage(pkg) {
|
|
48
|
+
if (!pkg) return void 0;
|
|
49
|
+
const runtime = pkg.registryType === "npm" ? "npm" : pkg.registryType === "pypi" ? "pypi" : null;
|
|
50
|
+
if (!runtime) return void 0;
|
|
51
|
+
const t = pkg.transport?.type;
|
|
52
|
+
const transport = t === "sse" ? "sse" : t === "streamable-http" ? "streamable-http" : "stdio";
|
|
53
|
+
const requiredEnv = (pkg.environmentVariables ?? []).map((e) => e.name).filter((n) => typeof n === "string" && n.length > 0);
|
|
54
|
+
const install = { runtime, transport };
|
|
55
|
+
if (pkg.identifier) install.packageId = pkg.identifier;
|
|
56
|
+
if (pkg.version) install.version = pkg.version;
|
|
57
|
+
if (requiredEnv.length > 0) install.requiredEnv = requiredEnv;
|
|
58
|
+
return install;
|
|
59
|
+
}
|
|
60
|
+
function normalizeOfficial(server) {
|
|
61
|
+
if (!server?.name) return null;
|
|
62
|
+
let install = normalizeOfficialPackage(server.packages?.[0]);
|
|
63
|
+
if (!install && server.remotes?.[0]?.url) {
|
|
64
|
+
const remote = server.remotes[0];
|
|
65
|
+
const transport = remote.type === "streamable-http" ? "streamable-http" : "sse";
|
|
66
|
+
install = { runtime: "remote", transport, url: remote.url };
|
|
67
|
+
}
|
|
68
|
+
const entry = {
|
|
69
|
+
name: server.name,
|
|
70
|
+
title: server.title || server.name,
|
|
71
|
+
description: server.description ?? "",
|
|
72
|
+
source: "official"
|
|
73
|
+
};
|
|
74
|
+
if (install) entry.install = install;
|
|
75
|
+
if (server.websiteUrl) entry.homepage = server.websiteUrl;
|
|
76
|
+
const icon = server.icons?.find((i) => i.src)?.src;
|
|
77
|
+
if (icon) entry.iconUrl = icon;
|
|
78
|
+
return entry;
|
|
79
|
+
}
|
|
80
|
+
async function fetchOfficialPage(cursor, fetcher = globalThis.fetch) {
|
|
81
|
+
const url = cursor ? `${OFFICIAL_REGISTRY_URL}?cursor=${encodeURIComponent(cursor)}` : OFFICIAL_REGISTRY_URL;
|
|
82
|
+
const resp = await timeoutFetch(url, fetcher);
|
|
83
|
+
if (!resp.ok) throw new Error(`official registry HTTP ${resp.status}`);
|
|
84
|
+
const json = await resp.json();
|
|
85
|
+
const entries = [];
|
|
86
|
+
for (const e of json.servers ?? []) {
|
|
87
|
+
const norm = normalizeOfficial(e.server);
|
|
88
|
+
if (norm) entries.push(norm);
|
|
89
|
+
}
|
|
90
|
+
return { entries, nextCursor: json.metadata?.nextCursor ?? null };
|
|
91
|
+
}
|
|
92
|
+
function normalizeSmithery(s) {
|
|
93
|
+
if (!s.qualifiedName) return null;
|
|
94
|
+
const entry = {
|
|
95
|
+
name: s.qualifiedName,
|
|
96
|
+
title: s.displayName || s.qualifiedName,
|
|
97
|
+
description: s.description ?? "",
|
|
98
|
+
source: "smithery"
|
|
99
|
+
};
|
|
100
|
+
if (typeof s.useCount === "number") entry.popularity = s.useCount;
|
|
101
|
+
if (s.homepage) entry.homepage = s.homepage;
|
|
102
|
+
if (s.iconUrl) entry.iconUrl = s.iconUrl;
|
|
103
|
+
return entry;
|
|
104
|
+
}
|
|
105
|
+
async function fetchSmitheryDetail(qualifiedName, fetcher = globalThis.fetch) {
|
|
106
|
+
const url = `${SMITHERY_REGISTRY_URL}/${encodeURIComponent(qualifiedName)}`;
|
|
107
|
+
const resp = await timeoutFetch(url, fetcher);
|
|
108
|
+
if (!resp.ok) return null;
|
|
109
|
+
const json = await resp.json();
|
|
110
|
+
const conn = json.connections?.[0];
|
|
111
|
+
if (!conn) return null;
|
|
112
|
+
if (conn.type === "http" || conn.type === "ws") {
|
|
113
|
+
const deploymentUrl = conn.deploymentUrl ?? json.deploymentUrl;
|
|
114
|
+
if (!deploymentUrl) return null;
|
|
115
|
+
return { runtime: "remote", transport: "streamable-http", url: deploymentUrl };
|
|
116
|
+
}
|
|
117
|
+
if (conn.type === "stdio") {
|
|
118
|
+
return {
|
|
119
|
+
runtime: "npm",
|
|
120
|
+
packageId: "@smithery/cli",
|
|
121
|
+
transport: "stdio",
|
|
122
|
+
extraArgs: ["run", qualifiedName]
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
async function fetchSmitheryFirstPage(fetcher = globalThis.fetch) {
|
|
128
|
+
const resp = await timeoutFetch(SMITHERY_REGISTRY_URL, fetcher);
|
|
129
|
+
if (!resp.ok) throw new Error(`smithery HTTP ${resp.status}`);
|
|
130
|
+
const json = await resp.json();
|
|
131
|
+
const entries = (json.servers ?? []).map(normalizeSmithery).filter((x) => x !== null);
|
|
132
|
+
if (entries.length === 0) throw new Error("smithery returned no entries");
|
|
133
|
+
return entries;
|
|
134
|
+
}
|
|
135
|
+
function fallbackFromCatalog() {
|
|
136
|
+
return MCP_CATALOG.map((e) => ({
|
|
137
|
+
name: e.name,
|
|
138
|
+
title: e.name,
|
|
139
|
+
description: e.summary,
|
|
140
|
+
source: "local",
|
|
141
|
+
install: {
|
|
142
|
+
runtime: "npm",
|
|
143
|
+
packageId: e.package,
|
|
144
|
+
transport: "stdio"
|
|
145
|
+
}
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
function newOfficialCache(initial) {
|
|
149
|
+
const seen = /* @__PURE__ */ new Map();
|
|
150
|
+
for (const e of initial.entries) if (!seen.has(e.name)) seen.set(e.name, e);
|
|
151
|
+
return {
|
|
152
|
+
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
153
|
+
fetchedAt: Date.now(),
|
|
154
|
+
source: "official",
|
|
155
|
+
entries: [...seen.values()],
|
|
156
|
+
pagination: { pagesLoaded: 1, nextCursor: initial.nextCursor }
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function newStaticCache(source, entries) {
|
|
160
|
+
return {
|
|
161
|
+
schemaVersion: CACHE_SCHEMA_VERSION,
|
|
162
|
+
fetchedAt: Date.now(),
|
|
163
|
+
source,
|
|
164
|
+
entries,
|
|
165
|
+
pagination: { pagesLoaded: 1, nextCursor: null }
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function openRegistry(opts = {}) {
|
|
169
|
+
const fetcher = opts.fetcher ?? globalThis.fetch;
|
|
170
|
+
const cachePath = opts.cachePath ?? defaultCachePath();
|
|
171
|
+
const errors = [];
|
|
172
|
+
if (!opts.noCache && !opts.preferSource) {
|
|
173
|
+
const cached = readCache(cachePath);
|
|
174
|
+
if (cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS && cached.entries.length > 0) {
|
|
175
|
+
return {
|
|
176
|
+
source: cached.source,
|
|
177
|
+
cache: cached,
|
|
178
|
+
fromCache: true,
|
|
179
|
+
fetchedAt: cached.fetchedAt,
|
|
180
|
+
errors: [],
|
|
181
|
+
cachePath
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const tryOfficial = async () => {
|
|
186
|
+
const first = await fetchOfficialPage(null, fetcher);
|
|
187
|
+
const cache = newOfficialCache(first);
|
|
188
|
+
opts.onProgress?.({ source: "official", page: 1, entries: cache.entries.length });
|
|
189
|
+
writeCache(cachePath, cache);
|
|
190
|
+
return {
|
|
191
|
+
source: "official",
|
|
192
|
+
cache,
|
|
193
|
+
fromCache: false,
|
|
194
|
+
fetchedAt: cache.fetchedAt,
|
|
195
|
+
errors,
|
|
196
|
+
cachePath
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
const trySmithery = async () => {
|
|
200
|
+
const entries = await fetchSmitheryFirstPage(fetcher);
|
|
201
|
+
const cache = newStaticCache("smithery", entries);
|
|
202
|
+
opts.onProgress?.({ source: "smithery", page: 1, entries: entries.length });
|
|
203
|
+
writeCache(cachePath, cache);
|
|
204
|
+
return {
|
|
205
|
+
source: "smithery",
|
|
206
|
+
cache,
|
|
207
|
+
fromCache: false,
|
|
208
|
+
fetchedAt: cache.fetchedAt,
|
|
209
|
+
errors,
|
|
210
|
+
cachePath
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
const tryLocal = () => {
|
|
214
|
+
const cache = newStaticCache("local", fallbackFromCatalog());
|
|
215
|
+
return {
|
|
216
|
+
source: "local",
|
|
217
|
+
cache,
|
|
218
|
+
fromCache: false,
|
|
219
|
+
fetchedAt: cache.fetchedAt,
|
|
220
|
+
errors,
|
|
221
|
+
cachePath
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
if (opts.preferSource === "local") return tryLocal();
|
|
225
|
+
if (opts.preferSource === "smithery") {
|
|
226
|
+
try {
|
|
227
|
+
return await trySmithery();
|
|
228
|
+
} catch (e) {
|
|
229
|
+
errors.push(`smithery: ${e.message}`);
|
|
230
|
+
return tryLocal();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
return await tryOfficial();
|
|
235
|
+
} catch (e) {
|
|
236
|
+
errors.push(`official: ${e.message}`);
|
|
237
|
+
}
|
|
238
|
+
try {
|
|
239
|
+
return await trySmithery();
|
|
240
|
+
} catch (e) {
|
|
241
|
+
errors.push(`smithery: ${e.message}`);
|
|
242
|
+
}
|
|
243
|
+
const stale = readCache(cachePath);
|
|
244
|
+
if (stale) {
|
|
245
|
+
return {
|
|
246
|
+
source: stale.source,
|
|
247
|
+
cache: stale,
|
|
248
|
+
fromCache: true,
|
|
249
|
+
fetchedAt: stale.fetchedAt,
|
|
250
|
+
errors,
|
|
251
|
+
cachePath
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
return tryLocal();
|
|
255
|
+
}
|
|
256
|
+
async function loadMorePages(handle, opts = {}) {
|
|
257
|
+
if (handle.source !== "official") {
|
|
258
|
+
return { pagesAdded: 0, newEntries: 0, exhausted: true };
|
|
259
|
+
}
|
|
260
|
+
const cache = handle.cache;
|
|
261
|
+
if (cache.pagination.nextCursor === null) {
|
|
262
|
+
return { pagesAdded: 0, newEntries: 0, exhausted: true };
|
|
263
|
+
}
|
|
264
|
+
const fetcher = opts.fetcher ?? globalThis.fetch;
|
|
265
|
+
const limit = opts.pages ?? 1;
|
|
266
|
+
const seen = new Set(cache.entries.map((e) => e.name));
|
|
267
|
+
const matchCount = () => {
|
|
268
|
+
if (!opts.filter) return 0;
|
|
269
|
+
let n = 0;
|
|
270
|
+
for (const e of cache.entries) if (opts.filter(e)) n++;
|
|
271
|
+
return n;
|
|
272
|
+
};
|
|
273
|
+
let pagesAdded = 0;
|
|
274
|
+
let newEntries = 0;
|
|
275
|
+
for (let i = 0; i < limit; i++) {
|
|
276
|
+
if (cache.pagination.nextCursor === null) break;
|
|
277
|
+
if (opts.matchTarget !== void 0 && matchCount() >= opts.matchTarget) break;
|
|
278
|
+
const result = await fetchOfficialPage(cache.pagination.nextCursor, fetcher);
|
|
279
|
+
for (const e of result.entries) {
|
|
280
|
+
if (!seen.has(e.name)) {
|
|
281
|
+
seen.add(e.name);
|
|
282
|
+
cache.entries.push(e);
|
|
283
|
+
newEntries++;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
cache.pagination.pagesLoaded += 1;
|
|
287
|
+
cache.pagination.nextCursor = result.nextCursor;
|
|
288
|
+
pagesAdded += 1;
|
|
289
|
+
opts.onProgress?.({
|
|
290
|
+
source: "official",
|
|
291
|
+
page: cache.pagination.pagesLoaded,
|
|
292
|
+
entries: cache.entries.length
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (pagesAdded > 0) writeCache(handle.cachePath, cache);
|
|
296
|
+
return {
|
|
297
|
+
pagesAdded,
|
|
298
|
+
newEntries,
|
|
299
|
+
exhausted: cache.pagination.nextCursor === null
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function specStringFor(name, install) {
|
|
303
|
+
const localName = name.split("/").pop() ?? name;
|
|
304
|
+
const safe = localName.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/^-+|-+$/g, "") || "mcp";
|
|
305
|
+
if (install.runtime === "remote") {
|
|
306
|
+
if (!install.url) throw new Error(`remote install for ${name} has no URL`);
|
|
307
|
+
if (install.transport === "streamable-http") return `${safe}=streamable+${install.url}`;
|
|
308
|
+
return `${safe}=${install.url}`;
|
|
309
|
+
}
|
|
310
|
+
const trail = install.extraArgs?.length ? ` ${install.extraArgs.join(" ")}` : "";
|
|
311
|
+
if (install.runtime === "npm") {
|
|
312
|
+
if (!install.packageId) throw new Error(`npm install for ${name} has no packageId`);
|
|
313
|
+
const pinned = install.version ? `${install.packageId}@${install.version}` : install.packageId;
|
|
314
|
+
return `${safe}=npx -y ${pinned}${trail}`;
|
|
315
|
+
}
|
|
316
|
+
if (install.runtime === "pypi") {
|
|
317
|
+
if (!install.packageId) throw new Error(`pypi install for ${name} has no packageId`);
|
|
318
|
+
return `${safe}=uvx ${install.packageId}${trail}`;
|
|
319
|
+
}
|
|
320
|
+
throw new Error(`unsupported install runtime: ${install.runtime}`);
|
|
321
|
+
}
|
|
322
|
+
function handleToFetchResult(handle) {
|
|
323
|
+
return {
|
|
324
|
+
entries: handle.cache.entries,
|
|
325
|
+
source: handle.source,
|
|
326
|
+
fromCache: handle.fromCache,
|
|
327
|
+
fetchedAt: handle.fetchedAt,
|
|
328
|
+
errors: handle.errors,
|
|
329
|
+
hasMore: handle.cache.pagination.nextCursor !== null
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export {
|
|
334
|
+
fetchSmitheryDetail,
|
|
335
|
+
openRegistry,
|
|
336
|
+
loadMorePages,
|
|
337
|
+
specStringFor,
|
|
338
|
+
handleToFetchResult
|
|
339
|
+
};
|
|
340
|
+
//# sourceMappingURL=chunk-SOZE7V7V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/registry-fetch.ts"],"sourcesContent":["/** Primary: registry.modelcontextprotocol.io. Fallback: registry.smithery.ai. Last resort: bundled MCP_CATALOG. */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { MCP_CATALOG } from \"./catalog.js\";\nimport type {\n CacheFile,\n CachePagination,\n RegistryEntry,\n RegistryInstall,\n RegistrySource,\n} from \"./registry-types.js\";\n\nexport const OFFICIAL_REGISTRY_URL = \"https://registry.modelcontextprotocol.io/v0/servers\";\nexport const SMITHERY_REGISTRY_URL = \"https://registry.smithery.ai/servers\";\nexport const CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nexport const FETCH_TIMEOUT_MS = 10_000;\nexport const CACHE_SCHEMA_VERSION = 2;\n\nexport function defaultCachePath(): string {\n return join(homedir(), \".reasonix\", \"mcp-registry-cache.json\");\n}\n\nfunction readCache(path: string): CacheFile | null {\n try {\n const raw = readFileSync(path, \"utf8\");\n const parsed = JSON.parse(raw) as Partial<CacheFile>;\n if (\n parsed.schemaVersion !== CACHE_SCHEMA_VERSION ||\n typeof parsed.fetchedAt !== \"number\" ||\n !Array.isArray(parsed.entries) ||\n typeof parsed.pagination?.pagesLoaded !== \"number\"\n ) {\n return null;\n }\n return parsed as CacheFile;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(path: string, file: CacheFile): void {\n try {\n const dir = dirname(path);\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(path, JSON.stringify(file, null, 2));\n } catch {\n /* cache failures are non-fatal */\n }\n}\n\nasync function timeoutFetch(url: string, fetcher: typeof fetch): Promise<Response> {\n const ctrl = new AbortController();\n const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);\n try {\n return await fetcher(url, { signal: ctrl.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n\ninterface OfficialPackage {\n registryType?: string;\n identifier?: string;\n version?: string;\n transport?: { type?: string };\n environmentVariables?: Array<{ name?: string }>;\n}\n\ninterface OfficialServerCore {\n name?: string;\n title?: string;\n description?: string;\n packages?: OfficialPackage[];\n remotes?: Array<{ type?: string; url?: string }>;\n websiteUrl?: string;\n icons?: Array<{ src?: string }>;\n}\n\ninterface OfficialServerEntry {\n server?: OfficialServerCore;\n}\n\ninterface OfficialResponse {\n servers?: OfficialServerEntry[];\n metadata?: { nextCursor?: string };\n}\n\nfunction normalizeOfficialPackage(pkg: OfficialPackage | undefined): RegistryInstall | undefined {\n if (!pkg) return undefined;\n const runtime = pkg.registryType === \"npm\" ? \"npm\" : pkg.registryType === \"pypi\" ? \"pypi\" : null;\n if (!runtime) return undefined;\n const t = pkg.transport?.type;\n const transport: RegistryInstall[\"transport\"] =\n t === \"sse\" ? \"sse\" : t === \"streamable-http\" ? \"streamable-http\" : \"stdio\";\n const requiredEnv = (pkg.environmentVariables ?? [])\n .map((e) => e.name)\n .filter((n): n is string => typeof n === \"string\" && n.length > 0);\n const install: RegistryInstall = { runtime, transport };\n if (pkg.identifier) install.packageId = pkg.identifier;\n if (pkg.version) install.version = pkg.version;\n if (requiredEnv.length > 0) install.requiredEnv = requiredEnv;\n return install;\n}\n\nfunction normalizeOfficial(server: OfficialServerCore | undefined): RegistryEntry | null {\n if (!server?.name) return null;\n let install = normalizeOfficialPackage(server.packages?.[0]);\n if (!install && server.remotes?.[0]?.url) {\n const remote = server.remotes[0];\n const transport: RegistryInstall[\"transport\"] =\n remote.type === \"streamable-http\" ? \"streamable-http\" : \"sse\";\n install = { runtime: \"remote\", transport, url: remote.url };\n }\n const entry: RegistryEntry = {\n name: server.name,\n title: server.title || server.name,\n description: server.description ?? \"\",\n source: \"official\",\n };\n if (install) entry.install = install;\n if (server.websiteUrl) entry.homepage = server.websiteUrl;\n const icon = server.icons?.find((i) => i.src)?.src;\n if (icon) entry.iconUrl = icon;\n return entry;\n}\n\ninterface OfficialPageResult {\n entries: RegistryEntry[];\n nextCursor: string | null;\n}\n\nexport async function fetchOfficialPage(\n cursor: string | null,\n fetcher: typeof fetch = globalThis.fetch,\n): Promise<OfficialPageResult> {\n const url = cursor\n ? `${OFFICIAL_REGISTRY_URL}?cursor=${encodeURIComponent(cursor)}`\n : OFFICIAL_REGISTRY_URL;\n const resp = await timeoutFetch(url, fetcher);\n if (!resp.ok) throw new Error(`official registry HTTP ${resp.status}`);\n const json = (await resp.json()) as OfficialResponse;\n const entries: RegistryEntry[] = [];\n for (const e of json.servers ?? []) {\n const norm = normalizeOfficial(e.server);\n if (norm) entries.push(norm);\n }\n return { entries, nextCursor: json.metadata?.nextCursor ?? null };\n}\n\ninterface SmitheryServer {\n qualifiedName?: string;\n displayName?: string;\n description?: string;\n useCount?: number;\n homepage?: string;\n iconUrl?: string;\n}\n\ninterface SmitheryResponse {\n servers?: SmitheryServer[];\n pagination?: { totalPages?: number; pageSize?: number };\n}\n\nfunction normalizeSmithery(s: SmitheryServer): RegistryEntry | null {\n if (!s.qualifiedName) return null;\n const entry: RegistryEntry = {\n name: s.qualifiedName,\n title: s.displayName || s.qualifiedName,\n description: s.description ?? \"\",\n source: \"smithery\",\n };\n if (typeof s.useCount === \"number\") entry.popularity = s.useCount;\n if (s.homepage) entry.homepage = s.homepage;\n if (s.iconUrl) entry.iconUrl = s.iconUrl;\n return entry;\n}\n\ninterface SmitheryConnection {\n type?: string;\n deploymentUrl?: string;\n bundleUrl?: string;\n runtime?: string;\n}\n\ninterface SmitheryDetailResponse {\n qualifiedName?: string;\n remote?: boolean;\n deploymentUrl?: string | null;\n connections?: SmitheryConnection[];\n}\n\n/** Resolve a Smithery listing entry into a runnable install. http → streamable-http remote; stdio → spawn via @smithery/cli. */\nexport async function fetchSmitheryDetail(\n qualifiedName: string,\n fetcher: typeof fetch = globalThis.fetch,\n): Promise<RegistryInstall | null> {\n const url = `${SMITHERY_REGISTRY_URL}/${encodeURIComponent(qualifiedName)}`;\n const resp = await timeoutFetch(url, fetcher);\n if (!resp.ok) return null;\n const json = (await resp.json()) as SmitheryDetailResponse;\n const conn = json.connections?.[0];\n if (!conn) return null;\n if (conn.type === \"http\" || conn.type === \"ws\") {\n const deploymentUrl = conn.deploymentUrl ?? json.deploymentUrl;\n if (!deploymentUrl) return null;\n return { runtime: \"remote\", transport: \"streamable-http\", url: deploymentUrl };\n }\n if (conn.type === \"stdio\") {\n return {\n runtime: \"npm\",\n packageId: \"@smithery/cli\",\n transport: \"stdio\",\n extraArgs: [\"run\", qualifiedName],\n };\n }\n return null;\n}\n\nexport async function fetchSmitheryFirstPage(\n fetcher: typeof fetch = globalThis.fetch,\n): Promise<RegistryEntry[]> {\n const resp = await timeoutFetch(SMITHERY_REGISTRY_URL, fetcher);\n if (!resp.ok) throw new Error(`smithery HTTP ${resp.status}`);\n const json = (await resp.json()) as SmitheryResponse;\n const entries = (json.servers ?? [])\n .map(normalizeSmithery)\n .filter((x): x is RegistryEntry => x !== null);\n if (entries.length === 0) throw new Error(\"smithery returned no entries\");\n return entries;\n}\n\nexport function fallbackFromCatalog(): RegistryEntry[] {\n return MCP_CATALOG.map((e) => ({\n name: e.name,\n title: e.name,\n description: e.summary,\n source: \"local\" as const,\n install: {\n runtime: \"npm\" as const,\n packageId: e.package,\n transport: \"stdio\" as const,\n },\n }));\n}\n\nexport type FetchProgress = (info: {\n source: \"official\" | \"smithery\";\n page: number;\n entries: number;\n}) => void;\n\nexport interface FetchOptions {\n /** Force a network refresh even when cache is fresh. */\n noCache?: boolean;\n /** Override fetch — primarily for tests. */\n fetcher?: typeof fetch;\n /** Override cache file path — primarily for tests. */\n cachePath?: string;\n /** Skip the fallback chain and force a specific source. */\n preferSource?: \"official\" | \"smithery\" | \"local\";\n /** Progress callback — once per fetched page. */\n onProgress?: FetchProgress;\n}\n\nexport interface RegistryHandle {\n source: RegistrySource;\n /** Always present; mutated in place by loadMorePages. */\n cache: CacheFile;\n fromCache: boolean;\n fetchedAt: number;\n errors: string[];\n /** When source === \"official\", the path this handle persists to. Smithery + local are not persisted incrementally. */\n cachePath: string;\n}\n\nfunction newOfficialCache(initial: OfficialPageResult): CacheFile {\n const seen = new Map<string, RegistryEntry>();\n for (const e of initial.entries) if (!seen.has(e.name)) seen.set(e.name, e);\n return {\n schemaVersion: CACHE_SCHEMA_VERSION,\n fetchedAt: Date.now(),\n source: \"official\",\n entries: [...seen.values()],\n pagination: { pagesLoaded: 1, nextCursor: initial.nextCursor },\n };\n}\n\nfunction newStaticCache(source: RegistrySource, entries: RegistryEntry[]): CacheFile {\n return {\n schemaVersion: CACHE_SCHEMA_VERSION,\n fetchedAt: Date.now(),\n source,\n entries,\n pagination: { pagesLoaded: 1, nextCursor: null },\n };\n}\n\n/** Open the registry: returns a handle with at least one page loaded. Caller can advance via loadMorePages. */\nexport async function openRegistry(opts: FetchOptions = {}): Promise<RegistryHandle> {\n const fetcher = opts.fetcher ?? globalThis.fetch;\n const cachePath = opts.cachePath ?? defaultCachePath();\n const errors: string[] = [];\n\n if (!opts.noCache && !opts.preferSource) {\n const cached = readCache(cachePath);\n if (cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS && cached.entries.length > 0) {\n return {\n source: cached.source,\n cache: cached,\n fromCache: true,\n fetchedAt: cached.fetchedAt,\n errors: [],\n cachePath,\n };\n }\n }\n\n const tryOfficial = async (): Promise<RegistryHandle> => {\n const first = await fetchOfficialPage(null, fetcher);\n const cache = newOfficialCache(first);\n opts.onProgress?.({ source: \"official\", page: 1, entries: cache.entries.length });\n writeCache(cachePath, cache);\n return {\n source: \"official\",\n cache,\n fromCache: false,\n fetchedAt: cache.fetchedAt,\n errors,\n cachePath,\n };\n };\n\n const trySmithery = async (): Promise<RegistryHandle> => {\n const entries = await fetchSmitheryFirstPage(fetcher);\n const cache = newStaticCache(\"smithery\", entries);\n opts.onProgress?.({ source: \"smithery\", page: 1, entries: entries.length });\n writeCache(cachePath, cache);\n return {\n source: \"smithery\",\n cache,\n fromCache: false,\n fetchedAt: cache.fetchedAt,\n errors,\n cachePath,\n };\n };\n\n const tryLocal = (): RegistryHandle => {\n const cache = newStaticCache(\"local\", fallbackFromCatalog());\n return {\n source: \"local\",\n cache,\n fromCache: false,\n fetchedAt: cache.fetchedAt,\n errors,\n cachePath,\n };\n };\n\n if (opts.preferSource === \"local\") return tryLocal();\n if (opts.preferSource === \"smithery\") {\n try {\n return await trySmithery();\n } catch (e) {\n errors.push(`smithery: ${(e as Error).message}`);\n return tryLocal();\n }\n }\n\n try {\n return await tryOfficial();\n } catch (e) {\n errors.push(`official: ${(e as Error).message}`);\n }\n try {\n return await trySmithery();\n } catch (e) {\n errors.push(`smithery: ${(e as Error).message}`);\n }\n\n const stale = readCache(cachePath);\n if (stale) {\n return {\n source: stale.source,\n cache: stale,\n fromCache: true,\n fetchedAt: stale.fetchedAt,\n errors,\n cachePath,\n };\n }\n return tryLocal();\n}\n\nexport interface LoadMoreOptions {\n /** Number of additional pages to fetch (cap). Stops early when the source is exhausted. */\n pages?: number;\n /** Override fetch — primarily for tests. */\n fetcher?: typeof fetch;\n /** Stop early if filter() finds at least this many matching entries (across all loaded pages). */\n matchTarget?: number;\n /** Filter applied for matchTarget counting. */\n filter?: (e: RegistryEntry) => boolean;\n /** Progress callback. */\n onProgress?: FetchProgress;\n}\n\nexport interface LoadMoreResult {\n pagesAdded: number;\n newEntries: number;\n exhausted: boolean;\n}\n\n/** Advance an official-source handle by fetching more pages on demand. Smithery / local handles are no-ops. */\nexport async function loadMorePages(\n handle: RegistryHandle,\n opts: LoadMoreOptions = {},\n): Promise<LoadMoreResult> {\n if (handle.source !== \"official\") {\n return { pagesAdded: 0, newEntries: 0, exhausted: true };\n }\n const cache = handle.cache;\n if (cache.pagination.nextCursor === null) {\n return { pagesAdded: 0, newEntries: 0, exhausted: true };\n }\n\n const fetcher = opts.fetcher ?? globalThis.fetch;\n const limit = opts.pages ?? 1;\n const seen = new Set(cache.entries.map((e) => e.name));\n const matchCount = (): number => {\n if (!opts.filter) return 0;\n let n = 0;\n for (const e of cache.entries) if (opts.filter(e)) n++;\n return n;\n };\n\n let pagesAdded = 0;\n let newEntries = 0;\n for (let i = 0; i < limit; i++) {\n if (cache.pagination.nextCursor === null) break;\n if (opts.matchTarget !== undefined && matchCount() >= opts.matchTarget) break;\n const result = await fetchOfficialPage(cache.pagination.nextCursor, fetcher);\n for (const e of result.entries) {\n if (!seen.has(e.name)) {\n seen.add(e.name);\n cache.entries.push(e);\n newEntries++;\n }\n }\n cache.pagination.pagesLoaded += 1;\n cache.pagination.nextCursor = result.nextCursor;\n pagesAdded += 1;\n opts.onProgress?.({\n source: \"official\",\n page: cache.pagination.pagesLoaded,\n entries: cache.entries.length,\n });\n }\n\n if (pagesAdded > 0) writeCache(handle.cachePath, cache);\n return {\n pagesAdded,\n newEntries,\n exhausted: cache.pagination.nextCursor === null,\n };\n}\n\n/** Build a `--mcp`-format spec string from a registry install descriptor. */\nexport function specStringFor(name: string, install: RegistryInstall): string {\n const localName = name.split(\"/\").pop() ?? name;\n const safe = localName.replace(/[^a-zA-Z0-9_-]/g, \"-\").replace(/^-+|-+$/g, \"\") || \"mcp\";\n if (install.runtime === \"remote\") {\n if (!install.url) throw new Error(`remote install for ${name} has no URL`);\n if (install.transport === \"streamable-http\") return `${safe}=streamable+${install.url}`;\n return `${safe}=${install.url}`;\n }\n const trail = install.extraArgs?.length ? ` ${install.extraArgs.join(\" \")}` : \"\";\n if (install.runtime === \"npm\") {\n if (!install.packageId) throw new Error(`npm install for ${name} has no packageId`);\n const pinned = install.version ? `${install.packageId}@${install.version}` : install.packageId;\n return `${safe}=npx -y ${pinned}${trail}`;\n }\n if (install.runtime === \"pypi\") {\n if (!install.packageId) throw new Error(`pypi install for ${name} has no packageId`);\n return `${safe}=uvx ${install.packageId}${trail}`;\n }\n throw new Error(`unsupported install runtime: ${(install as RegistryInstall).runtime}`);\n}\n\n/** Re-exported for consumers that want a shape compatible with the old fetchRegistry result. */\nexport interface FetchResult {\n entries: RegistryEntry[];\n source: RegistrySource;\n fromCache: boolean;\n fetchedAt: number;\n errors: string[];\n /** Whether more pages are available beyond what's already loaded. */\n hasMore: boolean;\n}\n\nexport function handleToFetchResult(handle: RegistryHandle): FetchResult {\n return {\n entries: handle.cache.entries,\n source: handle.source,\n fromCache: handle.fromCache,\n fetchedAt: handle.fetchedAt,\n errors: handle.errors,\n hasMore: handle.cache.pagination.nextCursor !== null,\n };\n}\n"],"mappings":"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","names":[]}
|