@creeperhost/modlens-mcp 1.6.0
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/README.md +938 -0
- package/dist/access-flags.d.ts +58 -0
- package/dist/access-flags.d.ts.map +1 -0
- package/dist/access-flags.js +79 -0
- package/dist/access-flags.js.map +1 -0
- package/dist/access-flags.test.d.ts +2 -0
- package/dist/access-flags.test.d.ts.map +1 -0
- package/dist/access-flags.test.js +189 -0
- package/dist/access-flags.test.js.map +1 -0
- package/dist/batch-ingest.d.ts +2 -0
- package/dist/batch-ingest.d.ts.map +1 -0
- package/dist/batch-ingest.js +54 -0
- package/dist/batch-ingest.js.map +1 -0
- package/dist/batch-resolve-mixins.d.ts +2 -0
- package/dist/batch-resolve-mixins.d.ts.map +1 -0
- package/dist/batch-resolve-mixins.js +36 -0
- package/dist/batch-resolve-mixins.js.map +1 -0
- package/dist/cache.d.ts +16 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +36 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1318 -0
- package/dist/cli.js.map +1 -0
- package/dist/curseforge.d.ts +53 -0
- package/dist/curseforge.d.ts.map +1 -0
- package/dist/curseforge.js +104 -0
- package/dist/curseforge.js.map +1 -0
- package/dist/db-backend.d.ts +17 -0
- package/dist/db-backend.d.ts.map +1 -0
- package/dist/db-backend.js +40 -0
- package/dist/db-backend.js.map +1 -0
- package/dist/db.d.ts +11 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +55 -0
- package/dist/db.js.map +1 -0
- package/dist/embed-queue.d.ts +12 -0
- package/dist/embed-queue.d.ts.map +1 -0
- package/dist/embed-queue.js +103 -0
- package/dist/embed-queue.js.map +1 -0
- package/dist/embeddings.d.ts +21 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +55 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/env-path.d.ts +19 -0
- package/dist/env-path.d.ts.map +1 -0
- package/dist/env-path.js +40 -0
- package/dist/env-path.js.map +1 -0
- package/dist/fetch-utils.d.ts +24 -0
- package/dist/fetch-utils.d.ts.map +1 -0
- package/dist/fetch-utils.js +73 -0
- package/dist/fetch-utils.js.map +1 -0
- package/dist/fetch-utils.test.d.ts +2 -0
- package/dist/fetch-utils.test.d.ts.map +1 -0
- package/dist/fetch-utils.test.js +133 -0
- package/dist/fetch-utils.test.js.map +1 -0
- package/dist/generated/sqlite/browser.d.ts +55 -0
- package/dist/generated/sqlite/browser.d.ts.map +1 -0
- package/dist/generated/sqlite/browser.js +18 -0
- package/dist/generated/sqlite/browser.js.map +1 -0
- package/dist/generated/sqlite/client.d.ts +72 -0
- package/dist/generated/sqlite/client.d.ts.map +1 -0
- package/dist/generated/sqlite/client.js +33 -0
- package/dist/generated/sqlite/client.js.map +1 -0
- package/dist/generated/sqlite/commonInputTypes.d.ts +387 -0
- package/dist/generated/sqlite/commonInputTypes.d.ts.map +1 -0
- package/dist/generated/sqlite/commonInputTypes.js +11 -0
- package/dist/generated/sqlite/commonInputTypes.js.map +1 -0
- package/dist/generated/sqlite/enums.d.ts +2 -0
- package/dist/generated/sqlite/enums.d.ts.map +1 -0
- package/dist/generated/sqlite/enums.js +11 -0
- package/dist/generated/sqlite/enums.js.map +1 -0
- package/dist/generated/sqlite/internal/class.d.ts +226 -0
- package/dist/generated/sqlite/internal/class.d.ts.map +1 -0
- package/dist/generated/sqlite/internal/class.js +84 -0
- package/dist/generated/sqlite/internal/class.js.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespace.d.ts +1344 -0
- package/dist/generated/sqlite/internal/prismaNamespace.d.ts.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespace.js +220 -0
- package/dist/generated/sqlite/internal/prismaNamespace.js.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts +204 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.d.ts.map +1 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js +191 -0
- package/dist/generated/sqlite/internal/prismaNamespaceBrowser.js.map +1 -0
- package/dist/generated/sqlite/models/DocEntry.d.ts +1223 -0
- package/dist/generated/sqlite/models/DocEntry.d.ts.map +1 -0
- package/dist/generated/sqlite/models/DocEntry.js +2 -0
- package/dist/generated/sqlite/models/DocEntry.js.map +1 -0
- package/dist/generated/sqlite/models/McSourceFile.d.ts +1289 -0
- package/dist/generated/sqlite/models/McSourceFile.d.ts.map +1 -0
- package/dist/generated/sqlite/models/McSourceFile.js +2 -0
- package/dist/generated/sqlite/models/McSourceFile.js.map +1 -0
- package/dist/generated/sqlite/models/McVersion.d.ts +1315 -0
- package/dist/generated/sqlite/models/McVersion.d.ts.map +1 -0
- package/dist/generated/sqlite/models/McVersion.js +2 -0
- package/dist/generated/sqlite/models/McVersion.js.map +1 -0
- package/dist/generated/sqlite/models/McVersionDiff.d.ts +1061 -0
- package/dist/generated/sqlite/models/McVersionDiff.d.ts.map +1 -0
- package/dist/generated/sqlite/models/McVersionDiff.js +2 -0
- package/dist/generated/sqlite/models/McVersionDiff.js.map +1 -0
- package/dist/generated/sqlite/models/Mod.d.ts +2396 -0
- package/dist/generated/sqlite/models/Mod.d.ts.map +1 -0
- package/dist/generated/sqlite/models/Mod.js +2 -0
- package/dist/generated/sqlite/models/Mod.js.map +1 -0
- package/dist/generated/sqlite/models/ModClass.d.ts +1254 -0
- package/dist/generated/sqlite/models/ModClass.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModClass.js +2 -0
- package/dist/generated/sqlite/models/ModClass.js.map +1 -0
- package/dist/generated/sqlite/models/ModSourceFile.d.ts +1283 -0
- package/dist/generated/sqlite/models/ModSourceFile.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModSourceFile.js +2 -0
- package/dist/generated/sqlite/models/ModSourceFile.js.map +1 -0
- package/dist/generated/sqlite/models/ModTag.d.ts +1278 -0
- package/dist/generated/sqlite/models/ModTag.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModTag.js +2 -0
- package/dist/generated/sqlite/models/ModTag.js.map +1 -0
- package/dist/generated/sqlite/models/ModVersionDiff.d.ts +1073 -0
- package/dist/generated/sqlite/models/ModVersionDiff.d.ts.map +1 -0
- package/dist/generated/sqlite/models/ModVersionDiff.js +2 -0
- package/dist/generated/sqlite/models/ModVersionDiff.js.map +1 -0
- package/dist/generated/sqlite/models/Primer.d.ts +1319 -0
- package/dist/generated/sqlite/models/Primer.d.ts.map +1 -0
- package/dist/generated/sqlite/models/Primer.js +2 -0
- package/dist/generated/sqlite/models/Primer.js.map +1 -0
- package/dist/generated/sqlite/models.d.ts +12 -0
- package/dist/generated/sqlite/models.d.ts.map +1 -0
- package/dist/generated/sqlite/models.js +2 -0
- package/dist/generated/sqlite/models.js.map +1 -0
- package/dist/jar.d.ts +7 -0
- package/dist/jar.d.ts.map +1 -0
- package/dist/jar.js +52 -0
- package/dist/jar.js.map +1 -0
- package/dist/java-tools.d.ts +46 -0
- package/dist/java-tools.d.ts.map +1 -0
- package/dist/java-tools.js +263 -0
- package/dist/java-tools.js.map +1 -0
- package/dist/launcher.d.ts +3 -0
- package/dist/launcher.d.ts.map +1 -0
- package/dist/launcher.js +105 -0
- package/dist/launcher.js.map +1 -0
- package/dist/mappings.d.ts +95 -0
- package/dist/mappings.d.ts.map +1 -0
- package/dist/mappings.js +1094 -0
- package/dist/mappings.js.map +1 -0
- package/dist/mappings.test.d.ts +2 -0
- package/dist/mappings.test.d.ts.map +1 -0
- package/dist/mappings.test.js +161 -0
- package/dist/mappings.test.js.map +1 -0
- package/dist/minecraft.d.ts +21 -0
- package/dist/minecraft.d.ts.map +1 -0
- package/dist/minecraft.js +70 -0
- package/dist/minecraft.js.map +1 -0
- package/dist/modpacks-ch.d.ts +224 -0
- package/dist/modpacks-ch.d.ts.map +1 -0
- package/dist/modpacks-ch.js +146 -0
- package/dist/modpacks-ch.js.map +1 -0
- package/dist/modrinth.d.ts +67 -0
- package/dist/modrinth.d.ts.map +1 -0
- package/dist/modrinth.js +88 -0
- package/dist/modrinth.js.map +1 -0
- package/dist/platform-adapter.d.ts +23 -0
- package/dist/platform-adapter.d.ts.map +1 -0
- package/dist/platform-adapter.js +2 -0
- package/dist/platform-adapter.js.map +1 -0
- package/dist/platform.d.ts +47 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +175 -0
- package/dist/platform.js.map +1 -0
- package/dist/processor.d.ts +51 -0
- package/dist/processor.d.ts.map +1 -0
- package/dist/processor.js +655 -0
- package/dist/processor.js.map +1 -0
- package/dist/processor.test.d.ts +2 -0
- package/dist/processor.test.d.ts.map +1 -0
- package/dist/processor.test.js +629 -0
- package/dist/processor.test.js.map +1 -0
- package/dist/repositories/embeddings-sqlite.d.ts +38 -0
- package/dist/repositories/embeddings-sqlite.d.ts.map +1 -0
- package/dist/repositories/embeddings-sqlite.js +208 -0
- package/dist/repositories/embeddings-sqlite.js.map +1 -0
- package/dist/repositories/embeddings.d.ts +40 -0
- package/dist/repositories/embeddings.d.ts.map +1 -0
- package/dist/repositories/embeddings.js +136 -0
- package/dist/repositories/embeddings.js.map +1 -0
- package/dist/repositories/index.d.ts +2 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +15 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/mcVersion.d.ts +16 -0
- package/dist/repositories/mcVersion.d.ts.map +1 -0
- package/dist/repositories/mcVersion.js +52 -0
- package/dist/repositories/mcVersion.js.map +1 -0
- package/dist/repositories/mod.d.ts +241 -0
- package/dist/repositories/mod.d.ts.map +1 -0
- package/dist/repositories/mod.js +342 -0
- package/dist/repositories/mod.js.map +1 -0
- package/dist/repositories/packs.d.ts +44 -0
- package/dist/repositories/packs.d.ts.map +1 -0
- package/dist/repositories/packs.js +138 -0
- package/dist/repositories/packs.js.map +1 -0
- package/dist/search-adapter.d.ts +34 -0
- package/dist/search-adapter.d.ts.map +1 -0
- package/dist/search-adapter.js +195 -0
- package/dist/search-adapter.js.map +1 -0
- package/dist/search.d.ts +6 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +54 -0
- package/dist/search.js.map +1 -0
- package/dist/search.test.d.ts +2 -0
- package/dist/search.test.d.ts.map +1 -0
- package/dist/search.test.js +71 -0
- package/dist/search.test.js.map +1 -0
- package/dist/security.d.ts +98 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +446 -0
- package/dist/security.js.map +1 -0
- package/dist/security.test.d.ts +2 -0
- package/dist/security.test.d.ts.map +1 -0
- package/dist/security.test.js +687 -0
- package/dist/security.test.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1465 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +1113 -0
- package/dist/setup.js.map +1 -0
- package/dist/tools/bytecode.d.ts +129 -0
- package/dist/tools/bytecode.d.ts.map +1 -0
- package/dist/tools/bytecode.js +679 -0
- package/dist/tools/bytecode.js.map +1 -0
- package/dist/tools/catalog.d.ts +54 -0
- package/dist/tools/catalog.d.ts.map +1 -0
- package/dist/tools/catalog.js +249 -0
- package/dist/tools/catalog.js.map +1 -0
- package/dist/tools/compat-check.d.ts +23 -0
- package/dist/tools/compat-check.d.ts.map +1 -0
- package/dist/tools/compat-check.js +250 -0
- package/dist/tools/compat-check.js.map +1 -0
- package/dist/tools/compat-check.test.d.ts +2 -0
- package/dist/tools/compat-check.test.d.ts.map +1 -0
- package/dist/tools/compat-check.test.js +179 -0
- package/dist/tools/compat-check.test.js.map +1 -0
- package/dist/tools/diagnostics.d.ts +10 -0
- package/dist/tools/diagnostics.d.ts.map +1 -0
- package/dist/tools/diagnostics.js +133 -0
- package/dist/tools/diagnostics.js.map +1 -0
- package/dist/tools/diagnostics.test.d.ts +2 -0
- package/dist/tools/diagnostics.test.d.ts.map +1 -0
- package/dist/tools/diagnostics.test.js +168 -0
- package/dist/tools/diagnostics.test.js.map +1 -0
- package/dist/tools/docs.d.ts +19 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +230 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/embed-registry.d.ts +125 -0
- package/dist/tools/embed-registry.d.ts.map +1 -0
- package/dist/tools/embed-registry.js +560 -0
- package/dist/tools/embed-registry.js.map +1 -0
- package/dist/tools/gradle.d.ts +16 -0
- package/dist/tools/gradle.d.ts.map +1 -0
- package/dist/tools/gradle.js +182 -0
- package/dist/tools/gradle.js.map +1 -0
- package/dist/tools/graphify.d.ts +144 -0
- package/dist/tools/graphify.d.ts.map +1 -0
- package/dist/tools/graphify.js +798 -0
- package/dist/tools/graphify.js.map +1 -0
- package/dist/tools/graphify.test.d.ts +2 -0
- package/dist/tools/graphify.test.d.ts.map +1 -0
- package/dist/tools/graphify.test.js +39 -0
- package/dist/tools/graphify.test.js.map +1 -0
- package/dist/tools/ingest.d.ts +85 -0
- package/dist/tools/ingest.d.ts.map +1 -0
- package/dist/tools/ingest.js +477 -0
- package/dist/tools/ingest.js.map +1 -0
- package/dist/tools/ingest.test.d.ts +2 -0
- package/dist/tools/ingest.test.d.ts.map +1 -0
- package/dist/tools/ingest.test.js +340 -0
- package/dist/tools/ingest.test.js.map +1 -0
- package/dist/tools/kubejs.d.ts +37 -0
- package/dist/tools/kubejs.d.ts.map +1 -0
- package/dist/tools/kubejs.js +245 -0
- package/dist/tools/kubejs.js.map +1 -0
- package/dist/tools/mappings.d.ts +17 -0
- package/dist/tools/mappings.d.ts.map +1 -0
- package/dist/tools/mappings.js +85 -0
- package/dist/tools/mappings.js.map +1 -0
- package/dist/tools/mc-fts.d.ts +101 -0
- package/dist/tools/mc-fts.d.ts.map +1 -0
- package/dist/tools/mc-fts.js +279 -0
- package/dist/tools/mc-fts.js.map +1 -0
- package/dist/tools/mcmeta.d.ts +41 -0
- package/dist/tools/mcmeta.d.ts.map +1 -0
- package/dist/tools/mcmeta.js +365 -0
- package/dist/tools/mcmeta.js.map +1 -0
- package/dist/tools/mixin-scan.d.ts +113 -0
- package/dist/tools/mixin-scan.d.ts.map +1 -0
- package/dist/tools/mixin-scan.js +433 -0
- package/dist/tools/mixin-scan.js.map +1 -0
- package/dist/tools/mod-data.d.ts +83 -0
- package/dist/tools/mod-data.d.ts.map +1 -0
- package/dist/tools/mod-data.js +630 -0
- package/dist/tools/mod-data.js.map +1 -0
- package/dist/tools/mod-tags.d.ts +59 -0
- package/dist/tools/mod-tags.d.ts.map +1 -0
- package/dist/tools/mod-tags.js +279 -0
- package/dist/tools/mod-tags.js.map +1 -0
- package/dist/tools/mod-tags.test.d.ts +2 -0
- package/dist/tools/mod-tags.test.d.ts.map +1 -0
- package/dist/tools/mod-tags.test.js +75 -0
- package/dist/tools/mod-tags.test.js.map +1 -0
- package/dist/tools/modpacks-ch.d.ts +257 -0
- package/dist/tools/modpacks-ch.d.ts.map +1 -0
- package/dist/tools/modpacks-ch.js +516 -0
- package/dist/tools/modpacks-ch.js.map +1 -0
- package/dist/tools/packtools.d.ts +113 -0
- package/dist/tools/packtools.d.ts.map +1 -0
- package/dist/tools/packtools.js +809 -0
- package/dist/tools/packtools.js.map +1 -0
- package/dist/tools/packtools.test.d.ts +2 -0
- package/dist/tools/packtools.test.d.ts.map +1 -0
- package/dist/tools/packtools.test.js +99 -0
- package/dist/tools/packtools.test.js.map +1 -0
- package/dist/tools/platform.d.ts +68 -0
- package/dist/tools/platform.d.ts.map +1 -0
- package/dist/tools/platform.js +452 -0
- package/dist/tools/platform.js.map +1 -0
- package/dist/tools/primers.d.ts +36 -0
- package/dist/tools/primers.d.ts.map +1 -0
- package/dist/tools/primers.js +451 -0
- package/dist/tools/primers.js.map +1 -0
- package/dist/tools/reports.d.ts +19 -0
- package/dist/tools/reports.d.ts.map +1 -0
- package/dist/tools/reports.js +573 -0
- package/dist/tools/reports.js.map +1 -0
- package/dist/tools/source.d.ts +10 -0
- package/dist/tools/source.d.ts.map +1 -0
- package/dist/tools/source.js +101 -0
- package/dist/tools/source.js.map +1 -0
- package/dist/tools/vanilla-data.d.ts +127 -0
- package/dist/tools/vanilla-data.d.ts.map +1 -0
- package/dist/tools/vanilla-data.js +824 -0
- package/dist/tools/vanilla-data.js.map +1 -0
- package/dist/tools/vanilla.d.ts +171 -0
- package/dist/tools/vanilla.d.ts.map +1 -0
- package/dist/tools/vanilla.js +612 -0
- package/dist/tools/vanilla.js.map +1 -0
- package/dist/tools/version-diff.d.ts +113 -0
- package/dist/tools/version-diff.d.ts.map +1 -0
- package/dist/tools/version-diff.js +519 -0
- package/dist/tools/version-diff.js.map +1 -0
- package/dist/tools/version-diff.test.d.ts +2 -0
- package/dist/tools/version-diff.test.d.ts.map +1 -0
- package/dist/tools/version-diff.test.js +102 -0
- package/dist/tools/version-diff.test.js.map +1 -0
- package/dist/validate.d.ts +19 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +54 -0
- package/dist/validate.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +73 -0
- package/dist/validate.test.js.map +1 -0
- package/package.json +62 -0
- package/prisma/backends/schema.sqlite.prisma +215 -0
- package/prisma/backends/template.db +0 -0
- package/prisma/schema.prisma +303 -0
- package/scripts/backup.mjs +151 -0
- package/scripts/build-template-db.mjs +38 -0
- package/scripts/check-atm10.mjs +27 -0
- package/scripts/check-sync.mjs +13 -0
- package/scripts/create-fts-index.mjs +50 -0
- package/scripts/enable-pgvector.mjs +90 -0
- package/scripts/enable-sqlite-vec.mjs +158 -0
- package/scripts/migrate-backend.mjs +188 -0
- package/scripts/migrate-embed-provenance.mjs +80 -0
- package/scripts/migrate-metadata-source.mjs +62 -0
- package/scripts/migrate-mod-source-files.mjs +67 -0
- package/scripts/post-update.mjs +77 -0
- package/scripts/verify-atm10.mjs +63 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* modpacks.ch public API client.
|
|
3
|
+
*
|
|
4
|
+
* modpacks.ch is a service by CreeperHost (https://www.creeperhost.net).
|
|
5
|
+
* The API is freely accessible — no auth required.
|
|
6
|
+
* The modpacks.ch team requested a custom User-Agent for usage tracking.
|
|
7
|
+
*/
|
|
8
|
+
import { fetchWithRetry, DOWNLOAD_OPTS } from "./fetch-utils.js";
|
|
9
|
+
import { createWriteStream } from "fs";
|
|
10
|
+
import { pipeline } from "stream/promises";
|
|
11
|
+
export const FTBAPI = "https://api.modpacks.ch/public";
|
|
12
|
+
/** User-Agent as requested by the modpacks.ch (CreeperHost) team for usage tracking. */
|
|
13
|
+
export const USER_AGENT = "modlens-mcp/1.0 (github.com/CreeperHost/modlens-mcp)";
|
|
14
|
+
const HEADERS = { "User-Agent": USER_AGENT };
|
|
15
|
+
// ── API helpers ───────────────────────────────────────────────────────────────
|
|
16
|
+
async function get(path) {
|
|
17
|
+
const res = await fetchWithRetry(`${FTBAPI}/${path}`, { headers: HEADERS });
|
|
18
|
+
if (res.status === 404)
|
|
19
|
+
return null;
|
|
20
|
+
if (!res.ok)
|
|
21
|
+
throw new Error(`modpacks.ch API ${res.status} for /${path}`);
|
|
22
|
+
const text = await res.text();
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(text);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new Error(`modpacks.ch returned non-JSON for /${path}: ${text.slice(0, 200)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// ── Mod API ───────────────────────────────────────────────────────────────────
|
|
31
|
+
export async function searchMods(term, limit = 20) {
|
|
32
|
+
return get(`mod/search/${limit}?term=${encodeURIComponent(term)}`);
|
|
33
|
+
}
|
|
34
|
+
export async function getMod(id) {
|
|
35
|
+
return get(`mod/${id}`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Batch-fetch multiple mods by their IDs. Useful after a search to enrich
|
|
39
|
+
* result IDs into full mod objects. Runs requests in parallel.
|
|
40
|
+
*/
|
|
41
|
+
export async function getModsBatch(ids) {
|
|
42
|
+
const results = await Promise.allSettled(ids.map((id) => getMod(id)));
|
|
43
|
+
return results
|
|
44
|
+
.filter((r) => r.status === "fulfilled" && r.value !== null)
|
|
45
|
+
.map((r) => r.value);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve the download URL for a mod version.
|
|
49
|
+
* Some entries have url="" — in that case the CDN URL is constructed from
|
|
50
|
+
* the file ID using the same cfCdnUrl pattern as pack manifests.
|
|
51
|
+
*/
|
|
52
|
+
export function resolveModVersionUrl(version) {
|
|
53
|
+
if (version.url)
|
|
54
|
+
return version.url;
|
|
55
|
+
if (version.id)
|
|
56
|
+
return cfCdnUrl(version.id, version.name);
|
|
57
|
+
if (version.mirrors?.length)
|
|
58
|
+
return version.mirrors[0];
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
// ── Modpack API (FTB namespace) ───────────────────────────────────────────────
|
|
62
|
+
export async function searchPacks(term, limit = 20) {
|
|
63
|
+
return get(`modpack/search/${limit}?term=${encodeURIComponent(term)}`);
|
|
64
|
+
}
|
|
65
|
+
export async function getFeaturedPacks(limit = 20) {
|
|
66
|
+
return get(`modpack/featured/${limit}`);
|
|
67
|
+
}
|
|
68
|
+
export async function getPack(packId) {
|
|
69
|
+
return get(`modpack/${packId}`);
|
|
70
|
+
}
|
|
71
|
+
export async function getPackManifest(packId, versionId) {
|
|
72
|
+
return get(`modpack/${packId}/${versionId}`);
|
|
73
|
+
}
|
|
74
|
+
// ── CurseForge modpack API (no CF API key required) ───────────────────────────
|
|
75
|
+
// Mirrors the /modpack/ namespace but for CurseForge-hosted packs.
|
|
76
|
+
// provider field will be "curseforge" in all responses.
|
|
77
|
+
/**
|
|
78
|
+
* Search CurseForge packs via the unified FTB search endpoint.
|
|
79
|
+
* The /curseforge/search/ endpoint does NOT exist — CF packs are returned
|
|
80
|
+
* in the `curseforge` array of the main /modpack/search/ response.
|
|
81
|
+
*/
|
|
82
|
+
export async function searchCfPacks(term, limit = 20) {
|
|
83
|
+
return searchPacks(term, limit);
|
|
84
|
+
}
|
|
85
|
+
export async function getCfPack(packId) {
|
|
86
|
+
return get(`curseforge/${packId}`);
|
|
87
|
+
}
|
|
88
|
+
export async function getCfPackManifest(packId, versionId) {
|
|
89
|
+
return get(`curseforge/${packId}/${versionId}`);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build a direct CurseForge CDN download URL for a manifest file whose `url`
|
|
93
|
+
* is empty (CF packs return url: "" for mod-type files).
|
|
94
|
+
*
|
|
95
|
+
* Pattern: https://edge.forgecdn.net/files/{fileId÷1000}/{fileId%1000}/{name}
|
|
96
|
+
*/
|
|
97
|
+
export function cfCdnUrl(fileId, filename) {
|
|
98
|
+
const hi = Math.floor(fileId / 1000);
|
|
99
|
+
const lo = fileId % 1000;
|
|
100
|
+
return `https://edge.forgecdn.net/files/${hi}/${lo}/${encodeURIComponent(filename)}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolve the download URL for any manifest file, regardless of whether it
|
|
104
|
+
* comes from an FTB pack (direct URL) or a CurseForge pack (empty url →
|
|
105
|
+
* reconstruct from the embedded curseforge metadata).
|
|
106
|
+
*
|
|
107
|
+
* Returns null if the file type is not downloadable (e.g. "cf-extract"
|
|
108
|
+
* overrides ZIPs that have their own url should still be fine, this only
|
|
109
|
+
* returns null if there is genuinely no URL to construct).
|
|
110
|
+
*/
|
|
111
|
+
export function resolveFileUrl(file) {
|
|
112
|
+
if (file.url)
|
|
113
|
+
return file.url;
|
|
114
|
+
if (file.curseforge)
|
|
115
|
+
return cfCdnUrl(file.curseforge.file, file.name);
|
|
116
|
+
if (file.mirror)
|
|
117
|
+
return file.mirror;
|
|
118
|
+
// cf-extract overrides ZIPs use the version ID as their file ID
|
|
119
|
+
if (file.type === "cf-extract" && file.id)
|
|
120
|
+
return cfCdnUrl(file.id, file.name);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
// ── File download ─────────────────────────────────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* Download a single FTB/CF manifest file to a local destination path.
|
|
126
|
+
* Handles both FTB packs (direct CDN `url`) and CurseForge packs (empty `url`
|
|
127
|
+
* → reconstruct via cfCdnUrl from embedded curseforge metadata).
|
|
128
|
+
*/
|
|
129
|
+
export async function downloadManifestFile(file, destPath) {
|
|
130
|
+
const primary = resolveFileUrl(file);
|
|
131
|
+
if (!primary)
|
|
132
|
+
throw new Error(`No download URL for file ${file.name} (id ${file.id})`);
|
|
133
|
+
const attempt = async (url) => {
|
|
134
|
+
const res = await fetchWithRetry(url, { headers: HEADERS }, DOWNLOAD_OPTS);
|
|
135
|
+
return res;
|
|
136
|
+
};
|
|
137
|
+
let res = await attempt(primary);
|
|
138
|
+
if (!res.ok && file.mirror && file.mirror !== primary) {
|
|
139
|
+
res = await attempt(file.mirror);
|
|
140
|
+
}
|
|
141
|
+
if (!res.ok)
|
|
142
|
+
throw new Error(`Failed to download ${file.name}: HTTP ${res.status} from ${primary}`);
|
|
143
|
+
const writer = createWriteStream(destPath);
|
|
144
|
+
await pipeline(res.body, writer);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=modpacks-ch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modpacks-ch.js","sourceRoot":"","sources":["../src/modpacks-ch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { PlatformAdapter } from "./platform-adapter.js";
|
|
2
|
+
export interface ModrinthVersion {
|
|
3
|
+
id: string;
|
|
4
|
+
project_id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
version_number: string;
|
|
7
|
+
date_published: string;
|
|
8
|
+
downloads: number;
|
|
9
|
+
files: Array<{
|
|
10
|
+
url: string;
|
|
11
|
+
filename: string;
|
|
12
|
+
primary: boolean;
|
|
13
|
+
hashes: {
|
|
14
|
+
sha512: string;
|
|
15
|
+
};
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
export interface ModrinthProject {
|
|
19
|
+
id: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
title: string;
|
|
22
|
+
description: string;
|
|
23
|
+
source_url: string | null;
|
|
24
|
+
issues_url: string | null;
|
|
25
|
+
}
|
|
26
|
+
export declare function lookupBySha512(sha512: string): Promise<ModrinthVersion | null>;
|
|
27
|
+
export declare function getProject(projectId: string): Promise<ModrinthProject | null>;
|
|
28
|
+
export declare function getLatestVersion(projectId: string, mcVersion?: string): Promise<ModrinthVersion | null>;
|
|
29
|
+
export interface ModrinthSearchHit {
|
|
30
|
+
project_id: string;
|
|
31
|
+
slug: string;
|
|
32
|
+
title: string;
|
|
33
|
+
description: string;
|
|
34
|
+
categories: string[];
|
|
35
|
+
downloads: number;
|
|
36
|
+
follows: number;
|
|
37
|
+
latest_version: string;
|
|
38
|
+
versions: string[];
|
|
39
|
+
loaders: string[];
|
|
40
|
+
date_modified: string;
|
|
41
|
+
license: string;
|
|
42
|
+
project_type: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ModrinthSearchResult {
|
|
45
|
+
hits: ModrinthSearchHit[];
|
|
46
|
+
offset: number;
|
|
47
|
+
limit: number;
|
|
48
|
+
total_hits: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Search Modrinth by name/keyword, optionally filtered by loader and/or MC version.
|
|
52
|
+
*/
|
|
53
|
+
export declare function searchProjects(query: string, opts?: {
|
|
54
|
+
loader?: string;
|
|
55
|
+
mcVersion?: string;
|
|
56
|
+
limit?: number;
|
|
57
|
+
projectType?: string;
|
|
58
|
+
}): Promise<ModrinthSearchResult | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Get all versions for a project, optionally filtered by loader and/or MC version.
|
|
61
|
+
*/
|
|
62
|
+
export declare function getProjectVersions(projectId: string, opts?: {
|
|
63
|
+
loader?: string;
|
|
64
|
+
mcVersion?: string;
|
|
65
|
+
}): Promise<ModrinthVersion[]>;
|
|
66
|
+
export declare const modrinthPlatformAdapter: PlatformAdapter;
|
|
67
|
+
//# sourceMappingURL=modrinth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modrinth.d.ts","sourceRoot":"","sources":["../src/modrinth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAU7D,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;SAAE,CAAC;KAAE,CAAC,CAAC;CACnG;AAED,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAOpF;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAKnF;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAO7G;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACjC,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACzF,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CActC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACpC,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,OAAO,CAAC,eAAe,EAAE,CAAC,CAO5B;AAED,eAAO,MAAM,uBAAuB,EAAE,eAcrC,CAAC"}
|
package/dist/modrinth.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { fetchWithRetry, safeJson } from "./fetch-utils.js";
|
|
2
|
+
const MODRINTH_BASE = "https://api.modrinth.com/v2";
|
|
3
|
+
const token = process.env.MODRINTH_TOKEN ?? "";
|
|
4
|
+
const headers = {
|
|
5
|
+
"User-Agent": "modlens-mcp/1.0 (github.com/CreeperHost/modlens-mcp)",
|
|
6
|
+
...(token ? { Authorization: token } : {}),
|
|
7
|
+
};
|
|
8
|
+
export async function lookupBySha512(sha512) {
|
|
9
|
+
if (!/^[a-f0-9]{128}$/i.test(sha512))
|
|
10
|
+
throw new Error(`Invalid SHA-512 hash: expected 128 hex chars, got ${sha512.length} chars`);
|
|
11
|
+
const res = await fetchWithRetry(`${MODRINTH_BASE}/version_file/${sha512}?algorithm=sha512`, { headers });
|
|
12
|
+
if (res.status === 404)
|
|
13
|
+
return null;
|
|
14
|
+
if (!res.ok)
|
|
15
|
+
throw new Error(`Modrinth lookup failed: ${res.status}`);
|
|
16
|
+
return safeJson(res, "Modrinth version lookup");
|
|
17
|
+
}
|
|
18
|
+
export async function getProject(projectId) {
|
|
19
|
+
const res = await fetchWithRetry(`${MODRINTH_BASE}/project/${projectId}`, { headers });
|
|
20
|
+
if (res.status === 404)
|
|
21
|
+
return null;
|
|
22
|
+
if (!res.ok)
|
|
23
|
+
throw new Error(`Modrinth project fetch failed: ${res.status}`);
|
|
24
|
+
return safeJson(res, "Modrinth project");
|
|
25
|
+
}
|
|
26
|
+
export async function getLatestVersion(projectId, mcVersion) {
|
|
27
|
+
const params = new URLSearchParams({ loaders: '["fabric","neoforge","forge","quilt"]' });
|
|
28
|
+
if (mcVersion)
|
|
29
|
+
params.set("game_versions", JSON.stringify([mcVersion]));
|
|
30
|
+
const res = await fetchWithRetry(`${MODRINTH_BASE}/project/${projectId}/version?${params}`, { headers });
|
|
31
|
+
if (!res.ok)
|
|
32
|
+
return null;
|
|
33
|
+
const versions = await safeJson(res, "Modrinth versions");
|
|
34
|
+
return versions[0] ?? null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Search Modrinth by name/keyword, optionally filtered by loader and/or MC version.
|
|
38
|
+
*/
|
|
39
|
+
export async function searchProjects(query, opts = {}) {
|
|
40
|
+
const facets = [["project_type:mod"]];
|
|
41
|
+
if (opts.loader)
|
|
42
|
+
facets.push([`categories:${opts.loader}`]);
|
|
43
|
+
if (opts.mcVersion)
|
|
44
|
+
facets.push([`versions:${opts.mcVersion}`]);
|
|
45
|
+
if (opts.projectType)
|
|
46
|
+
facets[0] = [`project_type:${opts.projectType}`];
|
|
47
|
+
const params = new URLSearchParams({
|
|
48
|
+
query,
|
|
49
|
+
limit: String(opts.limit ?? 20),
|
|
50
|
+
facets: JSON.stringify(facets),
|
|
51
|
+
});
|
|
52
|
+
const res = await fetchWithRetry(`${MODRINTH_BASE}/search?${params}`, { headers });
|
|
53
|
+
if (!res.ok)
|
|
54
|
+
return null;
|
|
55
|
+
return safeJson(res, "Modrinth search");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get all versions for a project, optionally filtered by loader and/or MC version.
|
|
59
|
+
*/
|
|
60
|
+
export async function getProjectVersions(projectId, opts = {}) {
|
|
61
|
+
const params = new URLSearchParams();
|
|
62
|
+
if (opts.loader)
|
|
63
|
+
params.set("loaders", JSON.stringify([opts.loader]));
|
|
64
|
+
if (opts.mcVersion)
|
|
65
|
+
params.set("game_versions", JSON.stringify([opts.mcVersion]));
|
|
66
|
+
const res = await fetchWithRetry(`${MODRINTH_BASE}/project/${projectId}/version?${params}`, { headers });
|
|
67
|
+
if (!res.ok)
|
|
68
|
+
return [];
|
|
69
|
+
return safeJson(res, "Modrinth project versions");
|
|
70
|
+
}
|
|
71
|
+
export const modrinthPlatformAdapter = {
|
|
72
|
+
name: "modrinth",
|
|
73
|
+
async lookup({ sha512 }) {
|
|
74
|
+
if (!sha512)
|
|
75
|
+
return null;
|
|
76
|
+
const ver = await lookupBySha512(sha512).catch(() => null);
|
|
77
|
+
if (!ver)
|
|
78
|
+
return null;
|
|
79
|
+
const proj = await getProject(ver.project_id).catch(() => null);
|
|
80
|
+
return {
|
|
81
|
+
platform: "modrinth",
|
|
82
|
+
projectId: ver.project_id,
|
|
83
|
+
slug: proj?.slug,
|
|
84
|
+
sourceUrl: proj?.source_url,
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=modrinth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modrinth.js","sourceRoot":"","sources":["../src/modrinth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Hashes available for a mod JAR at ingest time. */
|
|
2
|
+
export type JarHashes = {
|
|
3
|
+
sha512: string | null;
|
|
4
|
+
murmur2: string | null;
|
|
5
|
+
};
|
|
6
|
+
/** Result from a successful platform lookup. */
|
|
7
|
+
export type PlatformHit = {
|
|
8
|
+
platform: "modrinth";
|
|
9
|
+
projectId: string;
|
|
10
|
+
slug?: string;
|
|
11
|
+
sourceUrl?: string | null;
|
|
12
|
+
} | {
|
|
13
|
+
platform: "curseforge";
|
|
14
|
+
projectId: number;
|
|
15
|
+
slug?: string;
|
|
16
|
+
sourceUrl?: string;
|
|
17
|
+
};
|
|
18
|
+
/** An adapter that can identify a mod JAR on one platform. */
|
|
19
|
+
export type PlatformAdapter = {
|
|
20
|
+
name: string;
|
|
21
|
+
lookup: (hashes: JarHashes) => Promise<PlatformHit | null>;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=platform-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-adapter.d.ts","sourceRoot":"","sources":["../src/platform-adapter.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG;IACpB,MAAM,EAAG,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,gDAAgD;AAChD,MAAM,MAAM,WAAW,GACjB;IAAE,QAAQ,EAAE,UAAU,CAAC;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACvF;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF,8DAA8D;AAC9D,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC9D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-adapter.js","sourceRoot":"","sources":["../src/platform-adapter.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface MCVersion {
|
|
2
|
+
id: string;
|
|
3
|
+
type: "release" | "snapshot" | "old_beta" | "old_alpha";
|
|
4
|
+
releaseTime: string;
|
|
5
|
+
}
|
|
6
|
+
export interface NeoForgeVersion {
|
|
7
|
+
version: string;
|
|
8
|
+
mcVersion: string;
|
|
9
|
+
}
|
|
10
|
+
export interface FabricApiVersion {
|
|
11
|
+
version: string;
|
|
12
|
+
mcVersion: string;
|
|
13
|
+
datePublished: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ForgeVersion {
|
|
16
|
+
/** Full artifact version, e.g. "1.20.1-47.3.22" */
|
|
17
|
+
fullVersion: string;
|
|
18
|
+
/** Forge build version, e.g. "47.3.22" */
|
|
19
|
+
version: string;
|
|
20
|
+
/** Minecraft version, e.g. "1.20.1" */
|
|
21
|
+
mcVersion: string;
|
|
22
|
+
/** Whether this is the recommended build */
|
|
23
|
+
recommended?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function listMcVersions(type?: "release" | "snapshot" | "all"): Promise<MCVersion[]>;
|
|
26
|
+
export declare function listNeoForgeVersions(mcVersion?: string, limit?: number): Promise<NeoForgeVersion[]>;
|
|
27
|
+
export declare function listFabricApiVersions(mcVersion?: string, limit?: number): Promise<FabricApiVersion[]>;
|
|
28
|
+
export declare function listForgeVersions(mcVersion?: string, limit?: number): Promise<ForgeVersion[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Download the NeoForge universal JAR for a given version.
|
|
31
|
+
* Version format: "21.1.228" (maps to MC 1.21.1).
|
|
32
|
+
* Returns the local JAR path.
|
|
33
|
+
*/
|
|
34
|
+
export declare function downloadNeoForge(version: string): Promise<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Download the Forge universal JAR for a given version.
|
|
37
|
+
* Version format: "1.20.1-47.3.22" (full artifact version) or just "47.3.22" with mcVersion.
|
|
38
|
+
* Returns the local JAR path.
|
|
39
|
+
*/
|
|
40
|
+
export declare function downloadForge(version: string, mcVersion?: string): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Download the Fabric API JAR for a given version from Modrinth.
|
|
43
|
+
* Version format: "0.116.11+1.21.1".
|
|
44
|
+
* Returns the local JAR path.
|
|
45
|
+
*/
|
|
46
|
+
export declare function downloadFabricApi(version: string): Promise<string>;
|
|
47
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;IACxD,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IACzB,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAMD,wBAAsB,cAAc,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAahG;AAED,wBAAsB,oBAAoB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAqBrG;AAED,wBAAsB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoBvG;AAED,wBAAsB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAmD/F;AAYD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIvE;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUxF;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBxE"}
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { createWriteStream } from "fs";
|
|
2
|
+
import { pipeline } from "stream/promises";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { CACHE_ROOT, ensureDir, exists } from "./cache.js";
|
|
5
|
+
import { LEGACY_SRG_VERSIONS, LEGACY_RETROMCP_VERSIONS } from "./minecraft.js";
|
|
6
|
+
const PISTON_META = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json";
|
|
7
|
+
const NEOFORGE_MAVEN = "https://maven.neoforged.net/releases/net/neoforged/neoforge";
|
|
8
|
+
const NEOFORGE_META = "https://maven.neoforged.net/api/maven/versions/releases/net/neoforged/neoforge";
|
|
9
|
+
const FORGE_MAVEN = "https://maven.minecraftforge.net/net/minecraftforge/forge";
|
|
10
|
+
const FORGE_PROMOS = "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json";
|
|
11
|
+
let mcCache = null;
|
|
12
|
+
let neoforgeCache = null;
|
|
13
|
+
let forgeCache = null;
|
|
14
|
+
export async function listMcVersions(type) {
|
|
15
|
+
if (!mcCache) {
|
|
16
|
+
const res = await fetch(PISTON_META);
|
|
17
|
+
if (!res.ok)
|
|
18
|
+
throw new Error(`Failed to fetch MC versions: ${res.status}`);
|
|
19
|
+
const data = await res.json();
|
|
20
|
+
mcCache = data.versions.filter((v) => v.type !== "old_beta" && v.type !== "old_alpha" &&
|
|
21
|
+
(new Date(v.releaseTime) >= new Date("2019-04-23") || LEGACY_SRG_VERSIONS.has(v.id) || LEGACY_RETROMCP_VERSIONS.has(v.id)));
|
|
22
|
+
}
|
|
23
|
+
if (!type || type === "all")
|
|
24
|
+
return mcCache;
|
|
25
|
+
if (type === "release")
|
|
26
|
+
return mcCache.filter((v) => v.type === "release");
|
|
27
|
+
return mcCache.filter((v) => v.type === "snapshot");
|
|
28
|
+
}
|
|
29
|
+
export async function listNeoForgeVersions(mcVersion, limit = 20) {
|
|
30
|
+
if (!neoforgeCache) {
|
|
31
|
+
const res = await fetch(NEOFORGE_META);
|
|
32
|
+
if (!res.ok)
|
|
33
|
+
throw new Error(`Failed to fetch NeoForge versions: ${res.status}`);
|
|
34
|
+
const data = await res.json();
|
|
35
|
+
// NeoForge versions look like "21.1.0", "21.1.1", etc. — leading number = MC major
|
|
36
|
+
neoforgeCache = data.versions
|
|
37
|
+
.filter((v) => /^\d+\.\d+\.\d+/.test(v))
|
|
38
|
+
.map((v) => {
|
|
39
|
+
const parts = v.split(".");
|
|
40
|
+
const mcVersion = `1.${parts[0]}.${parts[1]}`;
|
|
41
|
+
return { version: v, mcVersion };
|
|
42
|
+
})
|
|
43
|
+
.reverse(); // newest first
|
|
44
|
+
}
|
|
45
|
+
const filtered = mcVersion
|
|
46
|
+
? neoforgeCache.filter((v) => v.mcVersion === mcVersion || v.mcVersion.startsWith(mcVersion))
|
|
47
|
+
: neoforgeCache;
|
|
48
|
+
return filtered.slice(0, limit);
|
|
49
|
+
}
|
|
50
|
+
export async function listFabricApiVersions(mcVersion, limit = 20) {
|
|
51
|
+
// Fabric API project on Modrinth: P7dR8mSH
|
|
52
|
+
const url = mcVersion
|
|
53
|
+
? `https://api.modrinth.com/v2/project/P7dR8mSH/version?game_versions=%5B%22${encodeURIComponent(mcVersion)}%22%5D&loaders=%5B%22fabric%22%5D`
|
|
54
|
+
: `https://api.modrinth.com/v2/project/P7dR8mSH/version?loaders=%5B%22fabric%22%5D`;
|
|
55
|
+
const res = await fetch(url, { headers: { "User-Agent": "modlens-mcp/1.0" } });
|
|
56
|
+
if (!res.ok)
|
|
57
|
+
throw new Error(`Failed to fetch Fabric API versions: ${res.status}`);
|
|
58
|
+
const versions = await res.json();
|
|
59
|
+
return versions.slice(0, limit).map((v) => ({
|
|
60
|
+
version: v.version_number,
|
|
61
|
+
mcVersion: v.game_versions[0] ?? "unknown",
|
|
62
|
+
datePublished: v.date_published,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
export async function listForgeVersions(mcVersion, limit = 20) {
|
|
66
|
+
if (!forgeCache) {
|
|
67
|
+
// Fetch promotions to know which versions are recommended
|
|
68
|
+
const promoRes = await fetch(FORGE_PROMOS, { headers: { "User-Agent": "modlens-mcp/1.0" } });
|
|
69
|
+
const recommendedSet = new Set();
|
|
70
|
+
if (promoRes.ok) {
|
|
71
|
+
const promoData = await promoRes.json();
|
|
72
|
+
for (const [key, ver] of Object.entries(promoData.promos)) {
|
|
73
|
+
if (key.endsWith("-recommended")) {
|
|
74
|
+
const mc = key.replace("-recommended", "");
|
|
75
|
+
recommendedSet.add(`${mc}-${ver}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Fetch Maven metadata for full version list
|
|
80
|
+
const metaRes = await fetch(`${FORGE_MAVEN}/maven-metadata.xml`, { headers: { "User-Agent": "modlens-mcp/1.0" } });
|
|
81
|
+
if (!metaRes.ok)
|
|
82
|
+
throw new Error(`Failed to fetch Forge versions: ${metaRes.status}`);
|
|
83
|
+
const xml = await metaRes.text();
|
|
84
|
+
// Parse <version> tags from XML
|
|
85
|
+
const versionRegex = /<version>([^<]+)<\/version>/g;
|
|
86
|
+
const allVersions = [];
|
|
87
|
+
let match;
|
|
88
|
+
while ((match = versionRegex.exec(xml)) !== null) {
|
|
89
|
+
const fullVersion = match[1];
|
|
90
|
+
// Format: "mcVersion-forgeVersion" (e.g. "1.20.1-47.3.22")
|
|
91
|
+
// Some old ones: "1.7.10-10.13.4.1614-1.7.10" (MC version appended twice)
|
|
92
|
+
const dashIdx = fullVersion.indexOf("-");
|
|
93
|
+
if (dashIdx === -1)
|
|
94
|
+
continue;
|
|
95
|
+
const mc = fullVersion.substring(0, dashIdx);
|
|
96
|
+
// Strip trailing "-mcVersion" suffix from old Forge versions
|
|
97
|
+
let forgeVer = fullVersion.substring(dashIdx + 1);
|
|
98
|
+
if (forgeVer.endsWith(`-${mc}`)) {
|
|
99
|
+
forgeVer = forgeVer.substring(0, forgeVer.length - mc.length - 1);
|
|
100
|
+
}
|
|
101
|
+
allVersions.push({
|
|
102
|
+
fullVersion,
|
|
103
|
+
version: forgeVer,
|
|
104
|
+
mcVersion: mc,
|
|
105
|
+
recommended: recommendedSet.has(fullVersion),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
forgeCache = allVersions.reverse(); // newest first
|
|
109
|
+
}
|
|
110
|
+
const filtered = mcVersion
|
|
111
|
+
? forgeCache.filter((v) => v.mcVersion === mcVersion || v.mcVersion.startsWith(mcVersion))
|
|
112
|
+
: forgeCache;
|
|
113
|
+
return filtered.slice(0, limit);
|
|
114
|
+
}
|
|
115
|
+
async function downloadJar(url, destPath) {
|
|
116
|
+
await ensureDir(destPath);
|
|
117
|
+
if (await exists(destPath))
|
|
118
|
+
return destPath;
|
|
119
|
+
const res = await fetch(url, { headers: { "User-Agent": "modlens-mcp/1.0" } });
|
|
120
|
+
if (!res.ok)
|
|
121
|
+
throw new Error(`Download failed (${res.status}): ${url}`);
|
|
122
|
+
const writer = createWriteStream(destPath);
|
|
123
|
+
await pipeline(res.body, writer);
|
|
124
|
+
return destPath;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Download the NeoForge universal JAR for a given version.
|
|
128
|
+
* Version format: "21.1.228" (maps to MC 1.21.1).
|
|
129
|
+
* Returns the local JAR path.
|
|
130
|
+
*/
|
|
131
|
+
export async function downloadNeoForge(version) {
|
|
132
|
+
const destPath = join(CACHE_ROOT, "loaders", "neoforge", `neoforge-${version}-universal.jar`);
|
|
133
|
+
const url = `${NEOFORGE_MAVEN}/${version}/neoforge-${version}-universal.jar`;
|
|
134
|
+
return downloadJar(url, destPath);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Download the Forge universal JAR for a given version.
|
|
138
|
+
* Version format: "1.20.1-47.3.22" (full artifact version) or just "47.3.22" with mcVersion.
|
|
139
|
+
* Returns the local JAR path.
|
|
140
|
+
*/
|
|
141
|
+
export async function downloadForge(version, mcVersion) {
|
|
142
|
+
let fullVersion = version;
|
|
143
|
+
// If user only provided the Forge build number (no dash), we need mcVersion to construct the full version
|
|
144
|
+
if (!version.includes("-")) {
|
|
145
|
+
if (!mcVersion)
|
|
146
|
+
throw new Error("Forge download requires either full version (e.g. 1.20.1-47.3.22) or version + mcVersion");
|
|
147
|
+
fullVersion = `${mcVersion}-${version}`;
|
|
148
|
+
}
|
|
149
|
+
const destPath = join(CACHE_ROOT, "loaders", "forge", `forge-${fullVersion}-universal.jar`);
|
|
150
|
+
const url = `${FORGE_MAVEN}/${fullVersion}/forge-${fullVersion}-universal.jar`;
|
|
151
|
+
return downloadJar(url, destPath);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Download the Fabric API JAR for a given version from Modrinth.
|
|
155
|
+
* Version format: "0.116.11+1.21.1".
|
|
156
|
+
* Returns the local JAR path.
|
|
157
|
+
*/
|
|
158
|
+
export async function downloadFabricApi(version) {
|
|
159
|
+
const destPath = join(CACHE_ROOT, "loaders", "fabric-api", `fabric-api-${version}.jar`);
|
|
160
|
+
if (await exists(destPath))
|
|
161
|
+
return destPath;
|
|
162
|
+
// Fetch the version file list from Modrinth
|
|
163
|
+
const res = await fetch(`https://api.modrinth.com/v2/project/P7dR8mSH/version?loaders=%5B%22fabric%22%5D`, { headers: { "User-Agent": "modlens-mcp/1.0" } });
|
|
164
|
+
if (!res.ok)
|
|
165
|
+
throw new Error(`Modrinth lookup failed: ${res.status}`);
|
|
166
|
+
const versions = await res.json();
|
|
167
|
+
const match = versions.find((v) => v.version_number === version);
|
|
168
|
+
if (!match)
|
|
169
|
+
throw new Error(`Fabric API version "${version}" not found on Modrinth`);
|
|
170
|
+
const file = match.files.find((f) => f.primary) ?? match.files[0];
|
|
171
|
+
if (!file)
|
|
172
|
+
throw new Error(`No download file found for Fabric API ${version}`);
|
|
173
|
+
return downloadJar(file.url, destPath);
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import AdmZip from "adm-zip";
|
|
2
|
+
export type MetadataSource = "fabric.mod.json" | "quilt.mod.json" | "mods.toml" | "mcmod.info" | "@Mod annotation" | "filename";
|
|
3
|
+
/** Higher = better quality metadata. Used to decide whether re-parse upgrades an existing record. */
|
|
4
|
+
export declare const METADATA_QUALITY: Record<MetadataSource, number>;
|
|
5
|
+
export interface ParsedManifest {
|
|
6
|
+
modId: string;
|
|
7
|
+
displayName: string;
|
|
8
|
+
version: string;
|
|
9
|
+
mcVersion: string;
|
|
10
|
+
loader: "fabric" | "neoforge" | "forge" | "quilt" | "unknown";
|
|
11
|
+
description: string;
|
|
12
|
+
sourceUrl: string | null;
|
|
13
|
+
dependencies: Array<{
|
|
14
|
+
id: string;
|
|
15
|
+
version: string;
|
|
16
|
+
required: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
mixinConfigs: string[];
|
|
19
|
+
hasMixins: boolean;
|
|
20
|
+
hasAt: boolean;
|
|
21
|
+
hasAw: boolean;
|
|
22
|
+
atEntries: string[];
|
|
23
|
+
awEntries: string[];
|
|
24
|
+
mixinTargets: string[];
|
|
25
|
+
metadataSource: MetadataSource;
|
|
26
|
+
}
|
|
27
|
+
export declare function parseJar(jarPath: string): Promise<ParsedManifest>;
|
|
28
|
+
interface ForgeModAnnotationResult {
|
|
29
|
+
modId: string;
|
|
30
|
+
name: string;
|
|
31
|
+
version: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Scan class entries in a JAR for the Forge @Mod annotation.
|
|
35
|
+
* Parses the constant pool and RuntimeVisibleAnnotations attribute
|
|
36
|
+
* to extract modid/name/version without requiring javap.
|
|
37
|
+
*/
|
|
38
|
+
export declare function extractForgeModAnnotation(zip: AdmZip): ForgeModAnnotationResult | null;
|
|
39
|
+
/** Parse a single .class file's bytes for a Forge @Mod annotation. */
|
|
40
|
+
export declare function parseClassForModAnnotation(buf: Buffer): ForgeModAnnotationResult | null;
|
|
41
|
+
export declare function parseAtEntries(content: string): string[];
|
|
42
|
+
export declare function parseAwEntries(content: string): string[];
|
|
43
|
+
export declare function computeHashes(jarPath: string): Promise<{
|
|
44
|
+
sha256: string;
|
|
45
|
+
sha512: string;
|
|
46
|
+
murmur2: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** CurseForge Murmur2 hash — matches CF API fingerprint (whitespace-normalized). */
|
|
49
|
+
export declare function computeMurmur2(data: Buffer): number;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=processor.d.ts.map
|